hatch3r 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/cli/index.js +77 -19
- package/dist/content/agents/hatch3r-brownfield-spec.md +1 -1
- package/dist/content/agents/hatch3r-fixer.md +21 -8
- package/dist/content/agents/hatch3r-handoff-loader.md +7 -2
- package/dist/content/agents/hatch3r-handoff-preparer.md +5 -16
- package/dist/content/agents/hatch3r-implementer.md +29 -3
- package/dist/content/agents/hatch3r-maintainability.md +2 -0
- package/dist/content/agents/hatch3r-researcher.md +1 -1
- package/dist/content/agents/hatch3r-reviewer.md +21 -13
- package/dist/content/agents/hatch3r-ui.md +1 -1
- package/dist/content/agents/hatch3r-ux.md +1 -1
- package/dist/content/agents/shared/cq-specialist-roster.md +2 -2
- package/dist/content/agents/shared/efficiency-patterns.md +1 -1
- package/dist/content/agents/shared/quality-charter.md +6 -5
- package/dist/content/agents/shared/quality-specialist-frame.md +1 -1
- package/dist/content/agents/shared/severity-mapping.md +1 -1
- package/dist/content/agents/shared/triage-vocabulary.md +1 -1
- package/dist/content/agents/shared/user-content-templates.md +1 -1
- package/dist/content/agents/shared/user-question-protocol.md +4 -3
- package/dist/content/checks/code-quality.md +11 -0
- package/dist/content/checks/security.md +5 -0
- package/dist/content/checks/testing.md +2 -0
- package/dist/content/commands/board/pickup-delegation-multi.md +18 -8
- package/dist/content/commands/board/pickup-delegation.md +5 -4
- package/dist/content/commands/hatch3r-api-spec.md +5 -17
- package/dist/content/commands/hatch3r-auth-scaffold.md +7 -20
- package/dist/content/commands/hatch3r-benchmark.md +5 -17
- package/dist/content/commands/hatch3r-board-fill.md +6 -18
- package/dist/content/commands/hatch3r-board-pickup.md +8 -19
- package/dist/content/commands/hatch3r-bug-pipeline.md +4 -16
- package/dist/content/commands/hatch3r-bug-plan.md +5 -17
- package/dist/content/commands/hatch3r-codebase-map.md +5 -17
- package/dist/content/commands/hatch3r-create.md +5 -17
- package/dist/content/commands/hatch3r-debug.md +5 -17
- package/dist/content/commands/hatch3r-design-system-create.md +254 -0
- package/dist/content/commands/hatch3r-diagnose.md +10 -18
- package/dist/content/commands/hatch3r-feature-plan.md +5 -17
- package/dist/content/commands/hatch3r-handoff.md +5 -17
- package/dist/content/commands/hatch3r-healthcheck.md +5 -17
- package/dist/content/commands/hatch3r-incident-response.md +3 -15
- package/dist/content/commands/hatch3r-migration-plan.md +5 -17
- package/dist/content/commands/hatch3r-onboard.md +6 -18
- package/dist/content/commands/hatch3r-pack-install.md +6 -29
- package/dist/content/commands/hatch3r-pr-resolve.md +77 -79
- package/dist/content/commands/hatch3r-project-spec.md +5 -17
- package/dist/content/commands/hatch3r-quick-change.md +5 -17
- package/dist/content/commands/hatch3r-refactor-plan.md +5 -17
- package/dist/content/commands/hatch3r-release.md +6 -16
- package/dist/content/commands/hatch3r-revision.md +11 -23
- package/dist/content/commands/hatch3r-roadmap.md +5 -17
- package/dist/content/commands/hatch3r-security-audit.md +5 -17
- package/dist/content/commands/hatch3r-slo-scaffold.md +8 -20
- package/dist/content/commands/hatch3r-spec.md +11 -16
- package/dist/content/commands/hatch3r-test-plan.md +5 -17
- package/dist/content/commands/hatch3r-workflow.md +16 -26
- package/dist/content/commands/revision/revision-quality.md +6 -5
- package/dist/content/commands/shared/orchestration-frame.md +2 -2
- package/dist/content/rules/hatch3r-agent-orchestration-detail.md +2 -2
- package/dist/content/rules/hatch3r-agent-orchestration-detail.mdc +2 -2
- package/dist/content/rules/hatch3r-agent-orchestration.md +15 -15
- package/dist/content/rules/hatch3r-agent-orchestration.mdc +15 -15
- package/dist/content/rules/hatch3r-anti-duplication.md +15 -4
- package/dist/content/rules/hatch3r-anti-duplication.mdc +15 -4
- package/dist/content/rules/hatch3r-clarification-default.md +8 -7
- package/dist/content/rules/hatch3r-clarification-default.mdc +8 -7
- package/dist/content/rules/hatch3r-code-standards.md +1 -1
- package/dist/content/rules/hatch3r-code-standards.mdc +1 -1
- package/dist/content/rules/hatch3r-contract-census.md +160 -0
- package/dist/content/rules/hatch3r-contract-census.mdc +160 -0
- package/dist/content/rules/hatch3r-cost-visibility.md +11 -4
- package/dist/content/rules/hatch3r-cost-visibility.mdc +11 -4
- package/dist/content/rules/hatch3r-deep-context.md +1 -0
- package/dist/content/rules/hatch3r-deep-context.mdc +1 -0
- package/dist/content/rules/hatch3r-dynamic-stack-verification.md +114 -0
- package/dist/content/rules/hatch3r-dynamic-stack-verification.mdc +109 -0
- package/dist/content/rules/hatch3r-enhancability.md +1 -1
- package/dist/content/rules/hatch3r-enhancability.mdc +1 -1
- package/dist/content/rules/hatch3r-findings-ledger.md +129 -0
- package/dist/content/rules/hatch3r-findings-ledger.mdc +129 -0
- package/dist/content/rules/hatch3r-handoff-readiness.md +1 -1
- package/dist/content/rules/hatch3r-handoff-readiness.mdc +1 -1
- package/dist/content/rules/hatch3r-i18n.md +4 -0
- package/dist/content/rules/hatch3r-i18n.mdc +4 -0
- package/dist/content/rules/hatch3r-iteration-summary.md +47 -49
- package/dist/content/rules/hatch3r-iteration-summary.mdc +47 -49
- package/dist/content/rules/hatch3r-learning-system.md +6 -6
- package/dist/content/rules/hatch3r-learning-system.mdc +6 -6
- package/dist/content/rules/hatch3r-migrations.md +1 -1
- package/dist/content/rules/hatch3r-migrations.mdc +1 -1
- package/dist/content/rules/hatch3r-reviewer-calibration.md +2 -2
- package/dist/content/rules/hatch3r-reviewer-calibration.mdc +2 -2
- package/dist/content/rules/hatch3r-security-patterns.md +4 -0
- package/dist/content/rules/hatch3r-security-patterns.mdc +4 -0
- package/dist/content/rules/hatch3r-testing.md +14 -0
- package/dist/content/rules/hatch3r-testing.mdc +14 -0
- package/dist/content/rules/hatch3r-tool-currency.md +1 -1
- package/dist/content/rules/hatch3r-tool-currency.mdc +1 -1
- package/dist/content/skills/hatch3r-adhoc-orchestrate/SKILL.md +1 -1
- package/dist/content/skills/hatch3r-design-system-detect/SKILL.md +2 -0
- package/dist/content/skills/hatch3r-handoff-prepare/SKILL.md +4 -4
- package/dist/content/skills/hatch3r-report/SKILL.md +1 -1
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
id: hatch3r-clarification-default
|
|
3
3
|
type: rule
|
|
4
|
-
description: "P8 B1 floor: every hatch3r-invoked agentic workflow detects and resolves ambiguity via the platform-native question tool BEFORE executing — default behavior, not exception-driven. Names the
|
|
4
|
+
description: "P8 B1 floor: every hatch3r-invoked agentic workflow detects and resolves ambiguity via the platform-native question tool BEFORE executing — default behavior, not exception-driven. Names the 5-trigger set and mandates a §0 ambiguity gate on every mutating agent, command, and skill."
|
|
5
5
|
tags: [orchestration, floor:protocol]
|
|
6
6
|
alwaysApply: true
|
|
7
7
|
precedence: high
|
|
@@ -20,7 +20,7 @@ Canonical reference for the *how* of asking: `agents/shared/user-question-protoc
|
|
|
20
20
|
|
|
21
21
|
Default-path, not exception: a workflow that proceeds without resolving a live trigger below has violated B1, even if it later succeeds. Asking is the baseline; silent assumption is the deviation that must be justified.
|
|
22
22
|
|
|
23
|
-
##
|
|
23
|
+
## Five-trigger set
|
|
24
24
|
|
|
25
25
|
Apply the protocol before any write-tool invocation when ANY of these hold:
|
|
26
26
|
|
|
@@ -28,17 +28,18 @@ Apply the protocol before any write-tool invocation when ANY of these hold:
|
|
|
28
28
|
2. **Multiple valid interpretations** — two or more viable approaches with materially different cost, scope, or risk.
|
|
29
29
|
3. **Irreversible action** — deleting an artifact, renaming a public artifact id, dropping a frontmatter field, force-pushing a branch.
|
|
30
30
|
4. **Missing acceptance criteria** — no testable definition of done for the requested change.
|
|
31
|
+
5. **Unattested product decision** — the change destroys or transforms user data, or alters user-visible behavior beyond stated acceptance criteria, with no user statement authorizing it; an agent-authored comment or PR sentence is self-certification, not authorization.
|
|
31
32
|
|
|
32
|
-
If none of the
|
|
33
|
+
If none of the five hold and the safer default is obvious and reversible, proceed and note the default — do not manufacture a question (anti-pattern per `agents/shared/user-question-protocol.md` "Echo-as-question").
|
|
33
34
|
|
|
34
35
|
## §0 ambiguity gate (every mutating artifact)
|
|
35
36
|
|
|
36
37
|
Every artifact under `agents/`, `commands/`, and `skills/` that can mutate files MUST carry a §0 (or "Step 0 — Ambiguity gate") block as its first procedural step. The block:
|
|
37
38
|
|
|
38
|
-
- scans the request against the
|
|
39
|
+
- scans the request against the five-trigger set above before any write;
|
|
39
40
|
- on a live trigger, asks via the platform-native question tool per `agents/shared/user-question-protocol.md` and awaits the answer before proceeding;
|
|
40
41
|
- declares the default-if-no-response option so the workflow never deadlocks;
|
|
41
|
-
- on a non-response, wires the central deadlock-break: apply the declared default AND log it in Iteration Summary
|
|
42
|
+
- on a non-response, wires the central deadlock-break: apply the declared default AND log it in the Iteration Summary via the `Default applied:` exception line (orchestrator path), OR return Status `BLOCKED_AMBIGUITY` when no default line was emitted (sub-agent / authoring-bug path) — never silent-pick, per `agents/shared/user-question-protocol.md` → Operationalising Default-if-no-Response.
|
|
42
43
|
|
|
43
44
|
A mutating artifact with no §0 ambiguity gate, or one whose gate does not reference `agents/shared/user-question-protocol.md`, is a P8 B1 finding (D05 prompt-engineering audit, D13 human-AI collaboration audit).
|
|
44
45
|
|
|
@@ -46,7 +47,7 @@ A mutating artifact with no §0 ambiguity gate, or one whose gate does not refer
|
|
|
46
47
|
|
|
47
48
|
Use the platform-native question tool per `agents/shared/user-question-protocol.md`. One question per turn; bundle related sub-questions into a single multiple-choice prompt; supply 2–4 numbered options with one-line trade-offs; declare the default-if-no-response option. When no native tool exists on the runtime platform, use the Plain-Text Fallback Template from the same protocol.
|
|
48
49
|
|
|
49
|
-
When an ASK goes unanswered, the default-if-no-response contract owns the outcome — silent-picking is never permitted. The workflow MUST take exactly one of two paths: (a) apply the declared default AND log a `Default applied: <q> → option <N> (<reason>)` line in Iteration Summary
|
|
50
|
+
When an ASK goes unanswered, the default-if-no-response contract owns the outcome — silent-picking is never permitted. The workflow MUST take exactly one of two paths: (a) apply the declared default AND log a `Default applied: <q> → option <N> (<reason>)` line in the Iteration Summary — the `Default applied:` exception line, a registered line of the recap contract (`rules/hatch3r-iteration-summary.md` → Exception Lines — the catching gate that makes the default audit-visible); or (b) if no `Default if no response:` line was emitted with the question (an authoring bug), return Status `BLOCKED_AMBIGUITY` (`agents/shared/quality-charter.md` §17) instead of guessing. An applied default with no Default-applied line is a P8 B1 gate failure. This default-handling contract is operationalised in `agents/shared/user-question-protocol.md` → Operationalising Default-if-no-Response; runtime emission of the `Default applied:` line is interpreted markdown the orchestrator produces, so static gates cannot verify it fired — D05/D13 audit-cycle spot checks plus the per-run Iteration Summary validation gate enforce it.
|
|
50
51
|
|
|
51
52
|
## Scope
|
|
52
53
|
|
|
@@ -54,7 +55,7 @@ Binds every hatch3r-invoked workflow that mutates artifacts in the end-user repo
|
|
|
54
55
|
|
|
55
56
|
## Confidence-floor calibration (D13-SA13.3-F13.3.3)
|
|
56
57
|
|
|
57
|
-
The
|
|
58
|
+
The five-trigger set above is the floor for *scope/intent* ambiguity. Orthogonally, the `--confidence-floor=any|medium|high` flag (and the persisted `hatch3r config confidence_floor=...` default) calibrates a *result-confidence* ASK surface in the core orchestrators (`hatch3r-workflow`, `hatch3r-board-pickup`, `hatch3r-quick-change`, `hatch3r-revision`). At floor `high`, the orchestrator ASKs the user on every low-confidence finding regardless of severity — an additional, user-selected ASK trigger layered on top of the always-on five-trigger set. The floor never relaxes the five triggers; it only adds ASK pressure on uncertain results. Per P1 maturity tier (Decision 16): solo defaults `any`, enterprise defaults `high`.
|
|
58
59
|
|
|
59
60
|
## Exemptions (D5-M5)
|
|
60
61
|
|
|
@@ -93,7 +93,7 @@ When working in a monorepo (multiple packages or apps in a single repository):
|
|
|
93
93
|
|
|
94
94
|
- Remove unused imports, variables, functions, and type definitions immediately. Do not comment them out "for later."
|
|
95
95
|
- Use the compiler's unused-symbol diagnostics (e.g., TypeScript `noUnusedLocals`/`noUnusedParameters`, Go `go vet`, Rust `dead_code`) and the linter (`no-unused-vars` or equivalent) to catch dead code automatically.
|
|
96
|
-
- After removing a feature or completing a refactor, search for all references to the removed code. Delete orphaned tests, fixtures, and documentation.
|
|
96
|
+
- After removing a feature or completing a refactor, search for all references to the removed code. Delete orphaned tests, fixtures, and documentation. Exception — façade contract-hold: while a dropped or renamed shared-contract field is inside its compatibility window (`rules/hatch3r-contract-census.md` → Façade Contract-Hold), the nulled field behind the façade and its guarded consumer reads are NOT dead code; run this reference sweep at the contract phase, when the held field is deleted.
|
|
97
97
|
- Feature-flagged code that has been fully rolled out (flag removed) must have the flag-off branch deleted in the same PR.
|
|
98
98
|
- Commented-out code is never acceptable in committed code. Use version control history to retrieve old implementations.
|
|
99
99
|
|
|
@@ -88,7 +88,7 @@ When working in a monorepo (multiple packages or apps in a single repository):
|
|
|
88
88
|
|
|
89
89
|
- Remove unused imports, variables, functions, and type definitions immediately. Do not comment them out "for later."
|
|
90
90
|
- Use the compiler's unused-symbol diagnostics (e.g., TypeScript `noUnusedLocals`/`noUnusedParameters`, Go `go vet`, Rust `dead_code`) and the linter (`no-unused-vars` or equivalent) to catch dead code automatically.
|
|
91
|
-
- After removing a feature or completing a refactor, search for all references to the removed code. Delete orphaned tests, fixtures, and documentation.
|
|
91
|
+
- After removing a feature or completing a refactor, search for all references to the removed code. Delete orphaned tests, fixtures, and documentation. Exception — façade contract-hold: while a dropped or renamed shared-contract field is inside its compatibility window (`rules/hatch3r-contract-census.md` → Façade Contract-Hold), the nulled field behind the façade and its guarded consumer reads are NOT dead code; run this reference sweep at the contract phase, when the held field is deleted.
|
|
92
92
|
- Feature-flagged code that has been fully rolled out (flag removed) must have the flag-off branch deleted in the same PR.
|
|
93
93
|
- Commented-out code is never acceptable in committed code. Use version control history to retrieve old implementations.
|
|
94
94
|
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: hatch3r-contract-census
|
|
3
|
+
type: rule
|
|
4
|
+
description: Shared-contract discipline for brownfield changes — contract taxonomy, repo-wide consumer census as lane-exit gate, seam-owner protocol for parallel lanes, façade contract-hold on field drop/rename, value-drift census for shared constants.
|
|
5
|
+
tags: [implementation, review, orchestration, ctx:brownfield-only]
|
|
6
|
+
precedence: high
|
|
7
|
+
scope: always
|
|
8
|
+
---
|
|
9
|
+
# hatch3r Contract Census
|
|
10
|
+
|
|
11
|
+
**Pillars:** P2 (Scientific & Practical Quality), P8 (Clarification & Fan-out Discipline), CQ8 (Maintainability Quality)
|
|
12
|
+
|
|
13
|
+
## Binding Condition
|
|
14
|
+
|
|
15
|
+
This rule binds any diff that mutates a contract in the Shared-Contract Taxonomy below, in a repo where that contract has existing consumers. A change touching no taxonomy class exits with `Consumer census: N/A (no shared-contract change)`. A greenfield-new contract with zero consumers exits trivially — the census grep returns nothing and reports `clean`.
|
|
16
|
+
|
|
17
|
+
The failure class this rule closes: parallel file-disjoint lanes silently breaking a shared runtime contract — a renamed persisted collection, a changed store symbol, a dropped wire field — that no quality gate and, in a no-static-types stack, no compiler checks. File disjointness is not contract disjointness: two lanes whose diffs share zero files still collide when both touch the same contract.
|
|
18
|
+
|
|
19
|
+
## Shared-Contract Taxonomy
|
|
20
|
+
|
|
21
|
+
Seven contract classes. Each line states why file-disjointness does not protect it.
|
|
22
|
+
|
|
23
|
+
- **(a) Exported symbol** — function, class, or store: its name, signature, or subpath. Importers live in other files by definition. (researcher: `api_signature` for signature changes, `public_interface` for name/visibility/subpath changes)
|
|
24
|
+
- **(b) Persisted collection/table/field name** — string-typed: writer and reader each spell the string independently; no compiler links them. (researcher: `data_migration`)
|
|
25
|
+
- **(c) Client↔server wire field** — a JSON key crossing the network: serializer and deserializer sit in different trees, often different languages. (researcher: `type_shape`)
|
|
26
|
+
- **(d) Event name + payload schema** — emitter and subscribers are decoupled by design; the bus hides the seam. (researcher: `event_schema`)
|
|
27
|
+
- **(e) Shared constant** — rate, default, threshold, or enum value: copies compile independently, and a stale copy computes wrong values with no error. (researcher: `type_shape` for enum members, `cli_contract` for surfaced defaults; value-only drift sits below the researcher's radar → §Value-Drift Census)
|
|
28
|
+
- **(f) CLI flag / config / env key** — the producer is code; the consumers are shell scripts, CI YAML, and dotfiles no type-checker loads. (researcher: `cli_contract`)
|
|
29
|
+
- **(g) Type or schema shape where no checker is authoritative** — plain JS, dynamic access, JSON blobs: shape agreement exists only by convention, so classes (a)-(f) all degrade to grep.
|
|
30
|
+
|
|
31
|
+
The parenthesized categories map classes (a)-(f) onto the researcher's breaking-change vocabulary — `api_signature / type_shape / event_schema / public_interface / data_migration / cli_contract` (`agents/hatch3r-researcher.md` → Full-Mode Breaking-Change Detection) — so a researcher Breaking Change Candidates row converts directly into a taxonomy class and back.
|
|
32
|
+
|
|
33
|
+
## Consumer Census
|
|
34
|
+
|
|
35
|
+
**Trigger:** any taxonomy mutation — rename, removal, re-signature, revalue, key add/drop.
|
|
36
|
+
|
|
37
|
+
**Procedure:**
|
|
38
|
+
|
|
39
|
+
1. Repo-wide grep of the OLD identifier AND the NEW identifier. Never limit the grep to the lane's `affectedFiles` — consumers live outside the lane's file set by definition.
|
|
40
|
+
2. Per-class patterns:
|
|
41
|
+
- **String contracts** (classes b, d, f) — grep the quoted forms: `'name'` and `"name"` (plus template-literal and heredoc forms where the language has them).
|
|
42
|
+
- **Wire fields** (class c) — grep BOTH the client and server trees, plus fixtures, mocks, and recorded payloads: a test fixture still asserting the old key is an unreconciled consumer.
|
|
43
|
+
- **Constants** (class e) — grep the NAME and the literal VALUE; an independent copy defines the value without the name.
|
|
44
|
+
- **Infra/config** (class f) — include non-code files: CI YAML, Dockerfiles, `.env*`, deploy manifests.
|
|
45
|
+
3. Narrowing tactics for short identifiers that over-match: qualified member access (`\.field\b`), collection-prefixed forms (`users.field`), and quoted-literal-only matches.
|
|
46
|
+
|
|
47
|
+
**Reconciled** — a consumer counts as reconciled when it is updated to the new shape in this diff, OR reads through a guard added in this diff (façade-hold null-guard), OR is justified by name. Exactly three justifications are valid:
|
|
48
|
+
|
|
49
|
+
1. Consumer owned by another lane's seam — name the lane/issue.
|
|
50
|
+
2. Dead code with a linked deletion.
|
|
51
|
+
3. Dynamic/reflective access grep cannot resolve — name the mechanism, add a runtime guard.
|
|
52
|
+
|
|
53
|
+
**Output grammar** — the census field emits exactly one of:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
Consumer census: clean | reconciled(N) | N unreconciled — justification | N/A (no shared-contract change)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
- `clean` — the grep found zero consumers of the old shape outside this diff.
|
|
60
|
+
- `reconciled(N)` — N consumers found; every one updated, guarded, or justified by name.
|
|
61
|
+
- `N unreconciled — justification` — N consumers not yet updated or guarded; each carries one of the three justifications above. `unreconciled` WITHOUT a named justification caps the producing agent's Status at PARTIAL — done is declared from grep evidence, not assumed (the large-scale-change discipline of *Software Engineering at Google* ch. 22).
|
|
62
|
+
- `N/A (no shared-contract change)` — the diff touches no taxonomy class.
|
|
63
|
+
|
|
64
|
+
**Spec-time seed:** when a brownfield spec exists, its Integration-Surface consumer inventory (`agents/hatch3r-brownfield-spec.md` → Integration-Surface Analysis) seeds the grep list. The lane still re-runs the grep at lane exit: parallel lanes may have added consumers since spec time.
|
|
65
|
+
|
|
66
|
+
**Where it runs:** `agents/hatch3r-implementer.md` Step 5d and `agents/hatch3r-fixer.md` Step 5b carry this census as a lane-exit gate — `Status: SUCCESS` requires census ∈ {`clean`, `reconciled(N)`, `N/A`}.
|
|
67
|
+
|
|
68
|
+
## Consumer-Scoped Review
|
|
69
|
+
|
|
70
|
+
The reviewer re-derives the census itself — a self-run grep of every changed contract's OLD and NEW identifier. The implementer's census field and the Phase-1 blast radius, when present, seed the list; neither substitutes for the reviewer's own grep.
|
|
71
|
+
|
|
72
|
+
The reviewer then OPENS and READS each consumer at its use site, both sides of every seam:
|
|
73
|
+
|
|
74
|
+
- serializer AND deserializer for a wire field;
|
|
75
|
+
- exporter AND importers for a store symbol;
|
|
76
|
+
- writer AND readers for a persisted name.
|
|
77
|
+
|
|
78
|
+
The verdict cites the captured grep output per the reviewer's Grounding rule. Severity: a consumer left reading the old shape is **Critical**; an implementer census of `unreconciled` without a named justification is **Critical**; a taxonomy diff with no census field at all is a **Warning** (protocol violation). Mirrors `agents/hatch3r-reviewer.md` item 11 (contract preservation, consumer-scoped, two-lens).
|
|
79
|
+
|
|
80
|
+
## Seam-Owner Protocol
|
|
81
|
+
|
|
82
|
+
A contract touched by ≥2 parallel lanes in the same batch gets exactly ONE owning lane: the lane whose acceptance criteria REQUIRE the mutation. The owner lands the emitter change AND all consumer reconciliation in one diff. Every peer lane's dispatch prompt gains the line:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
Seam constraint: contract <X> is owned by issue #<N> this batch — consume the current shape; do not mutate it
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Two lanes that BOTH require mutating the same contract are re-leveled sequential — the later lane consumes the owner's landed shape.
|
|
89
|
+
|
|
90
|
+
**Detection — two passes:**
|
|
91
|
+
|
|
92
|
+
1. First-pass textual scan of issue bodies and linked specs at batch triage: endpoint paths, collection/table names, event names, exported symbols, shared constants named in ≥2 issues (`commands/hatch3r-board-pickup.md` Step 3 item 5).
|
|
93
|
+
2. Authoritative cross-check before dispatch: union the per-issue researcher Breaking Change Candidates tables; any contract appearing in ≥2 issues of the same level is a collision (`commands/board/pickup-delegation-multi.md` Step 6c.2 item 4).
|
|
94
|
+
|
|
95
|
+
**Violation surface:** a post-batch semantic conflict on an owned contract names the violating peer lane. Reconciliation routes to the seam owner — one diff owns the contract; the conflict is never patched in the merge.
|
|
96
|
+
|
|
97
|
+
**Normative amendment to parallel safety:** the parallel-safety condition "disjoint writes" holds at file AND contract granularity (`rules/hatch3r-agent-orchestration.md` → parallel-safety conditions point here). Two lanes are NOT disjoint when their file-disjoint diffs mutate the same shared contract.
|
|
98
|
+
|
|
99
|
+
## Façade Contract-Hold
|
|
100
|
+
|
|
101
|
+
Never delete a field out from under consumers. On drop or rename of a shared output field:
|
|
102
|
+
|
|
103
|
+
1. **Hold the key-set** — the façade keeps emitting every key it emitted before, through the compatibility window.
|
|
104
|
+
2. **Hard-null the dropped field** — key present, value `null`. Absence is a silent shape change a consumer misreads without error; an explicit null fails loudly at the value, at the consumer, on the first read.
|
|
105
|
+
3. **Reconcile every consumer to guarded reads** — null-tolerant access, census-tracked: each guarded read counts as reconciled.
|
|
106
|
+
4. **Delete the key only at the contract phase** — when the census shows zero unguarded readers. This is Fowler's ParallelChange termination criterion: contract begins only "once all usages have been migrated"; skipping contract leaves you worse than you started (martinfowler.com/bliki/ParallelChange.html, accessed 2026-07-08).
|
|
107
|
+
|
|
108
|
+
**Renames** are a drop plus an add: the new key is added, the old key is held nulled or aliased through the window, and consumers migrate key-by-key under the census.
|
|
109
|
+
|
|
110
|
+
**Lane-exit question, answered verbatim before returning:**
|
|
111
|
+
|
|
112
|
+
**"Did you delete the field, or null it behind the façade?"**
|
|
113
|
+
|
|
114
|
+
"Deleted" during the compatibility window is a gate failure — revert to the hold pattern before returning.
|
|
115
|
+
|
|
116
|
+
**Precedence carve-out:** a held nulled field and its guarded reads are NOT dead code until the contract phase. The `rules/hatch3r-code-standards.md` dead-code reference sweep runs at the contract phase, when the held field is deleted — that rule carries the matching exception.
|
|
117
|
+
|
|
118
|
+
**Boundary:** this section is the in-code analog of expand-contract for the database (`rules/hatch3r-migrations.md`) and of the API field-removal lifecycle for public endpoints (`rules/hatch3r-api-versioning.md`). Those rules own their boundaries; this section owns every contract they do not load for — internal wire fields, store symbols, event payloads inside the app. Through the window the system builds and runs at all times, the BranchByAbstraction invariant.
|
|
119
|
+
|
|
120
|
+
## Value-Drift Census
|
|
121
|
+
|
|
122
|
+
A shared constant — rate, default, threshold, enum value — consumed by ≥2 features has exactly one owning module; every reader imports it. On touching such a constant:
|
|
123
|
+
|
|
124
|
+
1. Grep the constant NAME and the literal VALUE repo-wide.
|
|
125
|
+
2. Each independently-defined copy is a drift candidate.
|
|
126
|
+
3. Remedy per copy: import from the owner, or an inline ADR comment documenting intentional divergence.
|
|
127
|
+
|
|
128
|
+
**Damage ranking — silent-wrong beats loud-broken.** A deleted import fails at build; a stale copy computes wrong values in production with no signal.
|
|
129
|
+
|
|
130
|
+
One-line literals sit below clone-scan thresholds (≥30-line block matching) — this census is name+value grep, not block matching. `rules/hatch3r-anti-duplication.md` → Value-Drift Census carries the anti-duplication-side enforcement hook.
|
|
131
|
+
|
|
132
|
+
## Ownership Boundaries
|
|
133
|
+
|
|
134
|
+
| Surface | Owning artifact |
|
|
135
|
+
|---------|-----------------|
|
|
136
|
+
| Database schema (expand/migrate/contract, online DDL, backfill) | `rules/hatch3r-migrations.md` |
|
|
137
|
+
| Public API lifecycle (versioning, deprecation, `Sunset`) | `rules/hatch3r-api-versioning.md` |
|
|
138
|
+
| Event registry compatibility (BACKWARD/FORWARD/FULL) | `rules/hatch3r-event-schema-evolution.md` |
|
|
139
|
+
| Spec-time consumer inventory | `agents/hatch3r-brownfield-spec.md` → Integration-Surface Analysis |
|
|
140
|
+
| Code clones / block duplication | `rules/hatch3r-anti-duplication.md` |
|
|
141
|
+
|
|
142
|
+
This rule owns: internal cross-lane seams, the census output grammar, seam-owner assignment, the façade contract-hold, and value drift on shared constants.
|
|
143
|
+
|
|
144
|
+
## Enforcement Wiring
|
|
145
|
+
|
|
146
|
+
- `agents/hatch3r-implementer.md` Step 5d — consumer census as lane-exit gate.
|
|
147
|
+
- `agents/hatch3r-fixer.md` Step 5b — consumer census on shared-contract fixes.
|
|
148
|
+
- `agents/hatch3r-reviewer.md` item 11 — consumer-scoped review with self-run grep.
|
|
149
|
+
- `commands/hatch3r-board-pickup.md` Step 3 item 5 — first-pass contract-overlap scan at batch triage.
|
|
150
|
+
- `commands/board/pickup-delegation-multi.md` Step 6c.2 item 4 — seam-owner assignment; Step 6c.4 — per-lane census verification + cross-lane old-identifier grep.
|
|
151
|
+
- `agents/shared/quality-charter.md` → Data integrity quality — shared-contract census row + verification gate.
|
|
152
|
+
- `checks/code-quality.md` → Shared Contracts and Constants.
|
|
153
|
+
|
|
154
|
+
## References
|
|
155
|
+
|
|
156
|
+
- Fowler, M. "ParallelChange." martinfowler.com/bliki/ParallelChange.html (accessed 2026-07-08, T3 canonical, 2014). Expand/migrate/contract for any interface change; contract begins only "once all usages have been migrated" — skipping contract leaves you worse than you started.
|
|
157
|
+
- Fowler, M. "BranchByAbstraction." martinfowler.com/bliki/BranchByAbstraction.html (accessed 2026-07-08, T3 canonical, 2014). The system builds and runs at all times during the hold; the abstraction layer outlives the old supplier.
|
|
158
|
+
- Winters, T., Manshreck, T., Wright, H. *Software Engineering at Google*, ch. 22 "Large-Scale Changes." abseil.io/resources/swe-book/html/ch22.html (accessed 2026-07-08, T2, 2020). Tool-driven consumer discovery sharded by ownership; reintroduction guards; done is declared from evidence, not assumed.
|
|
159
|
+
- Sourcegraph. "Batch Changes." sourcegraph.com/docs/batch-changes (accessed 2026-07-08, T1, current). Text-search census as the consumer-discovery primitive; burndown-to-zero completion tracking.
|
|
160
|
+
- Pact. "can-i-deploy." docs.pact.io/pact_broker/can_i_deploy (accessed 2026-07-08, T1, current). Verification is recorded evidence per consumer; all known consumers gate the deploy.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: hatch3r-contract-census
|
|
3
|
+
type: rule
|
|
4
|
+
description: Shared-contract discipline for brownfield changes — contract taxonomy, repo-wide consumer census as lane-exit gate, seam-owner protocol for parallel lanes, façade contract-hold on field drop/rename, value-drift census for shared constants.
|
|
5
|
+
tags: [implementation, review, orchestration, ctx:brownfield-only]
|
|
6
|
+
precedence: high
|
|
7
|
+
alwaysApply: true
|
|
8
|
+
---
|
|
9
|
+
# hatch3r Contract Census
|
|
10
|
+
|
|
11
|
+
**Pillars:** P2 (Scientific & Practical Quality), P8 (Clarification & Fan-out Discipline), CQ8 (Maintainability Quality)
|
|
12
|
+
|
|
13
|
+
## Binding Condition
|
|
14
|
+
|
|
15
|
+
This rule binds any diff that mutates a contract in the Shared-Contract Taxonomy below, in a repo where that contract has existing consumers. A change touching no taxonomy class exits with `Consumer census: N/A (no shared-contract change)`. A greenfield-new contract with zero consumers exits trivially — the census grep returns nothing and reports `clean`.
|
|
16
|
+
|
|
17
|
+
The failure class this rule closes: parallel file-disjoint lanes silently breaking a shared runtime contract — a renamed persisted collection, a changed store symbol, a dropped wire field — that no quality gate and, in a no-static-types stack, no compiler checks. File disjointness is not contract disjointness: two lanes whose diffs share zero files still collide when both touch the same contract.
|
|
18
|
+
|
|
19
|
+
## Shared-Contract Taxonomy
|
|
20
|
+
|
|
21
|
+
Seven contract classes. Each line states why file-disjointness does not protect it.
|
|
22
|
+
|
|
23
|
+
- **(a) Exported symbol** — function, class, or store: its name, signature, or subpath. Importers live in other files by definition. (researcher: `api_signature` for signature changes, `public_interface` for name/visibility/subpath changes)
|
|
24
|
+
- **(b) Persisted collection/table/field name** — string-typed: writer and reader each spell the string independently; no compiler links them. (researcher: `data_migration`)
|
|
25
|
+
- **(c) Client↔server wire field** — a JSON key crossing the network: serializer and deserializer sit in different trees, often different languages. (researcher: `type_shape`)
|
|
26
|
+
- **(d) Event name + payload schema** — emitter and subscribers are decoupled by design; the bus hides the seam. (researcher: `event_schema`)
|
|
27
|
+
- **(e) Shared constant** — rate, default, threshold, or enum value: copies compile independently, and a stale copy computes wrong values with no error. (researcher: `type_shape` for enum members, `cli_contract` for surfaced defaults; value-only drift sits below the researcher's radar → §Value-Drift Census)
|
|
28
|
+
- **(f) CLI flag / config / env key** — the producer is code; the consumers are shell scripts, CI YAML, and dotfiles no type-checker loads. (researcher: `cli_contract`)
|
|
29
|
+
- **(g) Type or schema shape where no checker is authoritative** — plain JS, dynamic access, JSON blobs: shape agreement exists only by convention, so classes (a)-(f) all degrade to grep.
|
|
30
|
+
|
|
31
|
+
The parenthesized categories map classes (a)-(f) onto the researcher's breaking-change vocabulary — `api_signature / type_shape / event_schema / public_interface / data_migration / cli_contract` (`agents/hatch3r-researcher.md` → Full-Mode Breaking-Change Detection) — so a researcher Breaking Change Candidates row converts directly into a taxonomy class and back.
|
|
32
|
+
|
|
33
|
+
## Consumer Census
|
|
34
|
+
|
|
35
|
+
**Trigger:** any taxonomy mutation — rename, removal, re-signature, revalue, key add/drop.
|
|
36
|
+
|
|
37
|
+
**Procedure:**
|
|
38
|
+
|
|
39
|
+
1. Repo-wide grep of the OLD identifier AND the NEW identifier. Never limit the grep to the lane's `affectedFiles` — consumers live outside the lane's file set by definition.
|
|
40
|
+
2. Per-class patterns:
|
|
41
|
+
- **String contracts** (classes b, d, f) — grep the quoted forms: `'name'` and `"name"` (plus template-literal and heredoc forms where the language has them).
|
|
42
|
+
- **Wire fields** (class c) — grep BOTH the client and server trees, plus fixtures, mocks, and recorded payloads: a test fixture still asserting the old key is an unreconciled consumer.
|
|
43
|
+
- **Constants** (class e) — grep the NAME and the literal VALUE; an independent copy defines the value without the name.
|
|
44
|
+
- **Infra/config** (class f) — include non-code files: CI YAML, Dockerfiles, `.env*`, deploy manifests.
|
|
45
|
+
3. Narrowing tactics for short identifiers that over-match: qualified member access (`\.field\b`), collection-prefixed forms (`users.field`), and quoted-literal-only matches.
|
|
46
|
+
|
|
47
|
+
**Reconciled** — a consumer counts as reconciled when it is updated to the new shape in this diff, OR reads through a guard added in this diff (façade-hold null-guard), OR is justified by name. Exactly three justifications are valid:
|
|
48
|
+
|
|
49
|
+
1. Consumer owned by another lane's seam — name the lane/issue.
|
|
50
|
+
2. Dead code with a linked deletion.
|
|
51
|
+
3. Dynamic/reflective access grep cannot resolve — name the mechanism, add a runtime guard.
|
|
52
|
+
|
|
53
|
+
**Output grammar** — the census field emits exactly one of:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
Consumer census: clean | reconciled(N) | N unreconciled — justification | N/A (no shared-contract change)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
- `clean` — the grep found zero consumers of the old shape outside this diff.
|
|
60
|
+
- `reconciled(N)` — N consumers found; every one updated, guarded, or justified by name.
|
|
61
|
+
- `N unreconciled — justification` — N consumers not yet updated or guarded; each carries one of the three justifications above. `unreconciled` WITHOUT a named justification caps the producing agent's Status at PARTIAL — done is declared from grep evidence, not assumed (the large-scale-change discipline of *Software Engineering at Google* ch. 22).
|
|
62
|
+
- `N/A (no shared-contract change)` — the diff touches no taxonomy class.
|
|
63
|
+
|
|
64
|
+
**Spec-time seed:** when a brownfield spec exists, its Integration-Surface consumer inventory (`agents/hatch3r-brownfield-spec.md` → Integration-Surface Analysis) seeds the grep list. The lane still re-runs the grep at lane exit: parallel lanes may have added consumers since spec time.
|
|
65
|
+
|
|
66
|
+
**Where it runs:** `agents/hatch3r-implementer.md` Step 5d and `agents/hatch3r-fixer.md` Step 5b carry this census as a lane-exit gate — `Status: SUCCESS` requires census ∈ {`clean`, `reconciled(N)`, `N/A`}.
|
|
67
|
+
|
|
68
|
+
## Consumer-Scoped Review
|
|
69
|
+
|
|
70
|
+
The reviewer re-derives the census itself — a self-run grep of every changed contract's OLD and NEW identifier. The implementer's census field and the Phase-1 blast radius, when present, seed the list; neither substitutes for the reviewer's own grep.
|
|
71
|
+
|
|
72
|
+
The reviewer then OPENS and READS each consumer at its use site, both sides of every seam:
|
|
73
|
+
|
|
74
|
+
- serializer AND deserializer for a wire field;
|
|
75
|
+
- exporter AND importers for a store symbol;
|
|
76
|
+
- writer AND readers for a persisted name.
|
|
77
|
+
|
|
78
|
+
The verdict cites the captured grep output per the reviewer's Grounding rule. Severity: a consumer left reading the old shape is **Critical**; an implementer census of `unreconciled` without a named justification is **Critical**; a taxonomy diff with no census field at all is a **Warning** (protocol violation). Mirrors `agents/hatch3r-reviewer.md` item 11 (contract preservation, consumer-scoped, two-lens).
|
|
79
|
+
|
|
80
|
+
## Seam-Owner Protocol
|
|
81
|
+
|
|
82
|
+
A contract touched by ≥2 parallel lanes in the same batch gets exactly ONE owning lane: the lane whose acceptance criteria REQUIRE the mutation. The owner lands the emitter change AND all consumer reconciliation in one diff. Every peer lane's dispatch prompt gains the line:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
Seam constraint: contract <X> is owned by issue #<N> this batch — consume the current shape; do not mutate it
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Two lanes that BOTH require mutating the same contract are re-leveled sequential — the later lane consumes the owner's landed shape.
|
|
89
|
+
|
|
90
|
+
**Detection — two passes:**
|
|
91
|
+
|
|
92
|
+
1. First-pass textual scan of issue bodies and linked specs at batch triage: endpoint paths, collection/table names, event names, exported symbols, shared constants named in ≥2 issues (`commands/hatch3r-board-pickup.md` Step 3 item 5).
|
|
93
|
+
2. Authoritative cross-check before dispatch: union the per-issue researcher Breaking Change Candidates tables; any contract appearing in ≥2 issues of the same level is a collision (`commands/board/pickup-delegation-multi.md` Step 6c.2 item 4).
|
|
94
|
+
|
|
95
|
+
**Violation surface:** a post-batch semantic conflict on an owned contract names the violating peer lane. Reconciliation routes to the seam owner — one diff owns the contract; the conflict is never patched in the merge.
|
|
96
|
+
|
|
97
|
+
**Normative amendment to parallel safety:** the parallel-safety condition "disjoint writes" holds at file AND contract granularity (`rules/hatch3r-agent-orchestration.md` → parallel-safety conditions point here). Two lanes are NOT disjoint when their file-disjoint diffs mutate the same shared contract.
|
|
98
|
+
|
|
99
|
+
## Façade Contract-Hold
|
|
100
|
+
|
|
101
|
+
Never delete a field out from under consumers. On drop or rename of a shared output field:
|
|
102
|
+
|
|
103
|
+
1. **Hold the key-set** — the façade keeps emitting every key it emitted before, through the compatibility window.
|
|
104
|
+
2. **Hard-null the dropped field** — key present, value `null`. Absence is a silent shape change a consumer misreads without error; an explicit null fails loudly at the value, at the consumer, on the first read.
|
|
105
|
+
3. **Reconcile every consumer to guarded reads** — null-tolerant access, census-tracked: each guarded read counts as reconciled.
|
|
106
|
+
4. **Delete the key only at the contract phase** — when the census shows zero unguarded readers. This is Fowler's ParallelChange termination criterion: contract begins only "once all usages have been migrated"; skipping contract leaves you worse than you started (martinfowler.com/bliki/ParallelChange.html, accessed 2026-07-08).
|
|
107
|
+
|
|
108
|
+
**Renames** are a drop plus an add: the new key is added, the old key is held nulled or aliased through the window, and consumers migrate key-by-key under the census.
|
|
109
|
+
|
|
110
|
+
**Lane-exit question, answered verbatim before returning:**
|
|
111
|
+
|
|
112
|
+
**"Did you delete the field, or null it behind the façade?"**
|
|
113
|
+
|
|
114
|
+
"Deleted" during the compatibility window is a gate failure — revert to the hold pattern before returning.
|
|
115
|
+
|
|
116
|
+
**Precedence carve-out:** a held nulled field and its guarded reads are NOT dead code until the contract phase. The `rules/hatch3r-code-standards.md` dead-code reference sweep runs at the contract phase, when the held field is deleted — that rule carries the matching exception.
|
|
117
|
+
|
|
118
|
+
**Boundary:** this section is the in-code analog of expand-contract for the database (`rules/hatch3r-migrations.md`) and of the API field-removal lifecycle for public endpoints (`rules/hatch3r-api-versioning.md`). Those rules own their boundaries; this section owns every contract they do not load for — internal wire fields, store symbols, event payloads inside the app. Through the window the system builds and runs at all times, the BranchByAbstraction invariant.
|
|
119
|
+
|
|
120
|
+
## Value-Drift Census
|
|
121
|
+
|
|
122
|
+
A shared constant — rate, default, threshold, enum value — consumed by ≥2 features has exactly one owning module; every reader imports it. On touching such a constant:
|
|
123
|
+
|
|
124
|
+
1. Grep the constant NAME and the literal VALUE repo-wide.
|
|
125
|
+
2. Each independently-defined copy is a drift candidate.
|
|
126
|
+
3. Remedy per copy: import from the owner, or an inline ADR comment documenting intentional divergence.
|
|
127
|
+
|
|
128
|
+
**Damage ranking — silent-wrong beats loud-broken.** A deleted import fails at build; a stale copy computes wrong values in production with no signal.
|
|
129
|
+
|
|
130
|
+
One-line literals sit below clone-scan thresholds (≥30-line block matching) — this census is name+value grep, not block matching. `rules/hatch3r-anti-duplication.md` → Value-Drift Census carries the anti-duplication-side enforcement hook.
|
|
131
|
+
|
|
132
|
+
## Ownership Boundaries
|
|
133
|
+
|
|
134
|
+
| Surface | Owning artifact |
|
|
135
|
+
|---------|-----------------|
|
|
136
|
+
| Database schema (expand/migrate/contract, online DDL, backfill) | `rules/hatch3r-migrations.md` |
|
|
137
|
+
| Public API lifecycle (versioning, deprecation, `Sunset`) | `rules/hatch3r-api-versioning.md` |
|
|
138
|
+
| Event registry compatibility (BACKWARD/FORWARD/FULL) | `rules/hatch3r-event-schema-evolution.md` |
|
|
139
|
+
| Spec-time consumer inventory | `agents/hatch3r-brownfield-spec.md` → Integration-Surface Analysis |
|
|
140
|
+
| Code clones / block duplication | `rules/hatch3r-anti-duplication.md` |
|
|
141
|
+
|
|
142
|
+
This rule owns: internal cross-lane seams, the census output grammar, seam-owner assignment, the façade contract-hold, and value drift on shared constants.
|
|
143
|
+
|
|
144
|
+
## Enforcement Wiring
|
|
145
|
+
|
|
146
|
+
- `agents/hatch3r-implementer.md` Step 5d — consumer census as lane-exit gate.
|
|
147
|
+
- `agents/hatch3r-fixer.md` Step 5b — consumer census on shared-contract fixes.
|
|
148
|
+
- `agents/hatch3r-reviewer.md` item 11 — consumer-scoped review with self-run grep.
|
|
149
|
+
- `commands/hatch3r-board-pickup.md` Step 3 item 5 — first-pass contract-overlap scan at batch triage.
|
|
150
|
+
- `commands/board/pickup-delegation-multi.md` Step 6c.2 item 4 — seam-owner assignment; Step 6c.4 — per-lane census verification + cross-lane old-identifier grep.
|
|
151
|
+
- `agents/shared/quality-charter.md` → Data integrity quality — shared-contract census row + verification gate.
|
|
152
|
+
- `checks/code-quality.md` → Shared Contracts and Constants.
|
|
153
|
+
|
|
154
|
+
## References
|
|
155
|
+
|
|
156
|
+
- Fowler, M. "ParallelChange." martinfowler.com/bliki/ParallelChange.html (accessed 2026-07-08, T3 canonical, 2014). Expand/migrate/contract for any interface change; contract begins only "once all usages have been migrated" — skipping contract leaves you worse than you started.
|
|
157
|
+
- Fowler, M. "BranchByAbstraction." martinfowler.com/bliki/BranchByAbstraction.html (accessed 2026-07-08, T3 canonical, 2014). The system builds and runs at all times during the hold; the abstraction layer outlives the old supplier.
|
|
158
|
+
- Winters, T., Manshreck, T., Wright, H. *Software Engineering at Google*, ch. 22 "Large-Scale Changes." abseil.io/resources/swe-book/html/ch22.html (accessed 2026-07-08, T2, 2020). Tool-driven consumer discovery sharded by ownership; reintroduction guards; done is declared from evidence, not assumed.
|
|
159
|
+
- Sourcegraph. "Batch Changes." sourcegraph.com/docs/batch-changes (accessed 2026-07-08, T1, current). Text-search census as the consumer-discovery primitive; burndown-to-zero completion tracking.
|
|
160
|
+
- Pact. "can-i-deploy." docs.pact.io/pact_broker/can_i_deploy (accessed 2026-07-08, T1, current). Verification is recorded evidence per consumer; all known consumers gate the deploy.
|
|
@@ -12,7 +12,7 @@ scope: always
|
|
|
12
12
|
|
|
13
13
|
Source: the cost-visibility design decision and the cost-transparency principle (pillar P7; see `agents/shared/principles.md`).
|
|
14
14
|
|
|
15
|
-
Every orchestrator command (`commands/hatch3r-*.md` with `orchestrator: true`) and every meaningful skill run that mutates state MUST emit cost data — pre-execution estimate at plan time and post-execution actuals + delta at completion time. The delta lands in the
|
|
15
|
+
Every orchestrator command (`commands/hatch3r-*.md` with `orchestrator: true`) and every meaningful skill run that mutates state MUST emit cost data — pre-execution estimate at plan time and post-execution actuals + delta at completion time. The delta lands in the Iteration Summary recap (cost facet; full blocks on the `Cost:` exception line beyond ±25%) per `rules/hatch3r-iteration-summary.md`.
|
|
16
16
|
|
|
17
17
|
## Pre-Execution Estimate
|
|
18
18
|
|
|
@@ -57,9 +57,9 @@ delta:
|
|
|
57
57
|
|
|
58
58
|
## Surfacing in Iteration Summary
|
|
59
59
|
|
|
60
|
-
Per `rules/hatch3r-iteration-summary.md`
|
|
60
|
+
Per `rules/hatch3r-iteration-summary.md` (recap contract): the recap carries the cost facet on every run — `cost Δ<tok%>% tok / Δ<min%>% min`. Deltas exceeding 25% (absolute value) additionally fire the `Cost:` exception line — `Cost: flagged_for_review: true` followed by the fenced `cost_actuals` + `delta` blocks — because they signal under- or over-estimation patterns that the next cycle should investigate. The flag is informational, not a gate failure; deltas within ±25% emit no `Cost:` line (the recap Δ facet suffices; telemetry persists regardless).
|
|
61
61
|
|
|
62
|
-
A
|
|
62
|
+
A recap with no cost facet fails the Validation Gate of `rules/hatch3r-iteration-summary.md`.
|
|
63
63
|
|
|
64
64
|
### Worked Example
|
|
65
65
|
|
|
@@ -91,6 +91,13 @@ delta:
|
|
|
91
91
|
|
|
92
92
|
`duration_delta_percent` exceeds 25% — flagged informational for next-cycle EVOLVE review. `input_tokens_delta_percent` is 24.4% — under threshold, no flag.
|
|
93
93
|
|
|
94
|
+
In the closing recap these actuals surface as the cost facet, and the >25% duration delta fires the `Cost:` exception line (the fenced `cost_actuals` + `delta` blocks above follow it):
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
files 4 (+310/−22) · sa 6/5 · gates 6/6 · cost Δ24.4% tok / Δ27.5% min · tier 2
|
|
98
|
+
Cost: flagged_for_review: true
|
|
99
|
+
```
|
|
100
|
+
|
|
94
101
|
## Source of Telemetry
|
|
95
102
|
|
|
96
103
|
`src/pipeline/observability.ts` records:
|
|
@@ -117,7 +124,7 @@ A change to a `commands/hatch3r-*.md` orchestrator or to a meaningful state-muta
|
|
|
117
124
|
|
|
118
125
|
1. The artifact emits `cost_estimate` before the first sub-agent spawn.
|
|
119
126
|
2. The artifact emits `cost_actuals` + `delta` before declaring iteration-summary status.
|
|
120
|
-
3. The
|
|
127
|
+
3. The Iteration Summary recap carries the cost facet; when any delta exceeds 25% absolute, the `Cost:` exception line carries both blocks (per `rules/hatch3r-iteration-summary.md` → Exception Lines).
|
|
121
128
|
4. Telemetry persists to `.hatch3r/telemetry/<session-id>.json` even under `--quiet`.
|
|
122
129
|
5. Delta thresholds beyond 25% absolute value carry an explicit `flagged_for_review: true` annotation in the iteration summary.
|
|
123
130
|
|
|
@@ -12,7 +12,7 @@ alwaysApply: true
|
|
|
12
12
|
|
|
13
13
|
Source: the cost-visibility design decision and the cost-transparency principle (pillar P7; see `agents/shared/principles.md`).
|
|
14
14
|
|
|
15
|
-
Every orchestrator command (`commands/hatch3r-*.md` with `orchestrator: true`) and every meaningful skill run that mutates state MUST emit cost data — pre-execution estimate at plan time and post-execution actuals + delta at completion time. The delta lands in the
|
|
15
|
+
Every orchestrator command (`commands/hatch3r-*.md` with `orchestrator: true`) and every meaningful skill run that mutates state MUST emit cost data — pre-execution estimate at plan time and post-execution actuals + delta at completion time. The delta lands in the Iteration Summary recap (cost facet; full blocks on the `Cost:` exception line beyond ±25%) per `rules/hatch3r-iteration-summary.md`.
|
|
16
16
|
|
|
17
17
|
## Pre-Execution Estimate
|
|
18
18
|
|
|
@@ -57,9 +57,9 @@ delta:
|
|
|
57
57
|
|
|
58
58
|
## Surfacing in Iteration Summary
|
|
59
59
|
|
|
60
|
-
Per `rules/hatch3r-iteration-summary.md`
|
|
60
|
+
Per `rules/hatch3r-iteration-summary.md` (recap contract): the recap carries the cost facet on every run — `cost Δ<tok%>% tok / Δ<min%>% min`. Deltas exceeding 25% (absolute value) additionally fire the `Cost:` exception line — `Cost: flagged_for_review: true` followed by the fenced `cost_actuals` + `delta` blocks — because they signal under- or over-estimation patterns that the next cycle should investigate. The flag is informational, not a gate failure; deltas within ±25% emit no `Cost:` line (the recap Δ facet suffices; telemetry persists regardless).
|
|
61
61
|
|
|
62
|
-
A
|
|
62
|
+
A recap with no cost facet fails the Validation Gate of `rules/hatch3r-iteration-summary.md`.
|
|
63
63
|
|
|
64
64
|
### Worked Example
|
|
65
65
|
|
|
@@ -91,6 +91,13 @@ delta:
|
|
|
91
91
|
|
|
92
92
|
`duration_delta_percent` exceeds 25% — flagged informational for next-cycle EVOLVE review. `input_tokens_delta_percent` is 24.4% — under threshold, no flag.
|
|
93
93
|
|
|
94
|
+
In the closing recap these actuals surface as the cost facet, and the >25% duration delta fires the `Cost:` exception line (the fenced `cost_actuals` + `delta` blocks above follow it):
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
files 4 (+310/−22) · sa 6/5 · gates 6/6 · cost Δ24.4% tok / Δ27.5% min · tier 2
|
|
98
|
+
Cost: flagged_for_review: true
|
|
99
|
+
```
|
|
100
|
+
|
|
94
101
|
## Source of Telemetry
|
|
95
102
|
|
|
96
103
|
`src/pipeline/observability.ts` records:
|
|
@@ -117,7 +124,7 @@ A change to a `commands/hatch3r-*.md` orchestrator or to a meaningful state-muta
|
|
|
117
124
|
|
|
118
125
|
1. The artifact emits `cost_estimate` before the first sub-agent spawn.
|
|
119
126
|
2. The artifact emits `cost_actuals` + `delta` before declaring iteration-summary status.
|
|
120
|
-
3. The
|
|
127
|
+
3. The Iteration Summary recap carries the cost facet; when any delta exceeds 25% absolute, the `Cost:` exception line carries both blocks (per `rules/hatch3r-iteration-summary.md` → Exception Lines).
|
|
121
128
|
4. Telemetry persists to `.hatch3r/telemetry/<session-id>.json` even under `--quiet`.
|
|
122
129
|
5. Delta thresholds beyond 25% absolute value carry an explicit `flagged_for_review: true` annotation in the iteration summary.
|
|
123
130
|
|
|
@@ -28,6 +28,7 @@ Score every task against these signals before implementation. Each signal adds w
|
|
|
28
28
|
| Estimated file count > 5 | +2 | Infer from task scope and codebase exploration |
|
|
29
29
|
| Security-sensitive area (auth, payments, data access, secrets) | +2 | Match task against security-sensitive directories or keywords |
|
|
30
30
|
| Behavioral contract change (API signature, event schema, type interface) | +2 | Task implies changes to shared interfaces or public APIs |
|
|
31
|
+
| Module-boundary or client↔server contract change in files with no static type coverage | +2 | Changed exports / HTTP shapes / event names / store keys where no compiler validates consumers |
|
|
31
32
|
|
|
32
33
|
### Tier Assignment
|
|
33
34
|
|
|
@@ -23,6 +23,7 @@ Score every task against these signals before implementation. Each signal adds w
|
|
|
23
23
|
| Estimated file count > 5 | +2 | Infer from task scope and codebase exploration |
|
|
24
24
|
| Security-sensitive area (auth, payments, data access, secrets) | +2 | Match task against security-sensitive directories or keywords |
|
|
25
25
|
| Behavioral contract change (API signature, event schema, type interface) | +2 | Task implies changes to shared interfaces or public APIs |
|
|
26
|
+
| Module-boundary or client↔server contract change in files with no static type coverage | +2 | Changed exports / HTTP shapes / event names / store keys where no compiler validates consumers |
|
|
26
27
|
|
|
27
28
|
### Tier Assignment
|
|
28
29
|
|