hatch3r 2.1.1 → 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-fixer.md +20 -7
- package/dist/content/agents/hatch3r-handoff-loader.md +7 -2
- package/dist/content/agents/hatch3r-handoff-preparer.md +2 -1
- package/dist/content/agents/hatch3r-implementer.md +28 -2
- 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 +20 -12
- 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/quality-charter.md +3 -2
- package/dist/content/agents/shared/quality-specialist-frame.md +1 -1
- package/dist/content/agents/shared/user-question-protocol.md +1 -0
- 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 +1 -1
- package/dist/content/commands/hatch3r-benchmark.md +1 -1
- package/dist/content/commands/hatch3r-board-fill.md +2 -2
- package/dist/content/commands/hatch3r-board-pickup.md +4 -3
- package/dist/content/commands/hatch3r-bug-pipeline.md +1 -1
- package/dist/content/commands/hatch3r-bug-plan.md +1 -1
- package/dist/content/commands/hatch3r-codebase-map.md +1 -1
- package/dist/content/commands/hatch3r-create.md +1 -1
- package/dist/content/commands/hatch3r-debug.md +1 -1
- package/dist/content/commands/hatch3r-design-system-create.md +254 -0
- package/dist/content/commands/hatch3r-feature-plan.md +1 -1
- package/dist/content/commands/hatch3r-handoff.md +1 -1
- package/dist/content/commands/hatch3r-healthcheck.md +1 -1
- package/dist/content/commands/hatch3r-migration-plan.md +1 -1
- package/dist/content/commands/hatch3r-onboard.md +1 -1
- package/dist/content/commands/hatch3r-pr-resolve.md +69 -29
- package/dist/content/commands/hatch3r-project-spec.md +1 -1
- package/dist/content/commands/hatch3r-quick-change.md +1 -1
- package/dist/content/commands/hatch3r-refactor-plan.md +1 -1
- package/dist/content/commands/hatch3r-release.md +1 -1
- package/dist/content/commands/hatch3r-revision.md +7 -7
- package/dist/content/commands/hatch3r-roadmap.md +1 -1
- package/dist/content/commands/hatch3r-security-audit.md +1 -1
- package/dist/content/commands/hatch3r-test-plan.md +1 -1
- package/dist/content/commands/hatch3r-workflow.md +12 -10
- package/dist/content/commands/revision/revision-quality.md +6 -5
- 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 +14 -14
- package/dist/content/rules/hatch3r-agent-orchestration.mdc +14 -14
- package/dist/content/rules/hatch3r-anti-duplication.md +10 -1
- package/dist/content/rules/hatch3r-anti-duplication.mdc +10 -1
- package/dist/content/rules/hatch3r-clarification-default.md +6 -5
- package/dist/content/rules/hatch3r-clarification-default.mdc +6 -5
- 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-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-i18n.md +4 -0
- package/dist/content/rules/hatch3r-i18n.mdc +4 -0
- package/dist/content/rules/hatch3r-iteration-summary.md +2 -0
- package/dist/content/rules/hatch3r-iteration-summary.mdc +2 -0
- package/dist/content/rules/hatch3r-migrations.md +1 -1
- package/dist/content/rules/hatch3r-migrations.mdc +1 -1
- 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/skills/hatch3r-design-system-detect/SKILL.md +2 -0
- package/dist/content/skills/hatch3r-handoff-prepare/SKILL.md +1 -1
- package/package.json +1 -1
|
@@ -39,7 +39,7 @@ Score task complexity per the `hatch3r-deep-context` rule before Phase 1. Apply
|
|
|
39
39
|
- **Tier 2 hard gate (B1).** Before Phase 2, run `hatch3r-researcher` with `requirements-elicitation:quick` mode to detect ambiguity. The researcher sub-agent emits the elicited questions as a structured list in its result — it does NOT call the platform-native question tool (a spawned sub-agent has no interactive surface). The **orchestrator** renders that list to the user via the platform-native question tool (per `agents/shared/user-question-protocol.md`), mirroring `commands/hatch3r-workflow.md` Phase 1 "Present the `requirements-elicitation` questions inline and await answers". Orchestrator awaits answers and integrates them into the Phase 1 brief; do not begin Phase 2 with unresolved questions. Tier 1 is exempt only when scope is single-file, single-concern, and acceptance is testable from the user message alone.
|
|
40
40
|
- **Tier 3 (Deep):** Present Pre-Implementation Summary and ASK for confirmation. Do NOT proceed until all unresolved questions are answered.
|
|
41
41
|
|
|
42
|
-
**Tier-to-Phase-4 specialist depth mapping** (Finding D7-M9 / D7-SA7.4-1). Deep-context tier drives Phase 1 researcher depth; the same tier drives Phase 4 specialist depth so quality coverage scales with task risk: Tier 1 → run only the always-mode floor (`hatch3r-security` + `hatch3r-testability`) at `quick` depth — UI/perf/maintainability/etc. specialists are skipped per Phase Skip Criteria. Tier 2 → always-mode floor at `standard` depth + every triggered conditional specialist at `quick` depth. Tier 3 → every applicable specialist at `deep` depth — full WCAG AA / OWASP ASI / CWV / mandate-map sweep with N=3 sampling on always-mode specialists when `floor:security` items are touched (per `agents/shared/quality-charter.md` -> Non-Determinism Budget). The depth signal rides on the specialist prompt as the explicit field `depth: quick | standard | deep`; specialists read it via the shared `agents/shared/quality-specialist-frame.md`. Tier also drives **model class** as a first-order effort lever (Tier 1 → economy, Tier 2 → default, Tier 3 → strongest), resolved per-adapter against `models.default` / `src/models/resolve.ts` and ignored where an adapter has no model-routing surface — see `hatch3r-deep-context` -> Tier Assignment.
|
|
42
|
+
**Tier-to-Phase-4 specialist depth mapping** (Finding D7-M9 / D7-SA7.4-1). Deep-context tier drives Phase 1 researcher depth; the same tier drives Phase 4 specialist depth so quality coverage scales with task risk: Tier 1 → run only the always-mode floor (`hatch3r-security` + `hatch3r-testability`) at `quick` depth — UI/perf/maintainability/etc. specialists (mandatory-on-match included) are skipped per Phase Skip Criteria. Tier 2 → always-mode floor at `standard` depth + every triggered conditional specialist at `quick` depth, and a triggered mandatory-on-match specialist (`hatch3r-ui` CQ1 / `hatch3r-ux` CQ2) MUST spawn as its own dedicated sub-agent instance (never merged into one spawn) — skipping a triggered one at Tier 2/3 is a gate failure. Tier 3 → every applicable specialist at `deep` depth (same mandatory-on-match mandate) — full WCAG AA / OWASP ASI / CWV / mandate-map sweep with N=3 sampling on always-mode specialists when `floor:security` items are touched (per `agents/shared/quality-charter.md` -> Non-Determinism Budget). The depth signal rides on the specialist prompt as the explicit field `depth: quick | standard | deep`; specialists read it via the shared `agents/shared/quality-specialist-frame.md`. Tier also drives **model class** as a first-order effort lever (Tier 1 → economy, Tier 2 → default, Tier 3 → strongest), resolved per-adapter against `models.default` / `src/models/resolve.ts` and ignored where an adapter has no model-routing surface — see `hatch3r-deep-context` -> Tier Assignment.
|
|
43
43
|
|
|
44
44
|
## Mandatory Delegation Directives
|
|
45
45
|
|
|
@@ -49,7 +49,7 @@ Spawn `hatch3r-researcher` before implementing any task (skip only for trivial s
|
|
|
49
49
|
|
|
50
50
|
### Research Completeness Checklist
|
|
51
51
|
|
|
52
|
-
Before Phase 1 to Phase 2 handoff, verify all
|
|
52
|
+
Before Phase 1 to Phase 2 handoff, verify all five: (1) **affected files identified** (create/modify/delete listed); (2) **blast radius assessed** (downstream consumers + integration points documented); (3) **existing tests located** (or absence noted); (4) **dependencies mapped** (internal + external); (5) **shared contracts inventoried** (every contract the change will mutate — exported symbol, persisted name, wire field, event schema, shared constant — listed with a first-pass consumer grep count per `rules/hatch3r-contract-census.md` → Shared-Contract Taxonomy). If any item is unconfirmed, re-run researcher with additional modes or surface to user.
|
|
53
53
|
|
|
54
54
|
### Implementation Delegation
|
|
55
55
|
|
|
@@ -105,20 +105,20 @@ For multi-sub-task implementations, the implementer performs a lightweight mini-
|
|
|
105
105
|
**Phase 3 — Review Loop:**
|
|
106
106
|
|
|
107
107
|
1. Spawn `hatch3r-reviewer` with diff, acceptance criteria, and blast-radius summary.
|
|
108
|
-
2. Critical/Warning findings: spawn `hatch3r-fixer` with full reviewer output, then re-review. Repeat until 0 Critical + 0 Warning, or max 4 iterations (matches `DEFAULT_MAX_REVIEW_ITERATIONS` in `src/pipeline/reviewLoop.ts`, raised 3→4 in Cycle 7.5 W2B2 H26 to reach the oscillation detector in default config; kept in sync by `src/__tests__/pipeline/reviewLoop.test.ts`, CI-enforced).
|
|
108
|
+
2. Critical/Warning findings: spawn `hatch3r-fixer` with full reviewer output, then re-review. Repeat until 0 Critical + 0 Warning, or max 4 iterations (matches `DEFAULT_MAX_REVIEW_ITERATIONS` in `src/pipeline/reviewLoop.ts`, raised 3→4 in Cycle 7.5 W2B2 H26 to reach the oscillation detector in default config; kept in sync by `src/__tests__/pipeline/reviewLoop.test.ts`, CI-enforced). Before each fixer dispatch, append the W1 write-ahead rows; after each re-review, append the W2 disposition rows (`rules/hatch3r-findings-ledger.md` → Write Points).
|
|
109
109
|
- **Re-run honor-rule (anti-self-approval, F15.2-H2 / D13-SA13.2-F6 / D15-SA15.2-F3).** The fixer's `Reviewer re-run required` boolean is advisory; the orchestrator derives the authoritative value `reRunRequired = (fixer Files changed list is non-empty)`. When `true`, another `hatch3r-reviewer` pass is MANDATORY before the loop may exit clean — a fixer `Status: SUCCESS` with a non-empty `Files changed` can never self-approve to a clean exit. A `Reviewer re-run required: false` printed alongside a non-empty `Files changed` is overridden to `true` and noted as a self-declared protocol violation. The `Files changed` list is SSOT-bound: it is attested by the same fixer `delegation_proof_id` the orchestrator quotes in its End-of-Turn Delegation Attestation, so the signal cannot be forged without spawning the fixer.
|
|
110
110
|
3. **Confirmation pass** after clean review: lightweight re-review checking only (a) no new test failures vs Phase 2 baseline, (b) no type errors introduced, (c) acceptance criteria still met. Does not re-run the full checklist.
|
|
111
111
|
- **Runtime calibration second pass (orchestrator-owned).** At this would-be-clean exit, the orchestrator — not the stateless reviewer — evaluates the `rules/hatch3r-reviewer-calibration.md` trigger: read the cross-run `consecutive_clean_pass_count` from `.hatch3r/calibration-state.json`, increment it for this clean run, and fire a second-pass review (different model class, else same-class re-roll) when the post-increment count is a multiple of `N` (default 5) OR — for a high-risk diff (`floor:security` / auth / CQ3-security-dispatch files) — on the first clean PASS. A divergent second pass reverts the exit to step 2 (`REQUEST CHANGES`) and resets the count to 0; persist the count (atomic write via `src/merge/safeWrite.ts`) and append the calibration-log record. A REQUEST CHANGES or DESIGN_OBJECTION at any iteration also resets the persisted count to 0.
|
|
112
|
-
4. Max iterations reached: surface to user with a structured summary (iteration count, remaining Critical findings with file:line, remaining Warnings, fix-manually-vs-accept-risk recommendation). Never present raw reviewer output unsummarized.
|
|
112
|
+
4. Max iterations reached: surface to user with a structured summary (iteration count, remaining Critical findings with file:line, remaining Warnings, fix-manually-vs-accept-risk recommendation). Never present raw reviewer output unsummarized. Reconcile the ledger to the run-exit invariant (W3) before surfacing; the structured summary lists the open `finding_id`s.
|
|
113
113
|
5. **Review gate confidence signal:** on a clean verdict, record the iteration count in `PipelineContext.reviewResult.iterations`. Clean-on-first-pass signals higher confidence than clean-after-multiple-iterations; Phase 4 and the orchestrator factor this into risk assessment.
|
|
114
114
|
|
|
115
115
|
**Phase 4 — Final Quality** (after review loop is clean):
|
|
116
116
|
|
|
117
|
-
Launch Phase 4 specialists in parallel, bounded by an orchestrator-honored fan-out width `max_phase4_parallel` (default `8` — covers the empirical maximum of applicable specialists per the trigger table, so a typical Tier 3 change fans out in at most 2 batches). This bound is LLM-honored orchestrator guidance, not a code-enforced cap: the host Task tool is the actual dispatcher and applies no platform fan-out limit, so no hatch3r module reads an env var or clamps the count — the orchestrator self-limits per this prose. The bound exists for upstream provider rate-limit headroom (RPM/TPM) — a true dependency edge — NOT per-orchestrator context cost; token cost never serializes independent work (P8 dominates P7). A non-rate-limited orchestrator MAY raise the width up to the full applicable-specialist set. **Rate-limit back-off (orchestrator-LLM guidance):** when the orchestrator observes ≥3 consecutive rate-limit-class transient failures, reduce the active fan-out width by 1 for the next batch and record the back-off in the Iteration Summary; never silently cap a healthy run. When applicable specialists exceed the bound, batch by severity-descending priority `CRITICAL → HIGH → MEDIUM → LOW` (severity is the worst-case finding class the specialist surfaces: always-on testability (CQ5) / security (CQ3) → CRITICAL,
|
|
117
|
+
Launch Phase 4 specialists in parallel, bounded by an orchestrator-honored fan-out width `max_phase4_parallel` (default `8` — covers the empirical maximum of applicable specialists per the trigger table, so a typical Tier 3 change fans out in at most 2 batches). This bound is LLM-honored orchestrator guidance, not a code-enforced cap: the host Task tool is the actual dispatcher and applies no platform fan-out limit, so no hatch3r module reads an env var or clamps the count — the orchestrator self-limits per this prose. The bound exists for upstream provider rate-limit headroom (RPM/TPM) — a true dependency edge — NOT per-orchestrator context cost; token cost never serializes independent work (P8 dominates P7). A non-rate-limited orchestrator MAY raise the width up to the full applicable-specialist set. **Rate-limit back-off (orchestrator-LLM guidance):** when the orchestrator observes ≥3 consecutive rate-limit-class transient failures, reduce the active fan-out width by 1 for the next batch and record the back-off in the Iteration Summary; never silently cap a healthy run. When applicable specialists exceed the bound, batch by severity-descending priority `CRITICAL → HIGH → MEDIUM → LOW` (severity is the worst-case finding class the specialist surfaces: always-on testability (CQ5) / security (CQ3) → CRITICAL, mandatory-on-match CQ1/CQ2 (ui/ux) + conditional CQ4/CQ7 (reliability/performance) → HIGH, docs/lint → MEDIUM, low-impact → LOW); within a bucket, dispatch in trigger-table order. Each batch runs to completion before the next starts; the validation pass runs once after the final batch. The applicable specialists and their trigger conditions are listed in the Phase 4 Specialist Trigger Table below. The width bound and the rate-limit back-off never drop a triggered mandatory-on-match specialist — `hatch3r-ui`/`hatch3r-ux` dispatch as dedicated instances in the first HIGH batch.
|
|
118
118
|
|
|
119
119
|
**Specialist Prompt Enrichment:** When spawning Phase 4 specialists, include the Phase 2 `filesChanged` list (focus on affected code), the Phase 3 review verdict summary (avoid re-flagging reviewed issues), and `researchFindings.blastRadius` (assess downstream impact).
|
|
120
120
|
|
|
121
|
-
**Runtime trigger evaluation (D6-M11):** the orchestrator harness calls `shouldTriggerSpecialist(specialist, changedFiles, projectType)` from `src/pipeline/pipelineContext.ts` to evaluate whether each specialist applies to the current change set. The function returns `{ triggered: boolean, reasons: string[] }` and consumes the same `SPECIALIST_TRIGGER_TABLE` that the prose table below mirrors. Treat the prose as a quick reference; treat the TS predicate as the authoritative gate. `npm run validate:specialist-roster` enforces parity.
|
|
121
|
+
**Runtime trigger evaluation (D6-M11):** the orchestrator harness calls `shouldTriggerSpecialist(specialist, changedFiles, projectType)` from `src/pipeline/pipelineContext.ts` to evaluate whether each specialist applies to the current change set. The function returns `{ triggered: boolean, reasons: string[], mandatory?: boolean }` and consumes the same `SPECIALIST_TRIGGER_TABLE` that the prose table below mirrors. Treat the prose as a quick reference; treat the TS predicate as the authoritative gate. `npm run validate:specialist-roster` enforces parity. The orchestrator treats `mandatory: true` as non-skippable at Tier 2/3.
|
|
122
122
|
|
|
123
123
|
**Phase 4 Specialist Trigger Table:**
|
|
124
124
|
|
|
@@ -128,8 +128,8 @@ Launch Phase 4 specialists in parallel, bounded by an orchestrator-honored fan-o
|
|
|
128
128
|
| `hatch3r-lint-fixer` | Conditional | Lint/type errors present |
|
|
129
129
|
| `hatch3r-architect` | Conditional | Architectural decisions, new modules/services |
|
|
130
130
|
| `hatch3r-devops` | Conditional | CI/CD or infrastructure changes |
|
|
131
|
-
| `hatch3r-ui` (CQ1) |
|
|
132
|
-
| `hatch3r-ux` (CQ2) |
|
|
131
|
+
| `hatch3r-ui` (CQ1) | Mandatory-on-match | UI component / theme / token files modified (`*.{tsx,jsx,vue,svelte}`, `tailwind.config.*`, design-token registries) |
|
|
132
|
+
| `hatch3r-ux` (CQ2) | Mandatory-on-match | Flow / modal / route-transition / error-state files modified; microcopy or i18n strings changed |
|
|
133
133
|
| `hatch3r-security` (CQ3) | Always | Any code change (always-mode floor — absorbs legacy security-auditor scope); auth / JWT / OAuth / WebAuthn code modified; release workflow modified; cookie or session handling modified; dependency files modified |
|
|
134
134
|
| `hatch3r-reliability` (CQ4) | Conditional | Service handler / OTel / SLO / retry / circuit-breaker code modified; Kubernetes probe manifests modified |
|
|
135
135
|
| `hatch3r-testability` (CQ5) | Always | Any code change (always-mode floor — absorbs legacy test-writer scope); test code added or modified; mandate-map feature class introduced; coverage threshold or runner config modified |
|
|
@@ -173,9 +173,9 @@ Default is **linear per task** (Phase 1 → 2 → 3 → 4 serially) — `Pipelin
|
|
|
173
173
|
|
|
174
174
|
### Three Conditions to Parallelize
|
|
175
175
|
|
|
176
|
-
ALL three must hold: (1) **read-only or disjoint writes** (no conflict zone); (2) **deterministic aggregation** (outputs merge without orchestrator intervention — tests pass-if-all-pass, findings union); (3) **no shared mutable state** (agents that mutate `PipelineContext.state`/`featureFlags`/`metadata` serialize; parallel agents only READ).
|
|
176
|
+
ALL three must hold: (1) **read-only or disjoint writes, at file AND contract granularity** (no conflict zone: two lanes are NOT disjoint when their file-disjoint diffs mutate the same shared contract — exported symbol, persisted collection/field name, wire field, event schema, shared constant; on contract overlap, assign one seam owner or serialize per `rules/hatch3r-contract-census.md` → Seam-Owner Protocol); (2) **deterministic aggregation** (outputs merge without orchestrator intervention — tests pass-if-all-pass, findings union); (3) **no shared mutable state** (agents that mutate `PipelineContext.state`/`featureFlags`/`metadata` serialize; parallel agents only READ).
|
|
177
177
|
|
|
178
|
-
**Parallel-safe:** Phase 4 specialists; intra-Phase-1 researcher modes on a self-contained task; per-module Phase 2 fan-out on disjoint `affectedFiles` (merged post-Phase-2); Tier 2/3 elicitation researchers (outputs tagged with confidence + perspective). **NOT parallel-safe:** cross-phase execution (each phase depends on the prior's output); Phase 3 review-loop iterations (reviewer → fixer → re-reviewer serial); overlapping-file implementers (serialize or use a merge-conflict gate); Phase 4 validation re-review.
|
|
178
|
+
**Parallel-safe:** Phase 4 specialists; intra-Phase-1 researcher modes on a self-contained task; per-module Phase 2 fan-out on disjoint `affectedFiles` AND disjoint contract sets (merged post-Phase-2); Tier 2/3 elicitation researchers (outputs tagged with confidence + perspective). **NOT parallel-safe:** cross-phase execution (each phase depends on the prior's output); Phase 3 review-loop iterations (reviewer → fixer → re-reviewer serial); overlapping-file implementers (serialize or use a merge-conflict gate); contract-overlapping implementers even when file-disjoint (one seam owner mutates, peers consume — `rules/hatch3r-contract-census.md`); Phase 4 validation re-review.
|
|
179
179
|
|
|
180
180
|
**Cost-Dominance Principle.** Token cost of sub-agent invocation never justifies serialization of independent work. The three safety conditions govern WHEN parallelism is safe; cost does not govern WHETHER to parallelize. When in doubt, fan out. Serialization is only valid on true dependency edges.
|
|
181
181
|
|
|
@@ -183,13 +183,13 @@ ALL three must hold: (1) **read-only or disjoint writes** (no conflict zone); (2
|
|
|
183
183
|
|
|
184
184
|
### Concurrent Invocation Handling
|
|
185
185
|
|
|
186
|
-
Two top-level pipelines running at once (e.g. `hatch3r-workflow` in one shell, `hatch3r-board-pickup` in another) are bounded by the same three conditions, applied cross-pipeline (D7-SA7.5-F7.5.6): (1) **Advisory lock-note (best-effort, NOT atomic — D7-27)** — before Phase 1, the orchestrator writes/reads `.hatch3r/.lock` (JSON: `pid`, `command`, `branch`, `correlation_id`, `started_at`); clear on completion/abort; treat a note older than 6h as stale. This is an advisory coordination note, not a mutual-exclusion primitive: there is no `hatch3r` lock verb and no atomic acquire in `src/` (the only cross-process lock that ships is `acquireWriteLock` in `src/merge/safeWrite.ts`, scoped to single-file atomic writes, not top-level pipelines), so the LLM orchestrator's read-then-write is TOCTOU by construction and `src/cli/commands/status.ts` already labels this file "advisory". It exists to surface a likely collision, never to guarantee exclusion. (2) **Detect-then-warn** — if a live note names the same branch or an open `.hatch3r/hatch.json` board transaction, WARN and ASK (proceed on a separate branch / wait / abort); never silently co-mutate shared state. (3) **True isolation via worktree, not the lock-note (D7-27)** — when concurrency must actually be conflict-free rather than merely warned (the parallel-implementer path), route each pipeline through `hatch3r worktree-setup <name>` — the isolation primitive hatch3r already ships (`src/cli/commands/worktreeSetup.ts`; `commands/board/pickup-delegation-multi.md` already uses it per implementer) — so the pipelines write disjoint working trees and integrate back on completion, satisfying the disjoint-writes safety condition without relying on the non-atomic note. (4) **Cache-sharing** — `.hatch3r/learnings/` is read-many, write-once-at-completion with timestamp-ordered conflict resolution. Cross-task context sharing is bounded by the no-shared-mutable-state condition: learnings consolidate at pipeline completion; mid-pipeline writes are out of scope to preserve parallel-safety determinism (D7-SA7.5-F7.5.8). Each command's Guardrails cite this subsection.
|
|
186
|
+
Two top-level pipelines running at once (e.g. `hatch3r-workflow` in one shell, `hatch3r-board-pickup` in another) are bounded by the same three conditions, applied cross-pipeline (D7-SA7.5-F7.5.6): (1) **Advisory lock-note (best-effort, NOT atomic — D7-27)** — before Phase 1, the orchestrator writes/reads `.hatch3r/.lock` (JSON: `pid`, `command`, `branch`, `correlation_id`, `started_at`); clear on completion/abort; treat a note older than 6h as stale. This is an advisory coordination note, not a mutual-exclusion primitive: there is no `hatch3r` lock verb and no atomic acquire in `src/` (the only cross-process lock that ships is `acquireWriteLock` in `src/merge/safeWrite.ts`, scoped to single-file atomic writes, not top-level pipelines), so the LLM orchestrator's read-then-write is TOCTOU by construction and `src/cli/commands/status.ts` already labels this file "advisory". It exists to surface a likely collision, never to guarantee exclusion. (2) **Detect-then-warn** — if a live note names the same branch or an open `.hatch3r/hatch.json` board transaction, WARN and ASK (proceed on a separate branch / wait / abort); never silently co-mutate shared state. (3) **True isolation via worktree, not the lock-note (D7-27)** — when concurrency must actually be conflict-free rather than merely warned (the parallel-implementer path), route each pipeline through `hatch3r worktree-setup <name>` — the isolation primitive hatch3r already ships (`src/cli/commands/worktreeSetup.ts`; `commands/board/pickup-delegation-multi.md` already uses it per implementer) — so the pipelines write disjoint working trees and integrate back on completion, satisfying the disjoint-writes safety condition without relying on the non-atomic note. Worktree isolation guarantees FILE-level disjointness only — it cannot detect two lanes mutating the same shared contract (a persisted collection name, an exported store symbol, a wire field) from different files; contract disjointness is established before dispatch and re-checked at lane exit per `rules/hatch3r-contract-census.md`. (4) **Cache-sharing** — `.hatch3r/learnings/` is read-many, write-once-at-completion with timestamp-ordered conflict resolution. Cross-task context sharing is bounded by the no-shared-mutable-state condition: learnings consolidate at pipeline completion; mid-pipeline writes are out of scope to preserve parallel-safety determinism (D7-SA7.5-F7.5.8). Each command's Guardrails cite this subsection.
|
|
187
187
|
|
|
188
188
|
## Cross-Phase Error Propagation
|
|
189
189
|
|
|
190
|
-
On a non-SUCCESS status, the orchestrator MUST propagate error context downstream, never silently drop it. **Phase 1 PARTIAL:** include `researchGaps` in the implementer prompt and set confidence expectations accordingly. **Phase 2 PARTIAL:** include `reason` + unimplemented acceptance criteria in the reviewer prompt (reviewer distinguishes "not done yet" from "done incorrectly"). **Phase 3 UNRESOLVED:** include the unresolved findings in Phase 4 specialist prompts (specialists must not conflict with known issues). **Phase 4 specialist FAILED:** include the failure reason when surfacing — never report "Phase 4 failed" without naming which specialist and why.
|
|
190
|
+
On a non-SUCCESS status, the orchestrator MUST propagate error context downstream, never silently drop it. **Phase 1 PARTIAL:** include `researchGaps` in the implementer prompt and set confidence expectations accordingly. **Phase 2 PARTIAL:** include `reason` + unimplemented acceptance criteria in the reviewer prompt (reviewer distinguishes "not done yet" from "done incorrectly"). **Phase 3 UNRESOLVED:** include the unresolved findings in Phase 4 specialist prompts (specialists must not conflict with known issues). Unresolved findings persist as ledger rows (`rules/hatch3r-findings-ledger.md`); Phase 4 prompts carry the open `finding_id` list. **Phase 4 specialist FAILED:** include the failure reason when surfacing — never report "Phase 4 failed" without naming which specialist and why.
|
|
191
191
|
|
|
192
|
-
**Sub-agent-failure handling (shared clause; all commands cite this — never inline).** When any spawned implementer/fixer/specialist sub-agent FAILS or returns no usable output: (1) retry once with the same prompt; (2) if the retry fails, re-spawn `hatch3r-fixer` (Phase 3) with the failure reason + partial output as failure context — `hatch3r-fixer` is the code-mutation path, so the work stays delegated; (3) if the re-spawn also fails, emit `BLOCKED_OTHER` with a one-sentence reason and ASK the user (fix-manually vs adjust-scope vs accept-risk). The orchestrator MUST NOT fall back to inline implementation — that is the issue #73 bypass mode (see Mandatory Delegation Directive). The sole exception is `hatch3r-quick-change`, whose Tier-1 carve-out permits inline retry per its declared scope.
|
|
192
|
+
**Sub-agent-failure handling (shared clause; all commands cite this — never inline).** When any spawned implementer/fixer/specialist sub-agent FAILS or returns no usable output: (1) retry once with the same prompt; (2) if the retry fails, re-spawn `hatch3r-fixer` (Phase 3) with the failure reason + partial output as failure context — `hatch3r-fixer` is the code-mutation path, so the work stays delegated; (3) if the re-spawn also fails, emit `BLOCKED_OTHER` with a one-sentence reason and ASK the user (fix-manually vs adjust-scope vs accept-risk). Flush in-flight ledger rows per W4 — before the retry and again before the BLOCKED_OTHER ASK (`rules/hatch3r-findings-ledger.md`). The orchestrator MUST NOT fall back to inline implementation — that is the issue #73 bypass mode (see Mandatory Delegation Directive). The sole exception is `hatch3r-quick-change`, whose Tier-1 carve-out permits inline retry per its declared scope.
|
|
193
193
|
|
|
194
194
|
## Correlation ID
|
|
195
195
|
|
|
@@ -247,4 +247,4 @@ All `scope: always` rules apply to every task including sub-agent work; include
|
|
|
247
247
|
|
|
248
248
|
- **Tier 1 — always include (every sub-agent):** `hatch3r-security-patterns`, `hatch3r-code-standards`.
|
|
249
249
|
- **Tier 2 — by phase:** `hatch3r-testing` (testability/implementer/reviewer); `hatch3r-accessibility-standards` (ui, UI reviewer); `hatch3r-git-conventions` (orchestrator git ops); `hatch3r-ci-cd` (ci-watcher/devops); `hatch3r-dependency-management` (security CQ3 supply-chain slice).
|
|
250
|
-
- **Tier 3 — on-demand by role + scope:** `hatch3r-api-design`, `hatch3r-secrets-management`, `hatch3r-data-classification`, `hatch3r-performance-budgets`, `hatch3r-browser-verification`, `hatch3r-component-conventions`, `hatch3r-i18n`, `hatch3r-theming`, `hatch3r-migrations`, `hatch3r-feature-flags`, `hatch3r-observability-logging`, `hatch3r-observability-metrics`, `hatch3r-observability-tracing`.
|
|
250
|
+
- **Tier 3 — on-demand by role + scope:** `hatch3r-api-design`, `hatch3r-secrets-management`, `hatch3r-data-classification`, `hatch3r-performance-budgets`, `hatch3r-browser-verification`, `hatch3r-component-conventions`, `hatch3r-i18n`, `hatch3r-theming`, `hatch3r-migrations`, `hatch3r-feature-flags`, `hatch3r-observability-logging`, `hatch3r-observability-metrics`, `hatch3r-observability-tracing`, `hatch3r-dynamic-stack-verification`.
|
|
@@ -34,7 +34,7 @@ Score task complexity per the `hatch3r-deep-context` rule before Phase 1. Apply
|
|
|
34
34
|
- **Tier 2 hard gate (B1).** Before Phase 2, run `hatch3r-researcher` with `requirements-elicitation:quick` mode to detect ambiguity. The researcher sub-agent emits the elicited questions as a structured list in its result — it does NOT call the platform-native question tool (a spawned sub-agent has no interactive surface). The **orchestrator** renders that list to the user via the platform-native question tool (per `agents/shared/user-question-protocol.md`), mirroring `commands/hatch3r-workflow.md` Phase 1 "Present the `requirements-elicitation` questions inline and await answers". Orchestrator awaits answers and integrates them into the Phase 1 brief; do not begin Phase 2 with unresolved questions. Tier 1 is exempt only when scope is single-file, single-concern, and acceptance is testable from the user message alone.
|
|
35
35
|
- **Tier 3 (Deep):** Present Pre-Implementation Summary and ASK for confirmation. Do NOT proceed until all unresolved questions are answered.
|
|
36
36
|
|
|
37
|
-
**Tier-to-Phase-4 specialist depth mapping** (Finding D7-M9 / D7-SA7.4-1). Deep-context tier drives Phase 1 researcher depth; the same tier drives Phase 4 specialist depth so quality coverage scales with task risk: Tier 1 → run only the always-mode floor (`hatch3r-security` + `hatch3r-testability`) at `quick` depth — UI/perf/maintainability/etc. specialists are skipped per Phase Skip Criteria. Tier 2 → always-mode floor at `standard` depth + every triggered conditional specialist at `quick` depth. Tier 3 → every applicable specialist at `deep` depth — full WCAG AA / OWASP ASI / CWV / mandate-map sweep with N=3 sampling on always-mode specialists when `floor:security` items are touched (per `agents/shared/quality-charter.md` -> Non-Determinism Budget). The depth signal rides on the specialist prompt as the explicit field `depth: quick | standard | deep`; specialists read it via the shared `agents/shared/quality-specialist-frame.md`. Tier also drives **model class** as a first-order effort lever (Tier 1 → economy, Tier 2 → default, Tier 3 → strongest), resolved per-adapter against `models.default` / `src/models/resolve.ts` and ignored where an adapter has no model-routing surface — see `hatch3r-deep-context` -> Tier Assignment.
|
|
37
|
+
**Tier-to-Phase-4 specialist depth mapping** (Finding D7-M9 / D7-SA7.4-1). Deep-context tier drives Phase 1 researcher depth; the same tier drives Phase 4 specialist depth so quality coverage scales with task risk: Tier 1 → run only the always-mode floor (`hatch3r-security` + `hatch3r-testability`) at `quick` depth — UI/perf/maintainability/etc. specialists (mandatory-on-match included) are skipped per Phase Skip Criteria. Tier 2 → always-mode floor at `standard` depth + every triggered conditional specialist at `quick` depth, and a triggered mandatory-on-match specialist (`hatch3r-ui` CQ1 / `hatch3r-ux` CQ2) MUST spawn as its own dedicated sub-agent instance (never merged into one spawn) — skipping a triggered one at Tier 2/3 is a gate failure. Tier 3 → every applicable specialist at `deep` depth (same mandatory-on-match mandate) — full WCAG AA / OWASP ASI / CWV / mandate-map sweep with N=3 sampling on always-mode specialists when `floor:security` items are touched (per `agents/shared/quality-charter.md` -> Non-Determinism Budget). The depth signal rides on the specialist prompt as the explicit field `depth: quick | standard | deep`; specialists read it via the shared `agents/shared/quality-specialist-frame.md`. Tier also drives **model class** as a first-order effort lever (Tier 1 → economy, Tier 2 → default, Tier 3 → strongest), resolved per-adapter against `models.default` / `src/models/resolve.ts` and ignored where an adapter has no model-routing surface — see `hatch3r-deep-context` -> Tier Assignment.
|
|
38
38
|
|
|
39
39
|
## Mandatory Delegation Directives
|
|
40
40
|
|
|
@@ -44,7 +44,7 @@ Spawn `hatch3r-researcher` before implementing any task (skip only for trivial s
|
|
|
44
44
|
|
|
45
45
|
### Research Completeness Checklist
|
|
46
46
|
|
|
47
|
-
Before Phase 1 to Phase 2 handoff, verify all
|
|
47
|
+
Before Phase 1 to Phase 2 handoff, verify all five: (1) **affected files identified** (create/modify/delete listed); (2) **blast radius assessed** (downstream consumers + integration points documented); (3) **existing tests located** (or absence noted); (4) **dependencies mapped** (internal + external); (5) **shared contracts inventoried** (every contract the change will mutate — exported symbol, persisted name, wire field, event schema, shared constant — listed with a first-pass consumer grep count per `rules/hatch3r-contract-census.md` → Shared-Contract Taxonomy). If any item is unconfirmed, re-run researcher with additional modes or surface to user.
|
|
48
48
|
|
|
49
49
|
### Implementation Delegation
|
|
50
50
|
|
|
@@ -100,20 +100,20 @@ For multi-sub-task implementations, the implementer performs a lightweight mini-
|
|
|
100
100
|
**Phase 3 — Review Loop:**
|
|
101
101
|
|
|
102
102
|
1. Spawn `hatch3r-reviewer` with diff, acceptance criteria, and blast-radius summary.
|
|
103
|
-
2. Critical/Warning findings: spawn `hatch3r-fixer` with full reviewer output, then re-review. Repeat until 0 Critical + 0 Warning, or max 4 iterations (matches `DEFAULT_MAX_REVIEW_ITERATIONS` in `src/pipeline/reviewLoop.ts`, raised 3→4 in Cycle 7.5 W2B2 H26 to reach the oscillation detector in default config; kept in sync by `src/__tests__/pipeline/reviewLoop.test.ts`, CI-enforced).
|
|
103
|
+
2. Critical/Warning findings: spawn `hatch3r-fixer` with full reviewer output, then re-review. Repeat until 0 Critical + 0 Warning, or max 4 iterations (matches `DEFAULT_MAX_REVIEW_ITERATIONS` in `src/pipeline/reviewLoop.ts`, raised 3→4 in Cycle 7.5 W2B2 H26 to reach the oscillation detector in default config; kept in sync by `src/__tests__/pipeline/reviewLoop.test.ts`, CI-enforced). Before each fixer dispatch, append the W1 write-ahead rows; after each re-review, append the W2 disposition rows (`rules/hatch3r-findings-ledger.md` → Write Points).
|
|
104
104
|
- **Re-run honor-rule (anti-self-approval, F15.2-H2 / D13-SA13.2-F6 / D15-SA15.2-F3).** The fixer's `Reviewer re-run required` boolean is advisory; the orchestrator derives the authoritative value `reRunRequired = (fixer Files changed list is non-empty)`. When `true`, another `hatch3r-reviewer` pass is MANDATORY before the loop may exit clean — a fixer `Status: SUCCESS` with a non-empty `Files changed` can never self-approve to a clean exit. A `Reviewer re-run required: false` printed alongside a non-empty `Files changed` is overridden to `true` and noted as a self-declared protocol violation. The `Files changed` list is SSOT-bound: it is attested by the same fixer `delegation_proof_id` the orchestrator quotes in its End-of-Turn Delegation Attestation, so the signal cannot be forged without spawning the fixer.
|
|
105
105
|
3. **Confirmation pass** after clean review: lightweight re-review checking only (a) no new test failures vs Phase 2 baseline, (b) no type errors introduced, (c) acceptance criteria still met. Does not re-run the full checklist.
|
|
106
106
|
- **Runtime calibration second pass (orchestrator-owned).** At this would-be-clean exit, the orchestrator — not the stateless reviewer — evaluates the `rules/hatch3r-reviewer-calibration.md` trigger: read the cross-run `consecutive_clean_pass_count` from `.hatch3r/calibration-state.json`, increment it for this clean run, and fire a second-pass review (different model class, else same-class re-roll) when the post-increment count is a multiple of `N` (default 5) OR — for a high-risk diff (`floor:security` / auth / CQ3-security-dispatch files) — on the first clean PASS. A divergent second pass reverts the exit to step 2 (`REQUEST CHANGES`) and resets the count to 0; persist the count (atomic write via `src/merge/safeWrite.ts`) and append the calibration-log record. A REQUEST CHANGES or DESIGN_OBJECTION at any iteration also resets the persisted count to 0.
|
|
107
|
-
4. Max iterations reached: surface to user with a structured summary (iteration count, remaining Critical findings with file:line, remaining Warnings, fix-manually-vs-accept-risk recommendation). Never present raw reviewer output unsummarized.
|
|
107
|
+
4. Max iterations reached: surface to user with a structured summary (iteration count, remaining Critical findings with file:line, remaining Warnings, fix-manually-vs-accept-risk recommendation). Never present raw reviewer output unsummarized. Reconcile the ledger to the run-exit invariant (W3) before surfacing; the structured summary lists the open `finding_id`s.
|
|
108
108
|
5. **Review gate confidence signal:** on a clean verdict, record the iteration count in `PipelineContext.reviewResult.iterations`. Clean-on-first-pass signals higher confidence than clean-after-multiple-iterations; Phase 4 and the orchestrator factor this into risk assessment.
|
|
109
109
|
|
|
110
110
|
**Phase 4 — Final Quality** (after review loop is clean):
|
|
111
111
|
|
|
112
|
-
Launch Phase 4 specialists in parallel, bounded by an orchestrator-honored fan-out width `max_phase4_parallel` (default `8` — covers the empirical maximum of applicable specialists per the trigger table, so a typical Tier 3 change fans out in at most 2 batches). This bound is LLM-honored orchestrator guidance, not a code-enforced cap: the host Task tool is the actual dispatcher and applies no platform fan-out limit, so no hatch3r module reads an env var or clamps the count — the orchestrator self-limits per this prose. The bound exists for upstream provider rate-limit headroom (RPM/TPM) — a true dependency edge — NOT per-orchestrator context cost; token cost never serializes independent work (P8 dominates P7). A non-rate-limited orchestrator MAY raise the width up to the full applicable-specialist set. **Rate-limit back-off (orchestrator-LLM guidance):** when the orchestrator observes ≥3 consecutive rate-limit-class transient failures, reduce the active fan-out width by 1 for the next batch and record the back-off in the Iteration Summary; never silently cap a healthy run. When applicable specialists exceed the bound, batch by severity-descending priority `CRITICAL → HIGH → MEDIUM → LOW` (severity is the worst-case finding class the specialist surfaces: always-on testability (CQ5) / security (CQ3) → CRITICAL,
|
|
112
|
+
Launch Phase 4 specialists in parallel, bounded by an orchestrator-honored fan-out width `max_phase4_parallel` (default `8` — covers the empirical maximum of applicable specialists per the trigger table, so a typical Tier 3 change fans out in at most 2 batches). This bound is LLM-honored orchestrator guidance, not a code-enforced cap: the host Task tool is the actual dispatcher and applies no platform fan-out limit, so no hatch3r module reads an env var or clamps the count — the orchestrator self-limits per this prose. The bound exists for upstream provider rate-limit headroom (RPM/TPM) — a true dependency edge — NOT per-orchestrator context cost; token cost never serializes independent work (P8 dominates P7). A non-rate-limited orchestrator MAY raise the width up to the full applicable-specialist set. **Rate-limit back-off (orchestrator-LLM guidance):** when the orchestrator observes ≥3 consecutive rate-limit-class transient failures, reduce the active fan-out width by 1 for the next batch and record the back-off in the Iteration Summary; never silently cap a healthy run. When applicable specialists exceed the bound, batch by severity-descending priority `CRITICAL → HIGH → MEDIUM → LOW` (severity is the worst-case finding class the specialist surfaces: always-on testability (CQ5) / security (CQ3) → CRITICAL, mandatory-on-match CQ1/CQ2 (ui/ux) + conditional CQ4/CQ7 (reliability/performance) → HIGH, docs/lint → MEDIUM, low-impact → LOW); within a bucket, dispatch in trigger-table order. Each batch runs to completion before the next starts; the validation pass runs once after the final batch. The applicable specialists and their trigger conditions are listed in the Phase 4 Specialist Trigger Table below. The width bound and the rate-limit back-off never drop a triggered mandatory-on-match specialist — `hatch3r-ui`/`hatch3r-ux` dispatch as dedicated instances in the first HIGH batch.
|
|
113
113
|
|
|
114
114
|
**Specialist Prompt Enrichment:** When spawning Phase 4 specialists, include the Phase 2 `filesChanged` list (focus on affected code), the Phase 3 review verdict summary (avoid re-flagging reviewed issues), and `researchFindings.blastRadius` (assess downstream impact).
|
|
115
115
|
|
|
116
|
-
**Runtime trigger evaluation (D6-M11):** the orchestrator harness calls `shouldTriggerSpecialist(specialist, changedFiles, projectType)` from `src/pipeline/pipelineContext.ts` to evaluate whether each specialist applies to the current change set. The function returns `{ triggered: boolean, reasons: string[] }` and consumes the same `SPECIALIST_TRIGGER_TABLE` that the prose table below mirrors. Treat the prose as a quick reference; treat the TS predicate as the authoritative gate. `npm run validate:specialist-roster` enforces parity.
|
|
116
|
+
**Runtime trigger evaluation (D6-M11):** the orchestrator harness calls `shouldTriggerSpecialist(specialist, changedFiles, projectType)` from `src/pipeline/pipelineContext.ts` to evaluate whether each specialist applies to the current change set. The function returns `{ triggered: boolean, reasons: string[], mandatory?: boolean }` and consumes the same `SPECIALIST_TRIGGER_TABLE` that the prose table below mirrors. Treat the prose as a quick reference; treat the TS predicate as the authoritative gate. `npm run validate:specialist-roster` enforces parity. The orchestrator treats `mandatory: true` as non-skippable at Tier 2/3.
|
|
117
117
|
|
|
118
118
|
**Phase 4 Specialist Trigger Table:**
|
|
119
119
|
|
|
@@ -123,8 +123,8 @@ Launch Phase 4 specialists in parallel, bounded by an orchestrator-honored fan-o
|
|
|
123
123
|
| `hatch3r-lint-fixer` | Conditional | Lint/type errors present |
|
|
124
124
|
| `hatch3r-architect` | Conditional | Architectural decisions, new modules/services |
|
|
125
125
|
| `hatch3r-devops` | Conditional | CI/CD or infrastructure changes |
|
|
126
|
-
| `hatch3r-ui` (CQ1) |
|
|
127
|
-
| `hatch3r-ux` (CQ2) |
|
|
126
|
+
| `hatch3r-ui` (CQ1) | Mandatory-on-match | UI component / theme / token files modified (`*.{tsx,jsx,vue,svelte}`, `tailwind.config.*`, design-token registries) |
|
|
127
|
+
| `hatch3r-ux` (CQ2) | Mandatory-on-match | Flow / modal / route-transition / error-state files modified; microcopy or i18n strings changed |
|
|
128
128
|
| `hatch3r-security` (CQ3) | Always | Any code change (always-mode floor — absorbs legacy security-auditor scope); auth / JWT / OAuth / WebAuthn code modified; release workflow modified; cookie or session handling modified; dependency files modified |
|
|
129
129
|
| `hatch3r-reliability` (CQ4) | Conditional | Service handler / OTel / SLO / retry / circuit-breaker code modified; Kubernetes probe manifests modified |
|
|
130
130
|
| `hatch3r-testability` (CQ5) | Always | Any code change (always-mode floor — absorbs legacy test-writer scope); test code added or modified; mandate-map feature class introduced; coverage threshold or runner config modified |
|
|
@@ -168,9 +168,9 @@ Default is **linear per task** (Phase 1 → 2 → 3 → 4 serially) — `Pipelin
|
|
|
168
168
|
|
|
169
169
|
### Three Conditions to Parallelize
|
|
170
170
|
|
|
171
|
-
ALL three must hold: (1) **read-only or disjoint writes** (no conflict zone); (2) **deterministic aggregation** (outputs merge without orchestrator intervention — tests pass-if-all-pass, findings union); (3) **no shared mutable state** (agents that mutate `PipelineContext.state`/`featureFlags`/`metadata` serialize; parallel agents only READ).
|
|
171
|
+
ALL three must hold: (1) **read-only or disjoint writes, at file AND contract granularity** (no conflict zone: two lanes are NOT disjoint when their file-disjoint diffs mutate the same shared contract — exported symbol, persisted collection/field name, wire field, event schema, shared constant; on contract overlap, assign one seam owner or serialize per `rules/hatch3r-contract-census.md` → Seam-Owner Protocol); (2) **deterministic aggregation** (outputs merge without orchestrator intervention — tests pass-if-all-pass, findings union); (3) **no shared mutable state** (agents that mutate `PipelineContext.state`/`featureFlags`/`metadata` serialize; parallel agents only READ).
|
|
172
172
|
|
|
173
|
-
**Parallel-safe:** Phase 4 specialists; intra-Phase-1 researcher modes on a self-contained task; per-module Phase 2 fan-out on disjoint `affectedFiles` (merged post-Phase-2); Tier 2/3 elicitation researchers (outputs tagged with confidence + perspective). **NOT parallel-safe:** cross-phase execution (each phase depends on the prior's output); Phase 3 review-loop iterations (reviewer → fixer → re-reviewer serial); overlapping-file implementers (serialize or use a merge-conflict gate); Phase 4 validation re-review.
|
|
173
|
+
**Parallel-safe:** Phase 4 specialists; intra-Phase-1 researcher modes on a self-contained task; per-module Phase 2 fan-out on disjoint `affectedFiles` AND disjoint contract sets (merged post-Phase-2); Tier 2/3 elicitation researchers (outputs tagged with confidence + perspective). **NOT parallel-safe:** cross-phase execution (each phase depends on the prior's output); Phase 3 review-loop iterations (reviewer → fixer → re-reviewer serial); overlapping-file implementers (serialize or use a merge-conflict gate); contract-overlapping implementers even when file-disjoint (one seam owner mutates, peers consume — `rules/hatch3r-contract-census.md`); Phase 4 validation re-review.
|
|
174
174
|
|
|
175
175
|
**Cost-Dominance Principle.** Token cost of sub-agent invocation never justifies serialization of independent work. The three safety conditions govern WHEN parallelism is safe; cost does not govern WHETHER to parallelize. When in doubt, fan out. Serialization is only valid on true dependency edges.
|
|
176
176
|
|
|
@@ -178,13 +178,13 @@ ALL three must hold: (1) **read-only or disjoint writes** (no conflict zone); (2
|
|
|
178
178
|
|
|
179
179
|
### Concurrent Invocation Handling
|
|
180
180
|
|
|
181
|
-
Two top-level pipelines running at once (e.g. `hatch3r-workflow` in one shell, `hatch3r-board-pickup` in another) are bounded by the same three conditions, applied cross-pipeline (D7-SA7.5-F7.5.6): (1) **Advisory lock-note (best-effort, NOT atomic — D7-27)** — before Phase 1, the orchestrator writes/reads `.hatch3r/.lock` (JSON: `pid`, `command`, `branch`, `correlation_id`, `started_at`); clear on completion/abort; treat a note older than 6h as stale. This is an advisory coordination note, not a mutual-exclusion primitive: there is no `hatch3r` lock verb and no atomic acquire in `src/` (the only cross-process lock that ships is `acquireWriteLock` in `src/merge/safeWrite.ts`, scoped to single-file atomic writes, not top-level pipelines), so the LLM orchestrator's read-then-write is TOCTOU by construction and `src/cli/commands/status.ts` already labels this file "advisory". It exists to surface a likely collision, never to guarantee exclusion. (2) **Detect-then-warn** — if a live note names the same branch or an open `.hatch3r/hatch.json` board transaction, WARN and ASK (proceed on a separate branch / wait / abort); never silently co-mutate shared state. (3) **True isolation via worktree, not the lock-note (D7-27)** — when concurrency must actually be conflict-free rather than merely warned (the parallel-implementer path), route each pipeline through `hatch3r worktree-setup <name>` — the isolation primitive hatch3r already ships (`src/cli/commands/worktreeSetup.ts`; `commands/board/pickup-delegation-multi.md` already uses it per implementer) — so the pipelines write disjoint working trees and integrate back on completion, satisfying the disjoint-writes safety condition without relying on the non-atomic note. (4) **Cache-sharing** — `.hatch3r/learnings/` is read-many, write-once-at-completion with timestamp-ordered conflict resolution. Cross-task context sharing is bounded by the no-shared-mutable-state condition: learnings consolidate at pipeline completion; mid-pipeline writes are out of scope to preserve parallel-safety determinism (D7-SA7.5-F7.5.8). Each command's Guardrails cite this subsection.
|
|
181
|
+
Two top-level pipelines running at once (e.g. `hatch3r-workflow` in one shell, `hatch3r-board-pickup` in another) are bounded by the same three conditions, applied cross-pipeline (D7-SA7.5-F7.5.6): (1) **Advisory lock-note (best-effort, NOT atomic — D7-27)** — before Phase 1, the orchestrator writes/reads `.hatch3r/.lock` (JSON: `pid`, `command`, `branch`, `correlation_id`, `started_at`); clear on completion/abort; treat a note older than 6h as stale. This is an advisory coordination note, not a mutual-exclusion primitive: there is no `hatch3r` lock verb and no atomic acquire in `src/` (the only cross-process lock that ships is `acquireWriteLock` in `src/merge/safeWrite.ts`, scoped to single-file atomic writes, not top-level pipelines), so the LLM orchestrator's read-then-write is TOCTOU by construction and `src/cli/commands/status.ts` already labels this file "advisory". It exists to surface a likely collision, never to guarantee exclusion. (2) **Detect-then-warn** — if a live note names the same branch or an open `.hatch3r/hatch.json` board transaction, WARN and ASK (proceed on a separate branch / wait / abort); never silently co-mutate shared state. (3) **True isolation via worktree, not the lock-note (D7-27)** — when concurrency must actually be conflict-free rather than merely warned (the parallel-implementer path), route each pipeline through `hatch3r worktree-setup <name>` — the isolation primitive hatch3r already ships (`src/cli/commands/worktreeSetup.ts`; `commands/board/pickup-delegation-multi.md` already uses it per implementer) — so the pipelines write disjoint working trees and integrate back on completion, satisfying the disjoint-writes safety condition without relying on the non-atomic note. Worktree isolation guarantees FILE-level disjointness only — it cannot detect two lanes mutating the same shared contract (a persisted collection name, an exported store symbol, a wire field) from different files; contract disjointness is established before dispatch and re-checked at lane exit per `rules/hatch3r-contract-census.md`. (4) **Cache-sharing** — `.hatch3r/learnings/` is read-many, write-once-at-completion with timestamp-ordered conflict resolution. Cross-task context sharing is bounded by the no-shared-mutable-state condition: learnings consolidate at pipeline completion; mid-pipeline writes are out of scope to preserve parallel-safety determinism (D7-SA7.5-F7.5.8). Each command's Guardrails cite this subsection.
|
|
182
182
|
|
|
183
183
|
## Cross-Phase Error Propagation
|
|
184
184
|
|
|
185
|
-
On a non-SUCCESS status, the orchestrator MUST propagate error context downstream, never silently drop it. **Phase 1 PARTIAL:** include `researchGaps` in the implementer prompt and set confidence expectations accordingly. **Phase 2 PARTIAL:** include `reason` + unimplemented acceptance criteria in the reviewer prompt (reviewer distinguishes "not done yet" from "done incorrectly"). **Phase 3 UNRESOLVED:** include the unresolved findings in Phase 4 specialist prompts (specialists must not conflict with known issues). **Phase 4 specialist FAILED:** include the failure reason when surfacing — never report "Phase 4 failed" without naming which specialist and why.
|
|
185
|
+
On a non-SUCCESS status, the orchestrator MUST propagate error context downstream, never silently drop it. **Phase 1 PARTIAL:** include `researchGaps` in the implementer prompt and set confidence expectations accordingly. **Phase 2 PARTIAL:** include `reason` + unimplemented acceptance criteria in the reviewer prompt (reviewer distinguishes "not done yet" from "done incorrectly"). **Phase 3 UNRESOLVED:** include the unresolved findings in Phase 4 specialist prompts (specialists must not conflict with known issues). Unresolved findings persist as ledger rows (`rules/hatch3r-findings-ledger.md`); Phase 4 prompts carry the open `finding_id` list. **Phase 4 specialist FAILED:** include the failure reason when surfacing — never report "Phase 4 failed" without naming which specialist and why.
|
|
186
186
|
|
|
187
|
-
**Sub-agent-failure handling (shared clause; all commands cite this — never inline).** When any spawned implementer/fixer/specialist sub-agent FAILS or returns no usable output: (1) retry once with the same prompt; (2) if the retry fails, re-spawn `hatch3r-fixer` (Phase 3) with the failure reason + partial output as failure context — `hatch3r-fixer` is the code-mutation path, so the work stays delegated; (3) if the re-spawn also fails, emit `BLOCKED_OTHER` with a one-sentence reason and ASK the user (fix-manually vs adjust-scope vs accept-risk). The orchestrator MUST NOT fall back to inline implementation — that is the issue #73 bypass mode (see Mandatory Delegation Directive). The sole exception is `hatch3r-quick-change`, whose Tier-1 carve-out permits inline retry per its declared scope.
|
|
187
|
+
**Sub-agent-failure handling (shared clause; all commands cite this — never inline).** When any spawned implementer/fixer/specialist sub-agent FAILS or returns no usable output: (1) retry once with the same prompt; (2) if the retry fails, re-spawn `hatch3r-fixer` (Phase 3) with the failure reason + partial output as failure context — `hatch3r-fixer` is the code-mutation path, so the work stays delegated; (3) if the re-spawn also fails, emit `BLOCKED_OTHER` with a one-sentence reason and ASK the user (fix-manually vs adjust-scope vs accept-risk). Flush in-flight ledger rows per W4 — before the retry and again before the BLOCKED_OTHER ASK (`rules/hatch3r-findings-ledger.md`). The orchestrator MUST NOT fall back to inline implementation — that is the issue #73 bypass mode (see Mandatory Delegation Directive). The sole exception is `hatch3r-quick-change`, whose Tier-1 carve-out permits inline retry per its declared scope.
|
|
188
188
|
|
|
189
189
|
## Correlation ID
|
|
190
190
|
|
|
@@ -242,4 +242,4 @@ All `scope: always` rules apply to every task including sub-agent work; include
|
|
|
242
242
|
|
|
243
243
|
- **Tier 1 — always include (every sub-agent):** `hatch3r-security-patterns`, `hatch3r-code-standards`.
|
|
244
244
|
- **Tier 2 — by phase:** `hatch3r-testing` (testability/implementer/reviewer); `hatch3r-accessibility-standards` (ui, UI reviewer); `hatch3r-git-conventions` (orchestrator git ops); `hatch3r-ci-cd` (ci-watcher/devops); `hatch3r-dependency-management` (security CQ3 supply-chain slice).
|
|
245
|
-
- **Tier 3 — on-demand by role + scope:** `hatch3r-api-design`, `hatch3r-secrets-management`, `hatch3r-data-classification`, `hatch3r-performance-budgets`, `hatch3r-browser-verification`, `hatch3r-component-conventions`, `hatch3r-i18n`, `hatch3r-theming`, `hatch3r-migrations`, `hatch3r-feature-flags`, `hatch3r-observability-logging`, `hatch3r-observability-metrics`, `hatch3r-observability-tracing`.
|
|
245
|
+
- **Tier 3 — on-demand by role + scope:** `hatch3r-api-design`, `hatch3r-secrets-management`, `hatch3r-data-classification`, `hatch3r-performance-budgets`, `hatch3r-browser-verification`, `hatch3r-component-conventions`, `hatch3r-i18n`, `hatch3r-theming`, `hatch3r-migrations`, `hatch3r-feature-flags`, `hatch3r-observability-logging`, `hatch3r-observability-metrics`, `hatch3r-observability-tracing`, `hatch3r-dynamic-stack-verification`.
|
|
@@ -37,6 +37,15 @@ After every implementation:
|
|
|
37
37
|
|
|
38
38
|
Tools accepted as equivalent: `jscpd` (Node), `PMD CPD` (Java/multi-lang), `simian` (multi-lang), `sonar-scanner` duplication module. Pick by toolchain; the threshold below is tool-agnostic.
|
|
39
39
|
|
|
40
|
+
## Value-Drift Census (Shared Constants)
|
|
41
|
+
|
|
42
|
+
A rate, default, threshold, or enum value consumed by ≥2 features has exactly one owning module; every other reader imports it. On touching such a constant, run the census: grep the constant NAME and the literal VALUE repo-wide; every independently-defined copy is a drift candidate.
|
|
43
|
+
|
|
44
|
+
- **Damage ranking — silent-wrong beats loud-broken.** A deleted import fails at build; a stale copy computes wrong values in production with no signal.
|
|
45
|
+
- **Remedy per copy:** import from the owner, or document intentional divergence with an inline ADR comment.
|
|
46
|
+
- **Outside the jscpd scan's reach:** one-line literals sit below clone-scan thresholds (≥30-line blocks) — the census is name+value grep, not block matching.
|
|
47
|
+
- **Taxonomy owner:** `rules/hatch3r-contract-census.md` → Value-Drift Census; this section is the anti-duplication-side enforcement hook.
|
|
48
|
+
|
|
40
49
|
## Tunable Thresholds Per Maturity Tier
|
|
41
50
|
|
|
42
51
|
Per `hatch3r config maturity=<tier>`:
|
|
@@ -69,7 +78,7 @@ discovery_scan:
|
|
|
69
78
|
|
|
70
79
|
`overlap_assessment: high` without `decision: extend-existing | refactor-shared | adr-distinct` is a P4 violation — author is creating a duplicate.
|
|
71
80
|
|
|
72
|
-
At the user surface, the Iteration Summary carries the `Duplication:` exception line only on a non-clean or skipped scan — `Duplication: <n> match(es), closest <path>, overlap <none|partial|high>` when matches were found, or `Duplication: scan skipped (<reason>)` when skipped; a clean scan emits no line.
|
|
81
|
+
At the user surface, the Iteration Summary carries the `Duplication:` exception line only on a non-clean or skipped scan — `Duplication: <n> match(es), closest <path>, overlap <none|partial|high>` when matches were found, or `Duplication: scan skipped (<reason>)` when skipped; a clean scan emits no line. Value-drift census hits reuse the same channel and silent-failure contract with the variant `Duplication: value-drift — <n> independent definition(s) of <constant>, owner <path>`; a clean census emits no line.
|
|
73
82
|
|
|
74
83
|
## Worked Example
|
|
75
84
|
|
|
@@ -37,6 +37,15 @@ After every implementation:
|
|
|
37
37
|
|
|
38
38
|
Tools accepted as equivalent: `jscpd` (Node), `PMD CPD` (Java/multi-lang), `simian` (multi-lang), `sonar-scanner` duplication module. Pick by toolchain; the threshold below is tool-agnostic.
|
|
39
39
|
|
|
40
|
+
## Value-Drift Census (Shared Constants)
|
|
41
|
+
|
|
42
|
+
A rate, default, threshold, or enum value consumed by ≥2 features has exactly one owning module; every other reader imports it. On touching such a constant, run the census: grep the constant NAME and the literal VALUE repo-wide; every independently-defined copy is a drift candidate.
|
|
43
|
+
|
|
44
|
+
- **Damage ranking — silent-wrong beats loud-broken.** A deleted import fails at build; a stale copy computes wrong values in production with no signal.
|
|
45
|
+
- **Remedy per copy:** import from the owner, or document intentional divergence with an inline ADR comment.
|
|
46
|
+
- **Outside the jscpd scan's reach:** one-line literals sit below clone-scan thresholds (≥30-line blocks) — the census is name+value grep, not block matching.
|
|
47
|
+
- **Taxonomy owner:** `rules/hatch3r-contract-census.md` → Value-Drift Census; this section is the anti-duplication-side enforcement hook.
|
|
48
|
+
|
|
40
49
|
## Tunable Thresholds Per Maturity Tier
|
|
41
50
|
|
|
42
51
|
Per `hatch3r config maturity=<tier>`:
|
|
@@ -69,7 +78,7 @@ discovery_scan:
|
|
|
69
78
|
|
|
70
79
|
`overlap_assessment: high` without `decision: extend-existing | refactor-shared | adr-distinct` is a P4 violation — author is creating a duplicate.
|
|
71
80
|
|
|
72
|
-
At the user surface, the Iteration Summary carries the `Duplication:` exception line only on a non-clean or skipped scan — `Duplication: <n> match(es), closest <path>, overlap <none|partial|high>` when matches were found, or `Duplication: scan skipped (<reason>)` when skipped; a clean scan emits no line.
|
|
81
|
+
At the user surface, the Iteration Summary carries the `Duplication:` exception line only on a non-clean or skipped scan — `Duplication: <n> match(es), closest <path>, overlap <none|partial|high>` when matches were found, or `Duplication: scan skipped (<reason>)` when skipped; a clean scan emits no line. Value-drift census hits reuse the same channel and silent-failure contract with the variant `Duplication: value-drift — <n> independent definition(s) of <constant>, owner <path>`; a clean census emits no line.
|
|
73
82
|
|
|
74
83
|
## Worked Example
|
|
75
84
|
|
|
@@ -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
|
scope: always
|
|
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,14 +28,15 @@ 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
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.
|
|
@@ -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
|
|
|
@@ -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,14 +28,15 @@ 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
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.
|
|
@@ -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.
|