Product-law layer: domain invariants + product model (Domain & Product agents)#97
Merged
Conversation
…ugh the pipeline Phase 1 foundations for product-level rule synthesis: - rule_kinds.py: register domain_invariant kind + inv-/der- id-prefix map - _common.py normalize: coerce product_model (dict) + domain_invariants/ derived_invariants/unenforced_invariants (lists), preserving content - finalize.py: reset the Wave-2 product sections on full re-run (--from 5 redo-safety); domain_invariants (Wave 1) intentionally preserved - merge.py is section-agnostic (generic deep_merge) — no change needed - golden fixture + pipeline tests (generic invented domain, no test-bed data) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t-laws markdown Phase 2 (consumers, Python side): - step-6-rule-synthesis.md: domain_invariant kind, 2 coverage rows (domain_invariants/derived_invariants), severity policy (stated->block, derived->warn, promotion gate), entity+category dedup with domain_invariant as canonical carrier, and explicit exclusion of product_model + unenforced_invariants from rule sources. Quality-over-quantity quota reframe. - renderer.py: product-model.md (domain map) + product-laws.md (two tiers: enforced/grounded vs unverified/ungrounded with searched proof-of-work); Product Laws summary + links in AGENTS.md. domain_invariant enforcement rules group into by-topic/ for free via rule_kinds. - CLI viewer.py needs no change — serves the whole blueprint to the React app. - Tests: renderer two-tier output, gap-never-in-grounded, step-6 contract, domain_invariant round-trip (extract_output -> classify -> index). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…eport Phase 2 (consumers, React side — shared by the local viewer and the share report): - ReportSections.tsx: ProductModelSection (domain map), ProductLawsSection (grounded tier: domain_invariants + derived_invariants with resolved premise links + enforced-at citations), UnverifiedInvariantsSection (distinct amber 'unverified' surface, per-card warning badge, searched[] list for falsifiability). Grounded vs ungrounded drawn unmistakably. - ReportPage.tsx: pull the four bp sections (guarded), render between trade-offs and guidelines, register nav + scroll-spy ids. - fixPrompt.ts: resolve a derived law's derived_from back to its premises. - Mirrored to archie/assets/viewer + npm-package/assets/viewer (verify_sync). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…product laws Phase 3 (producers + dispatch wiring): - step-3-wave1/domain-agent.md: observes product correctness laws (cite-or-omit, 7-category taxonomy, self-discovered entities, test-read exception); emits domain_invariants. step-5d-product.md: reasons over them to emit product_model + derived_invariants (>=2-anchor derivation guardrail) + unenforced_invariants (the gap list, required searched proof-of-work, never a rule). - Wave 1: Data and Domain now ALWAYS spawn (only UI Layer is optional) — per policy that the fact-gathering agents must not be gated on a heuristic; a no-data repo just yields empty arrays. Updates orchestration, dispatch table, timing keys, comprehensive line, incremental emit list, step-4 merge. - Wave 2: Product is the 4th reasoning agent, gated on domain_invariants being non-empty (driven by Domain's actual output, not a heuristic). finalize lists the product file unconditionally (warns+skips when absent). Design now links decisions to the laws they preserve (forced_by/enables); Risk turns laws into pitfalls. Single-model-per-wave preserved (Codex-safe). - Mirrored to npm-package; verify_sync + full suite (800) green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…trip test Phase 5 hardening: - CLAUDE.md: Wave 1 (Data+Domain always, UI optional), Wave 2 (4 agents incl Product), blueprint data model lists the product-law sections + which are enforced vs informational. - integration test: Wave-1 domain_invariants + Wave-2 product sub-file flow through finalize() into blueprint.json + rendered product-laws.md (both tiers). - Full suite 801 green; verify_sync green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adversarial validation of the feature surfaced three real gaps (now fixed +
guarded by tests):
- step-6: enforced_at entries are file:line citations, not globs — the prompt
now tells the agent to strip :line and broaden to a dir glob when deriving
triggers.path_glob, else the hook trigger silently never matches.
- step-5: the Product spawn gate ('domain_invariants non-empty') had no concrete
evaluation mechanism for the orchestrator — added an explicit DOMAIN_LAW_COUNT
python -c check (auto-approved form), mirroring the telemetry count pattern.
- step-5: Product now runs in FULL mode only. derived_invariants/unenforced are
global reasoning, not per-change deltas; a patch merge would append duplicate
ids on a changed law. Incremental keeps observed domain_invariants fresh
(Wave 1); the reasoned layer refreshes on the next full scan.
Verified clean: hook enforces domain_invariant rules via severity_class
(kind-agnostic, blocks/warns + surfaces forced_by/enables/alternative); viewer
bundle passes the whole blueprint; viewer tsc --noEmit exit 0. Suite 803 green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Three independent reviewers (wiring, python-correctness, intent/parity) audited the branch. Fixes for what they found: - BLOCKER (incremental): merge.py --patch now upserts domain_invariants/ derived_invariants/unenforced_invariants by `id` (keep patch version). Without this, an incremental scan re-emitting a changed law APPENDED a duplicate id (deep_merge dedups by `name`; these are id-keyed). Regression test added. - MAJOR (docs): orchestration.md had stale 'as applicable' + 'sub5 absent when has_persistence_signal == false' wording that contradicted the always-run change. Fixed the dispatch-model line, the timing-fold enumeration (was missing Domain), and the no-op example. - MINOR (renderer): AGENTS.md product-laws summary no longer emits a dangling header on a derived-only blueprint (lists derived laws too); 'N more' count is computed from what was shown (correct under --comprehensive); empty-invariant entries are skipped instead of rendering '- ****'. Regression tests added. Verified non-issues by the reviewers: field-name consistency across agents/ renderer/viewer, gap-list never a rule, parity (single-model-per-wave), depth caps reach both agents, zero test-bed leakage in new lines, viewer tsc exit 0. Suite 806 green; verify_sync green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…in_role The Domain agent over-indexed on densely-guarded subsystems (monetization/auth): laws cluster where guard code is dense, not where product value lives. Fix: - Domain agent: anchor to the product's PRIMARY VALUE WORKFLOW first; tag every law with domain_role (core | supporting | platform); mine the core's data-flow / computation invariants (not just guards) so the core isn't starved; in default depth, core has NO cap while supporting subsystems are rationed to ~2-3 each and platform to ~1-2. COMPREHENSIVE depth lifts ALL caps (no suppression) per user directive. - Product agent: derived_invariants inherit domain_role from their anchors. - renderer: product-laws.md groups the grounded tier by role (Core first, then Supporting, then Platform), with a flat fallback for blueprints predating the field; AGENTS.md summary sorts core-first so the capped list leads with core. - web viewer (ProductLawsSection): same role grouping + flat fallback. - Tests: role-grouping order, flat fallback, domain-agent distribution prompt. Suite 809 green; verify_sync green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s, new Product menu
Per user feedback on the Product Model screen:
- Drop product_model.entities everywhere (prompt + renderer + viewer) — the Data
Models section already inventories models in detail; entities here were noise.
- product_model.summary is now a detailed 3-6 sentence product description
(prompt change), rendered as prose, not a cramped pill.
- core_workflow is now [{title, description}] (was bare strings) — rendered as
numbered titled cards in the viewer and numbered titled steps in product-model.md;
both renderer and viewer accept the legacy string shape for backward compat.
- Viewer: new sidebar group 'PRODUCT' (Product Overview, Product Laws, Unverified
Gaps) moved out of DESIGN; 'Product Model' renamed 'Product Overview'.
- Tests updated for the new shape + a legacy-string compat test. 889 green; sync clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ty removal
The Product agent under-complied last run: it emitted core_workflow as plain
strings (rendered as fake 'Step N') and still emitted entities, despite the
prompt. Confirmed via timing the new prompt WAS used — so this is agent
under-compliance, not a stale prompt.
- normalize: deterministically strip product_model.entities — guarantees entities
never render regardless of agent compliance (Data Models is the canonical
inventory).
- step-5d prompt: hard, contrastive STRICT block — core_workflow items are
OBJECTS {title,description}, NEVER bare strings (with wrong/right example).
- viewer: legacy string steps render description-only (no fabricated 'Step N').
- tests updated; 894 green; sync clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…iour, not code Two conceptual corrections from user feedback: - Archie runs on libraries/SDKs/services/CLIs too, not just end-user apps. The Domain + Product agents now first classify what the repo IS and frame the core + workflow accordingly: app=user journey, library=consumer call path, service=request lifecycle, CLI=invocation->effect. summary + core_workflow generalized to capability/consumer language. - Product Laws were reading as engineering notes (e.g. 'getLocationType() maps CURRENT_POSITION_HOME_ID -> POSITION'). New behavioural-altitude rule: the invariant SENTENCE must state product behaviour a user/consumer relies on, understandable without the source; function/enum/class internals move to enforced_at/evidence. Wrong/right contrast uses the exact reported example. Applied to both observed (Domain) and derived (Product) laws. Pure prompt/altitude change; effect materializes on next re-scan. 896 green; sync clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ule' Per user feedback: don't define the law-altitude rule by negation against 'engineering' — frame it positively about the product. Reworded the Domain + Product agent guidance to lead with what a law SHOULD be (a product rule: what the product guarantees for its user/consumer, in the domain's own words, that a product owner would recognise) and let the enforcing code live in enforced_at/evidence. Dropped all 'not engineering' / 'not code mechanics' phrasing. Step-lint now asserts the prompt contains no 'engineering' wording. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… in summary Prose alone failed to keep code out of the law sentence (3rd try) — so apply the structural fix that worked for the workflow shape: give the code its own field. - Domain + Product law schema: new 'mechanism' field. invariant = the product rule (product concepts only, no function/constant names); mechanism = how the code enforces it. The product-rule guidance now points all code detail there. - renderer: mechanism renders as a secondary 'How it's enforced:' line under each law (observed + derived). - viewer: mechanism shown de-emphasized under each law card; AND the Product Overview summary + workflow descriptions now render inline markdown via a local renderInlineMd helper (fixes literal '**BabyWeather**' asterisks). - fixture + tests cover mechanism render + the schema field. 896 green; sync clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…width, lead) The summary rendered as one dense full-width block. Now: split on blank lines into paragraphs (max-w-2xl reading column, ~65ch), first paragraph emphasized as a lead, the rest muted body — each still through renderInlineMd for bold/code. Prompt nudged to write the summary as 2-4 short blank-line-separated paragraphs so future scans are naturally scannable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…de leak) Replace 'weatherHourly[selectedHourIdx]' (a real identifier from the test repo) with a generic 'items[selectedIndex]' placeholder in the Domain agent prompt. No test-bed specifics in committed Archie artifacts.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
gbrbks
added a commit
that referenced
this pull request
Jun 11, 2026
Product-law layer (PR #97): domain invariants + product model — Domain (Wave 1) and Product (Wave 2) agents, domain_invariant rules, two-tier product-laws + Product viewer section. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a product-law layer to
/archie-deep-scanso the generated rules capture what the product must do, not just how the code is shaped. Two new agents, a new rule kind, three new blueprint sections, and a Product section in the viewer.domain_invariants), cite-or-omit. States each law as a product rule (what the product guarantees) with the code-level how in a separatemechanismfield. Tags each lawdomain_role(core / supporting / platform) and rations supporting subsystems so monetization/auth code can't crowd out the core.product_model(a product overview + value workflow),derived_invariants(reasoned laws, ≥2-anchor derivation), andunenforced_invariants(an advisory, clearly-labeled gap list — never enforced).domain_invariantrule kind (Step 6): observed laws →decision_violation(block), derived →tradeoff_undermined(warn). Enforced by the existing severity-gated hook, no hook change.product-laws.md(two tiers: grounded vsproduct-model.md; a new PRODUCT menu group in the viewer (Product Overview, Product Laws, Unverified Gaps) with the grounded/ungrounded distinction drawn identically across markdown and UI.Works on apps, libraries/SDKs, services, and CLIs (the agents classify the repo type and frame the core workflow accordingly). Data agent is now always-on alongside Domain (only the UI Layer agent is optional).
Why
Prior rules were deep but structural ("wrap an adapter in a transaction", "where files live") — none captured product correctness. This layer adds the missing tier: grounded, accurately-cited product laws (balance never negative, idempotent ingest, immutable issued records, tenant scoping, etc.).
Validation
Iteratively validated against a real codebase: laws verified accurate against source, distribution flipped core-first (subscription rationed), workflow renders as titled steps, entities deduplicated against Data Models, summary readable. 896 tests pass;
verify_syncclean; CC + Codex parity preserved (single-model-per-wave); comprehensive mode lifts all caps.Notes
mechanismfield + behavioral-altitude framing land on the next scan (prompt-driven); structure and rendering are in place.🤖 Generated with Claude Code