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
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: hatch3r-findings-ledger
|
|
3
|
+
type: rule
|
|
4
|
+
description: Write-ahead findings ledger — every review-loop finding is registered on disk before fix dispatch, folds to a terminal disposition at run exit, and survives interruption; no finding ends a run pending.
|
|
5
|
+
tags: [orchestration, review, floor:protocol]
|
|
6
|
+
precedence: high
|
|
7
|
+
alwaysApply: true
|
|
8
|
+
---
|
|
9
|
+
# hatch3r Findings Ledger
|
|
10
|
+
|
|
11
|
+
**Pillars:** P2 (Scientific & Practical Quality), P8 (Clarification & Fan-out Discipline)
|
|
12
|
+
|
|
13
|
+
This rule closes one failure class: review-loop findings that are registered in chat but never implemented — Suggestions dropped on clean exits, findings lost at loop exhaustion, sub-agent death, or context compaction, and cross-iteration finding identity reduced to a bare unresolved-count. The fix is a write-ahead ledger: every finding is persisted to disk BEFORE the fixer that would address it is dispatched — the ordering Temporal applies to workflow commands (persisted before execution; `docs.temporal.io/encyclopedia/event-history`, accessed 2026-07-08) — and disk state, not chat context, is the recovery source after interruption (durable file/JSON state over context, per Anthropic's long-running-agent harness guidance; `anthropic.com/engineering/effective-harnesses-for-long-running-agents`, accessed 2026-07-08). At run exit every row folds to exactly one terminal disposition; no finding ends a run pending.
|
|
14
|
+
|
|
15
|
+
## Store & Format
|
|
16
|
+
|
|
17
|
+
One JSONL file per run: `.hatch3r/findings/<YYYY-MM-DD>-<command>-<run8>.jsonl`, where `<run8>` is the first 8 hex chars of the run's `correlation_id` (`rules/hatch3r-agent-orchestration.md` → Correlation ID) and `<command>` is the invoking command's short name — the `hatch3r-` prefix dropped (e.g. `workflow`, `pr-resolve`). Append-only; atomic append via the `src/merge/safeWrite.ts` pattern (temp+rename then concat) — the same convention as `.hatch3r/bypass-log.jsonl`.
|
|
18
|
+
|
|
19
|
+
- **Full-row snapshots.** Every append is a complete row, never a partial patch. **Fold rule: last line per `finding_id` wins.** Any reader reconstructs current state by folding the file top to bottom.
|
|
20
|
+
- **Closure marker.** A final marker row with `"finding_id":"run-exit"` closes a file. Closed = last line is `run-exit` AND the fold is all-terminal. The marker row carries `ts`, `run_id`, `command`, `iteration`, and `finding_id` only.
|
|
21
|
+
- **Committed, not gitignored.** `.hatch3r/findings/` gets no gitignore entry — matching the `.hatch3r/review-findings/` + `todo.md` team-memory precedent — so open findings are visible in the PR diff. Degradation: in a repo with a blanket `.hatch3r/` ignore, interruption-proofing stays (same machine) but team visibility is lost.
|
|
22
|
+
|
|
23
|
+
Row schema (JSON keys):
|
|
24
|
+
|
|
25
|
+
| Key | Value |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `ts` | ISO-8601 UTC append time |
|
|
28
|
+
| `run_id` | `<run8>` |
|
|
29
|
+
| `command` | the filename's `<command>` token |
|
|
30
|
+
| `iteration` | review-loop iteration number at append time |
|
|
31
|
+
| `finding_id` | `<run8>-F<seq>` — see Finding IDs |
|
|
32
|
+
| `severity` | `Critical \| Warning \| Suggestion` |
|
|
33
|
+
| `source` | `reviewer \| specialist \| edge-case-ledger \| pr-comment \| spec-review` |
|
|
34
|
+
| `file` | `path:line`, or `issue#N` for board-scoped findings |
|
|
35
|
+
| `summary` | ≤200 chars |
|
|
36
|
+
| `disposition` | `registered` → `targeted \| deferred \| declined \| accepted-risk \| escalated \| already-resolved \| surfaced` |
|
|
37
|
+
| `status` | `pending` → `in-fix` → `done \| failed \| never-attempted` |
|
|
38
|
+
| `closure_ref` | commit SHA, fixer `Findings addressed` quote, todo.md anchor, quoted user reply ≤100 chars, or `review-findings/<id>` |
|
|
39
|
+
|
|
40
|
+
`status: done` with `closure_ref: null` is ILLEGAL — closure always names its evidence.
|
|
41
|
+
|
|
42
|
+
## Finding IDs
|
|
43
|
+
|
|
44
|
+
`finding_id` = `<run8>-F<seq>`; the orchestrator assigns `<seq>` in registration order (F1, F2, …). The reviewer is stateless, so ID continuity is the orchestrator's job: it passes the prior iteration's findings table (`finding_id`, file, summary, status) in every re-review prompt. The reviewer's severity tables carry an `ID` column — reuse the supplied ID for a persisting finding; write `new` for a first appearance (the orchestrator assigns the next `F<seq>`) — plus a `Resolved since last iteration: <ids | none>` line below the tables. Identity heuristic when uncertain: same file + same defect class = same ID. This contract is mirrored in `agents/hatch3r-reviewer.md` → Finding IDs; keep the two aligned when either changes.
|
|
45
|
+
|
|
46
|
+
## Write Points
|
|
47
|
+
|
|
48
|
+
| Point | Trigger | Appends |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| **W1 write-ahead** | reviewer verdict parsed, BEFORE any fixer dispatch — every iteration | new Critical/Warning rows as `targeted`/`pending`; new Suggestions as `registered`/`pending`; one `registered`/`pending` Warning row per reviewer `deferred:` partial-review remainder (summary = the unreviewed item), so unreviewed surfaces survive the session |
|
|
51
|
+
| **W2 per-iteration reconciliation** | after fixer return AND re-review | fixed-and-confirmed rows flip to `done` + `closure_ref`; attempted-but-still-failing rows to `failed`; rows the re-review reports resolved without this run's fix to `already-resolved` |
|
|
52
|
+
| **W3 loop-exit reconciliation** | every exit path: clean, max-iterations, DESIGN_OBJECTION, user abort | resolve every non-terminal row to a legal terminal (Run-Exit Invariant), then append the `run-exit` marker row |
|
|
53
|
+
| **W4 sub-agent-death flush** | the retry/BLOCKED_OTHER path of sub-agent-failure handling (`rules/hatch3r-agent-orchestration.md`) | flush in-flight rows — `in-fix` → `failed`, reason noted in `closure_ref` — before the retry and again before the ASK; a retry that lands re-flips the row at W2 (last line wins) |
|
|
54
|
+
| **W5 Suggestion terminalization** | at W3 | every Suggestion row goes terminal — grammar in Suggestion Handling |
|
|
55
|
+
|
|
56
|
+
At fixer dispatch the orchestrator appends each targeted row's `pending` → `in-fix` snapshot — the in-flight state W4 flushes. Run-start side task, with W1's first append: create `.hatch3r/findings/` when absent, then run the Hygiene prune.
|
|
57
|
+
|
|
58
|
+
## Run-Exit Invariant
|
|
59
|
+
|
|
60
|
+
After W3, zero rows fold to `status: pending` or `in-fix`, and zero rows fold to `disposition: registered`. Every folded row lands on one of the legal terminals:
|
|
61
|
+
|
|
62
|
+
- (a) `targeted` + `done` + `closure_ref`
|
|
63
|
+
- (b) `already-resolved`
|
|
64
|
+
- (c) `deferred` — with a todo.md anchor in `closure_ref`
|
|
65
|
+
- (d) `declined` or `accepted-risk` — user-attested only: each requires a quoted user reply in `closure_ref`; an autonomous run cannot produce them (`agents/shared/user-question-protocol.md` → Unattested product decision)
|
|
66
|
+
- (e) `escalated` — with an open ASK recorded; legal only when the run's own status is not SUCCESS (unattended runs take this path and exit PARTIAL)
|
|
67
|
+
- (f) `surfaced` — Suggestion severity only; the ID appears on the recap's `Open findings:` line
|
|
68
|
+
|
|
69
|
+
A Critical/Warning finding that cannot reach (a)–(d) forces an ASK. Terminal `status` pairs mechanically with the outcome: `done` = this run's fix landed (`closure_ref` required); `failed` = attempted and not landed (never a resting terminal alone — the disposition must still reach (c)–(e)); `never-attempted` = closed without a fix attempt this run (`deferred`, `declined`, `accepted-risk`, `escalated`, `surfaced`, `already-resolved`).
|
|
70
|
+
|
|
71
|
+
## Suggestion Handling
|
|
72
|
+
|
|
73
|
+
Suggestions register once, at first appearance (W1, `registered`/`pending`); a reviewer repeating one in a later iteration causes no re-append — unless its severity changed, which appends a new full-row snapshot (same `finding_id`, new severity). At W3 every Suggestion row goes terminal (W5) via exactly one of:
|
|
74
|
+
|
|
75
|
+
- `surfaced` — the ID is printed on the Iteration Summary's `Open findings:` line (`rules/hatch3r-iteration-summary.md` → Exception Lines). This is the never-silently-dropped guarantee: a clean exit still names every unaddressed Suggestion. Unattended default.
|
|
76
|
+
- `deferred` — the user chose deferral; `closure_ref` = the todo.md anchor.
|
|
77
|
+
- `declined` — the user declined; `closure_ref` = the quoted user reply (≤100 chars).
|
|
78
|
+
|
|
79
|
+
## Session-Start Surfacing
|
|
80
|
+
|
|
81
|
+
`agents/hatch3r-handoff-loader.md` owns this step. At session start the loader scans `.hatch3r/findings/*.jsonl` (skips silently when the directory is absent), skips closed files, folds each remaining file, and lists open rows — non-terminal rows plus rows terminal as `escalated`/`surfaced` — as `id · severity · file · summary · disposition`. A ledger file older than 14 days that still folds open rows is flagged stale, with three closure options: close as declined with reason "stale", re-defer to todo.md, or resume the work. This scan is the self-healing detector for runs that died before W3: whatever a crash left open re-surfaces next session instead of staying lost.
|
|
82
|
+
|
|
83
|
+
## Handoff Integration
|
|
84
|
+
|
|
85
|
+
No handoff-schema change. `agents/hatch3r-handoff-preparer.md` folds the active run's ledger in its collect-state step, and that fold is authoritative for the handoff's Work Remaining `Open findings` bullet at composition time — the handoff inherits open findings from the same fold every other consumer reads. The recap's `Open findings:` exception line (`rules/hatch3r-iteration-summary.md` → Exception Lines) is cross-check provenance, not the source: when it agrees with the fold the preparer copies it verbatim; when it is absent or disagrees (stale recap, mid-session interrupt) the fold wins and the bullet notes `(fold-derived; last recap stale or absent)`; zero open rows ⇒ no bullet. Composition procedure lives in `agents/hatch3r-handoff-preparer.md`, mirrored in `skills/hatch3r-handoff-prepare/SKILL.md` — keep the three aligned when any changes.
|
|
86
|
+
|
|
87
|
+
## Store Boundaries
|
|
88
|
+
|
|
89
|
+
Three stores, three jobs. Writes flow ledger-outward — the ledger is written first; the other stores derive from it, never the reverse.
|
|
90
|
+
|
|
91
|
+
| Store | Role |
|
|
92
|
+
|---|---|
|
|
93
|
+
| `.hatch3r/findings/` (this ledger) | Execution-lifecycle write-ahead log. Run-scoped; carries ALL severities; the source of truth for "is anything open?" |
|
|
94
|
+
| `.hatch3r/review-findings/` | Cross-PR reviewer memory of RESOLVED Critical/Warning findings. Its post-loop append DERIVES from the ledger fold — each entry cites its `finding_id` — never the reverse |
|
|
95
|
+
| `todo.md` | Human follow-up backlog. A `deferred` row's `closure_ref` is the todo.md anchor; the todo bullet carries `[ledger: <finding_id>]`; after deferral the board owns the item (the ledger row is terminal) |
|
|
96
|
+
|
|
97
|
+
## Hygiene
|
|
98
|
+
|
|
99
|
+
- The owning orchestrator closes its own file at W3. A dead run's file is never closed by another run — the loader surfaces it (Session-Start Surfacing) for a user decision.
|
|
100
|
+
- Prune at any run's W1: when more than 20 closed files exist, or any closed file is older than 30 days, delete the oldest closed files down to those bounds. Git history preserves pruned files; open files are never pruned.
|
|
101
|
+
|
|
102
|
+
## Worked Example
|
|
103
|
+
|
|
104
|
+
A 2-iteration `hatch3r-workflow` run (`run8` = `a3f81c2e`, file `.hatch3r/findings/2026-07-08-workflow-a3f81c2e.jsonl`): iteration 1 registers one Critical, one Warning, one Suggestion; the fixer takes the first two; iteration 2's re-review confirms both resolved; the Suggestion terminalizes as `surfaced`, so the recap prints `Open findings: a3f81c2e-F3 Suggestion — surfaced`.
|
|
105
|
+
|
|
106
|
+
```jsonl
|
|
107
|
+
{"ts":"2026-07-08T14:02:11Z","run_id":"a3f81c2e","command":"workflow","iteration":1,"finding_id":"a3f81c2e-F1","severity":"Critical","source":"reviewer","file":"src/auth/session.ts:88","summary":"Session token compared with non-constant-time equality","disposition":"targeted","status":"pending","closure_ref":null}
|
|
108
|
+
{"ts":"2026-07-08T14:02:11Z","run_id":"a3f81c2e","command":"workflow","iteration":1,"finding_id":"a3f81c2e-F2","severity":"Warning","source":"reviewer","file":"src/auth/session.ts:97","summary":"New expiry branch has no test","disposition":"targeted","status":"pending","closure_ref":null}
|
|
109
|
+
{"ts":"2026-07-08T14:02:11Z","run_id":"a3f81c2e","command":"workflow","iteration":1,"finding_id":"a3f81c2e-F3","severity":"Suggestion","source":"reviewer","file":"src/auth/session.ts:41","summary":"Extract shared cookie-parse helper","disposition":"registered","status":"pending","closure_ref":null}
|
|
110
|
+
{"ts":"2026-07-08T14:02:38Z","run_id":"a3f81c2e","command":"workflow","iteration":1,"finding_id":"a3f81c2e-F1","severity":"Critical","source":"reviewer","file":"src/auth/session.ts:88","summary":"Session token compared with non-constant-time equality","disposition":"targeted","status":"in-fix","closure_ref":null}
|
|
111
|
+
{"ts":"2026-07-08T14:02:38Z","run_id":"a3f81c2e","command":"workflow","iteration":1,"finding_id":"a3f81c2e-F2","severity":"Warning","source":"reviewer","file":"src/auth/session.ts:97","summary":"New expiry branch has no test","disposition":"targeted","status":"in-fix","closure_ref":null}
|
|
112
|
+
{"ts":"2026-07-08T14:11:02Z","run_id":"a3f81c2e","command":"workflow","iteration":2,"finding_id":"a3f81c2e-F1","severity":"Critical","source":"reviewer","file":"src/auth/session.ts:88","summary":"Session token compared with non-constant-time equality","disposition":"targeted","status":"done","closure_ref":"fixer: Findings addressed — a3f81c2e-F1 timingSafeEqual"}
|
|
113
|
+
{"ts":"2026-07-08T14:11:02Z","run_id":"a3f81c2e","command":"workflow","iteration":2,"finding_id":"a3f81c2e-F2","severity":"Warning","source":"reviewer","file":"src/auth/session.ts:97","summary":"New expiry branch has no test","disposition":"targeted","status":"done","closure_ref":"fixer: Findings addressed — a3f81c2e-F2 expiry-branch test added"}
|
|
114
|
+
{"ts":"2026-07-08T14:11:30Z","run_id":"a3f81c2e","command":"workflow","iteration":2,"finding_id":"a3f81c2e-F3","severity":"Suggestion","source":"reviewer","file":"src/auth/session.ts:41","summary":"Extract shared cookie-parse helper","disposition":"surfaced","status":"never-attempted","closure_ref":null}
|
|
115
|
+
{"ts":"2026-07-08T14:11:31Z","run_id":"a3f81c2e","command":"workflow","iteration":2,"finding_id":"run-exit"}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Pillar Service
|
|
119
|
+
|
|
120
|
+
- P2 — findings become falsifiable disk records with evidence-bearing closure (`closure_ref` names a commit, quote, or anchor), and the fold answers "is anything open?" from disk rather than from memory.
|
|
121
|
+
- P8 — `declined`/`accepted-risk` require quoted user attestation, and an open Critical/Warning forces an ASK — autonomy never absorbs a product decision silently.
|
|
122
|
+
|
|
123
|
+
## References
|
|
124
|
+
|
|
125
|
+
- Anthropic — Effective harnesses for long-running agents: durable file/JSON state over context; session-start re-read; session-end clean-state sweep. `anthropic.com/engineering/effective-harnesses-for-long-running-agents` (accessed 2026-07-08; T1, published 2025-11-26)
|
|
126
|
+
- Anthropic — Harness design for long-running application development: success criteria written before implementation; files as the inter-agent channel. `anthropic.com/engineering/harness-design-long-running-apps` (accessed 2026-07-08; T1, published 2026-03-24)
|
|
127
|
+
- OASIS — SARIF 2.1.0 Errata 01: `result.kind` open-by-default; `suppression.status: underReview` is never a final state. `docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html` (accessed 2026-07-08; T1, canonical spec, 2023-08-28)
|
|
128
|
+
- DefectDojo — Finding status definitions: risk-accepted carries a revisit pointer; dispositions carry cross-round semantics. `docs.defectdojo.com/triage_findings/findings_workflows/finding_status_definitions/` (accessed 2026-07-08; T2, current)
|
|
129
|
+
- Temporal — Event history / workflow execution: commands persisted before execution; a closed execution has exactly one terminal status. `docs.temporal.io/encyclopedia/event-history` (accessed 2026-07-08; T1, current)
|
|
@@ -27,6 +27,10 @@ cache_friendly: true
|
|
|
27
27
|
- Never concatenate translated fragments to build sentences — each complete sentence is a single translation key.
|
|
28
28
|
- Maintain a string extraction workflow (e.g., `i18next-parser`, `vue-i18n-extract`) that runs in CI to flag unused and missing keys.
|
|
29
29
|
|
|
30
|
+
### Dynamic Keys
|
|
31
|
+
|
|
32
|
+
String extraction cannot see interpolated keys (`t('status.' + value)`, template-literal keys). Every dynamic-key call site either (a) has a test iterating the full value set and asserting each resolved key exists in the default locale (`i18n.te(key)` or equivalent), or (b) carries a co-located comment enumerating the concrete keys for the parser. CI extraction reports count dynamic call sites as unverified, never as passing. Verification pattern owner: `rules/hatch3r-dynamic-stack-verification.md` → Dynamic i18n Keys.
|
|
33
|
+
|
|
30
34
|
## RTL Support
|
|
31
35
|
|
|
32
36
|
- Use CSS logical properties exclusively: `margin-inline-start` (not `margin-left`), `padding-inline-end` (not `padding-right`), `inset-inline-start` (not `left`), `text-align: start` (not `text-align: left`).
|
|
@@ -22,6 +22,10 @@ alwaysApply: false
|
|
|
22
22
|
- Never concatenate translated fragments to build sentences — each complete sentence is a single translation key.
|
|
23
23
|
- Maintain a string extraction workflow (e.g., `i18next-parser`, `vue-i18n-extract`) that runs in CI to flag unused and missing keys.
|
|
24
24
|
|
|
25
|
+
### Dynamic Keys
|
|
26
|
+
|
|
27
|
+
String extraction cannot see interpolated keys (`t('status.' + value)`, template-literal keys). Every dynamic-key call site either (a) has a test iterating the full value set and asserting each resolved key exists in the default locale (`i18n.te(key)` or equivalent), or (b) carries a co-located comment enumerating the concrete keys for the parser. CI extraction reports count dynamic call sites as unverified, never as passing. Verification pattern owner: `rules/hatch3r-dynamic-stack-verification.md` → Dynamic i18n Keys.
|
|
28
|
+
|
|
25
29
|
## RTL Support
|
|
26
30
|
|
|
27
31
|
- Use CSS logical properties exclusively: `margin-inline-start` (not `margin-left`), `padding-inline-end` (not `padding-right`), `inset-inline-start` (not `left`), `text-align: start` (not `text-align: left`).
|
|
@@ -37,6 +37,7 @@ Below the recap, a line appears ONLY when its firing condition holds. An absent
|
|
|
37
37
|
|---|---|---|---|---|
|
|
38
38
|
| Not done | `Not done: <item> [— deferred: <why> \| unverified: <what>]; …` | any scope item not done/deferred/unverified | charter honesty; handoff Work Remaining | full scope completed |
|
|
39
39
|
| Blockers | `Blockers: <blocker or open question>; …` | any open blocker | old §8; handoff Blockers | none open |
|
|
40
|
+
| Open findings | `Open findings: <finding_id> <sev> — <disposition>; …` | any findings-ledger row folds non-terminal, or terminal as `escalated`/`surfaced`, at recap time | findings-ledger run-exit invariant (`rules/hatch3r-findings-ledger.md`) | no ledger file for this run, or every row folds to done/deferred/declined/accepted-risk/already-resolved |
|
|
40
41
|
| Default applied | `Default applied: <question summary> → option <N> (<one-line reason>)` — format unchanged from the superseded template, one per default | ASK default exercised | **P8 B1** | no default taken |
|
|
41
42
|
| Gates failed | `Gates failed: <gate>: <one-line cause>; …` | recap gates shows failure | P1 actionability | all gates passed |
|
|
42
43
|
| Cost | `Cost: flagged_for_review: true` + fenced cost_actuals/delta YAML (the one multi-line exception) | any delta > 25% absolute | **Decision 24** / cost-visibility AC5 | deltas within ±25% (recap Δ facet suffices; telemetry persists regardless) |
|
|
@@ -56,6 +57,7 @@ Handoff surfaces (`rules/hatch3r-handoff-readiness.md`, `skills/hatch3r-handoff-
|
|
|
56
57
|
- **Work Done** ← recap outcome (line 1) + files facet
|
|
57
58
|
- **Work Remaining** ← `Not done:` line; absent ⇒ `None — full scope completed`
|
|
58
59
|
- **Blockers** ← `Blockers:` line; absent ⇒ `None`
|
|
60
|
+
- **Open Findings** ← `Open findings:` line; absent ⇒ none
|
|
59
61
|
|
|
60
62
|
## Confidence-to-Action Mapping (D13)
|
|
61
63
|
|
|
@@ -37,6 +37,7 @@ Below the recap, a line appears ONLY when its firing condition holds. An absent
|
|
|
37
37
|
|---|---|---|---|---|
|
|
38
38
|
| Not done | `Not done: <item> [— deferred: <why> \| unverified: <what>]; …` | any scope item not done/deferred/unverified | charter honesty; handoff Work Remaining | full scope completed |
|
|
39
39
|
| Blockers | `Blockers: <blocker or open question>; …` | any open blocker | old §8; handoff Blockers | none open |
|
|
40
|
+
| Open findings | `Open findings: <finding_id> <sev> — <disposition>; …` | any findings-ledger row folds non-terminal, or terminal as `escalated`/`surfaced`, at recap time | findings-ledger run-exit invariant (`rules/hatch3r-findings-ledger.md`) | no ledger file for this run, or every row folds to done/deferred/declined/accepted-risk/already-resolved |
|
|
40
41
|
| Default applied | `Default applied: <question summary> → option <N> (<one-line reason>)` — format unchanged from the superseded template, one per default | ASK default exercised | **P8 B1** | no default taken |
|
|
41
42
|
| Gates failed | `Gates failed: <gate>: <one-line cause>; …` | recap gates shows failure | P1 actionability | all gates passed |
|
|
42
43
|
| Cost | `Cost: flagged_for_review: true` + fenced cost_actuals/delta YAML (the one multi-line exception) | any delta > 25% absolute | **Decision 24** / cost-visibility AC5 | deltas within ±25% (recap Δ facet suffices; telemetry persists regardless) |
|
|
@@ -56,6 +57,7 @@ Handoff surfaces (`rules/hatch3r-handoff-readiness.md`, `skills/hatch3r-handoff-
|
|
|
56
57
|
- **Work Done** ← recap outcome (line 1) + files facet
|
|
57
58
|
- **Work Remaining** ← `Not done:` line; absent ⇒ `None — full scope completed`
|
|
58
59
|
- **Blockers** ← `Blockers:` line; absent ⇒ `None`
|
|
60
|
+
- **Open Findings** ← `Open findings:` line; absent ⇒ none
|
|
59
61
|
|
|
60
62
|
## Confidence-to-Action Mapping (D13)
|
|
61
63
|
|
|
@@ -75,4 +75,4 @@ Apply layered verification from cheapest to most thorough; stop at the cheapest
|
|
|
75
75
|
|
|
76
76
|
Pick one schema-management tool per project and commit the schema declaration to the repo. Greenfield default: Atlas (50+ destructive/locking linters, auto-generated down migrations, GitHub Actions approval policies) or dbmate (plain-SQL portability with first-class `-- migrate:down`). Existing-project default: whatever already ships migrations in the repo. Acceptable tools: Atlas, Prisma Migrate (forward-only — surface to reviewer), Drizzle Kit (forward-only — surface), Flyway 11+, Liquibase 4.27+ Pro, sqitch, Alembic, Knex, dbmate, Bytebase. Run a migration linter in CI — Atlas analyze, `squawk` for raw Postgres SQL — fail the PR on destructive operations without an explicit `IRREVERSIBLE:` annotation.
|
|
77
77
|
|
|
78
|
-
Cross-references: see `hatch3r-data-classification` (PII / encrypted-column migration requirements), `hatch3r-feature-flags` (read-path switchover gating), `hatch3r-observability-metrics` (backfill progress metrics).
|
|
78
|
+
Cross-references: see `hatch3r-data-classification` (PII / encrypted-column migration requirements), `hatch3r-feature-flags` (read-path switchover gating), `hatch3r-observability-metrics` (backfill progress metrics), `hatch3r-contract-census` (in-code analog: façade contract-hold for field drop/rename outside the database).
|
|
@@ -70,4 +70,4 @@ Apply layered verification from cheapest to most thorough; stop at the cheapest
|
|
|
70
70
|
|
|
71
71
|
Pick one schema-management tool per project and commit the schema declaration to the repo. Greenfield default: Atlas (50+ destructive/locking linters, auto-generated down migrations, GitHub Actions approval policies) or dbmate (plain-SQL portability with first-class `-- migrate:down`). Existing-project default: whatever already ships migrations in the repo. Acceptable tools: Atlas, Prisma Migrate (forward-only — surface to reviewer), Drizzle Kit (forward-only — surface), Flyway 11+, Liquibase 4.27+ Pro, sqitch, Alembic, Knex, dbmate, Bytebase. Run a migration linter in CI — Atlas analyze, `squawk` for raw Postgres SQL — fail the PR on destructive operations without an explicit `IRREVERSIBLE:` annotation.
|
|
72
72
|
|
|
73
|
-
Cross-references: see `hatch3r-data-classification` (PII / encrypted-column migration requirements), `hatch3r-feature-flags` (read-path switchover gating), `hatch3r-observability-metrics` (backfill progress metrics).
|
|
73
|
+
Cross-references: see `hatch3r-data-classification` (PII / encrypted-column migration requirements), `hatch3r-feature-flags` (read-path switchover gating), `hatch3r-observability-metrics` (backfill progress metrics), `hatch3r-contract-census` (in-code analog: façade contract-hold for field drop/rename outside the database).
|
|
@@ -40,6 +40,10 @@ Authentication and authorization patterns (auth middleware, token validation, se
|
|
|
40
40
|
- Circuit breakers for downstream service failures. Degrade gracefully rather than retrying indefinitely or passing errors upstream.
|
|
41
41
|
- Health checks and readiness probes must not expose sensitive configuration or internal topology.
|
|
42
42
|
- Disable debug endpoints, verbose logging, and source maps in production builds. Gate behind feature flags if needed in staging.
|
|
43
|
+
- **Dangerous-capability environment gates are allowlists, never denylists.** A capability that must not run in production — debug endpoint, seed/reset script, test-auth bypass, destructive CLI verb, mock-payment mode — is gated by an explicit allowlist of named safe environments (`const ALLOWED = ['development','test']; if (!ALLOWED.includes(env)) refuse`).
|
|
44
|
+
- The denylist form `if (process.env.NODE_ENV !== 'production')` is the named anti-pattern: an unset, misspelled, or novel environment value (`stage`, `prod-eu`, `undefined` in a fresh container) evaluates as "not production" and ENABLES the capability.
|
|
45
|
+
- Unknown environment fails closed: an absent or unrecognized value takes the deny branch.
|
|
46
|
+
- Assert at startup that the resolved environment is a member of the project's known-environment enum; refuse to boot otherwise.
|
|
43
47
|
|
|
44
48
|
## CSRF Protection
|
|
45
49
|
|
|
@@ -35,6 +35,10 @@ Authentication and authorization patterns (auth middleware, token validation, se
|
|
|
35
35
|
- Circuit breakers for downstream service failures. Degrade gracefully rather than retrying indefinitely or passing errors upstream.
|
|
36
36
|
- Health checks and readiness probes must not expose sensitive configuration or internal topology.
|
|
37
37
|
- Disable debug endpoints, verbose logging, and source maps in production builds. Gate behind feature flags if needed in staging.
|
|
38
|
+
- **Dangerous-capability environment gates are allowlists, never denylists.** A capability that must not run in production — debug endpoint, seed/reset script, test-auth bypass, destructive CLI verb, mock-payment mode — is gated by an explicit allowlist of named safe environments (`const ALLOWED = ['development','test']; if (!ALLOWED.includes(env)) refuse`).
|
|
39
|
+
- The denylist form `if (process.env.NODE_ENV !== 'production')` is the named anti-pattern: an unset, misspelled, or novel environment value (`stage`, `prod-eu`, `undefined` in a fresh container) evaluates as "not production" and ENABLES the capability.
|
|
40
|
+
- Unknown environment fails closed: an absent or unrecognized value takes the deny branch.
|
|
41
|
+
- Assert at startup that the resolved environment is a member of the project's known-environment enum; refuse to boot otherwise.
|
|
38
42
|
|
|
39
43
|
## CSRF Protection
|
|
40
44
|
|
|
@@ -143,6 +143,20 @@ Every test must be deterministic. Mandates:
|
|
|
143
143
|
- **Database state:** Integration tests set up and tear down within the test via helpers. Never depend on database state from a previous test. Enforce tenancy isolation via per-test schema or transaction rollback.
|
|
144
144
|
- **Testcontainers** pinned by image digest, not tag.
|
|
145
145
|
|
|
146
|
+
## Degenerate-Input Guard
|
|
147
|
+
|
|
148
|
+
A test whose input turns the computation under test into a no-op verifies wiring, not behavior. Canonical degenerate vectors:
|
|
149
|
+
|
|
150
|
+
- A 0%-interest loan (interest math never executes).
|
|
151
|
+
- A one-record merge (no conflict branch).
|
|
152
|
+
- An empty-array pipeline (every stage vacuously passes).
|
|
153
|
+
- A zero-quantity or zero-price order (totals stay 0).
|
|
154
|
+
- A same-source-and-target move (no-op transfer).
|
|
155
|
+
- `now()` timestamps against expiry logic (never expires).
|
|
156
|
+
- Single-user fixtures against cross-tenant checks.
|
|
157
|
+
|
|
158
|
+
**Requirement:** for each changed behavior, at least one input **activates** the computation, and the assertion distinguishes the activated result from the degenerate baseline (the two expected outputs differ). **Reviewer treatment:** a suite green only on degenerate vectors is a Warning; on payment, auth, or data-mutation paths, Critical. "N passing" is evidence only when paired with which changed behaviors those N tests activate.
|
|
159
|
+
|
|
146
160
|
## Error Path Coverage
|
|
147
161
|
|
|
148
162
|
Error handling code is often under-tested because developers focus on happy paths. Enforce minimum error coverage:
|
|
@@ -138,6 +138,20 @@ Every test must be deterministic. Mandates:
|
|
|
138
138
|
- **Database state:** Integration tests set up and tear down within the test via helpers. Never depend on database state from a previous test. Enforce tenancy isolation via per-test schema or transaction rollback.
|
|
139
139
|
- **Testcontainers** pinned by image digest, not tag.
|
|
140
140
|
|
|
141
|
+
## Degenerate-Input Guard
|
|
142
|
+
|
|
143
|
+
A test whose input turns the computation under test into a no-op verifies wiring, not behavior. Canonical degenerate vectors:
|
|
144
|
+
|
|
145
|
+
- A 0%-interest loan (interest math never executes).
|
|
146
|
+
- A one-record merge (no conflict branch).
|
|
147
|
+
- An empty-array pipeline (every stage vacuously passes).
|
|
148
|
+
- A zero-quantity or zero-price order (totals stay 0).
|
|
149
|
+
- A same-source-and-target move (no-op transfer).
|
|
150
|
+
- `now()` timestamps against expiry logic (never expires).
|
|
151
|
+
- Single-user fixtures against cross-tenant checks.
|
|
152
|
+
|
|
153
|
+
**Requirement:** for each changed behavior, at least one input **activates** the computation, and the assertion distinguishes the activated result from the degenerate baseline (the two expected outputs differ). **Reviewer treatment:** a suite green only on degenerate vectors is a Warning; on payment, auth, or data-mutation paths, Critical. "N passing" is evidence only when paired with which changed behaviors those N tests activate.
|
|
154
|
+
|
|
141
155
|
## Error Path Coverage
|
|
142
156
|
|
|
143
157
|
Error handling code is often under-tested because developers focus on happy paths. Enforce minimum error coverage:
|
|
@@ -153,6 +153,8 @@ Verdict: <reuse|extend|create-with-justification>
|
|
|
153
153
|
|
|
154
154
|
## Cross-references
|
|
155
155
|
|
|
156
|
+
Consumer: `commands/hatch3r-design-system-create.md` — creation-side orchestrator; invokes this skill as its mandatory Step 1 and routes on the inventory verdict (reuse → halt, extend → gap-scoped, create → full generation).
|
|
157
|
+
|
|
156
158
|
Rules consumed by this skill:
|
|
157
159
|
|
|
158
160
|
- `rules/hatch3r-design-system-detection.md` — rule version of this guidance (mandate + scope)
|
|
@@ -83,7 +83,7 @@ Populate the 8 required sections in the order defined by the README schema:
|
|
|
83
83
|
--- END USER-TIER CONTENT: handoff ---
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
**Provenance constraint:** `Work Done`, `Work Remaining`, and `Blockers` derive from the session's most recent Iteration Summary per the Handoff Mapping in `rules/hatch3r-iteration-summary.md`: Work Done ← recap outcome + files facet; Work Remaining ← `Not done:` line, absent ⇒ `None — full scope completed`; Blockers ← `Blockers:` line, absent ⇒ `None`. Present lines are copied **verbatim** — do not paraphrase; the contract is exact reuse so loaders can correlate handoff state with prior turn output.
|
|
86
|
+
**Provenance constraint:** `Work Done`, `Work Remaining`, and `Blockers` derive from the session's most recent Iteration Summary per the Handoff Mapping in `rules/hatch3r-iteration-summary.md`: Work Done ← recap outcome + files facet; Work Remaining ← `Not done:` line, absent ⇒ `None — full scope completed`; Blockers ← `Blockers:` line, absent ⇒ `None`. Present lines are copied **verbatim** — do not paraphrase; the contract is exact reuse so loaders can correlate handoff state with prior turn output. The Work Remaining `Open findings` bullet is composed from the active run's findings-ledger fold (last line per `finding_id` wins; `rules/hatch3r-findings-ledger.md`), authoritative at composition time, in the recap grammar `Open findings: <finding_id> <sev> — <disposition>; …`: when the last recap's line agrees with the fold, copy it verbatim; when it is absent or disagrees (stale recap, mid-session interrupt), the fold wins and the bullet notes `(fold-derived; last recap stale or absent)`; zero open rows ⇒ no bullet.
|
|
87
87
|
|
|
88
88
|
**Hard cap:** body ≤ 51,200 bytes (50 KB). If exceeded:
|
|
89
89
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hatch3r",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Agentic coding setup framework audited each release across 24 governance domains. One command to hatch your agent stack -- agents, skills, rules, commands, and MCP for Claude Code, Cursor, and GitHub Copilot.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|