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
package/README.md
CHANGED
|
@@ -27,8 +27,8 @@ npx hatch3r init # interactive: customize profile, tools, and CLI too
|
|
|
27
27
|
|----------|-------|-----------|
|
|
28
28
|
| **Agents** | 29 | Code reviewer, lint-fixer, dependency auditor, implementer (sub-agentic), fixer, researcher, architect, DevOps, handoff loader / preparer, 9 content-quality specialists (UI/UX/security/reliability/testability/scalability/performance/maintainability/enhancability), and more |
|
|
29
29
|
| **Skills** | 53 | Bug fix, feature implementation, issue workflow, release, incident response, context health, cost tracking, handoff prepare / resume, recipes, API spec, CI pipeline, migration, customization, board lifecycle, ad-hoc orchestration scaffold, 5 standalone CLI-tool skills (ripgrep, jq, gh, fd, fzf) + a 24-tool `cli-toolbox`, and more |
|
|
30
|
-
| **Rules** |
|
|
31
|
-
| **Commands** |
|
|
30
|
+
| **Rules** | 70 | Code standards, testing, API design, observability, theming, i18n, security patterns, agent orchestration, fan-out discipline, right-sizing, deep context analysis, handoff readiness, mobile + backend stack rules, and more |
|
|
31
|
+
| **Commands** | 31 | Board management, planning (feature, bug, refactor, test), workflow, quick-change, bug-pipeline, revision, debug, healthcheck, security-audit, onboard, benchmark, handoff (prepare/resume/list/complete/prune), and more |
|
|
32
32
|
| **CLI tools** | 29 across 3 tiers | Tier-1 default (ripgrep, fd, jq, yq, gh, delta, bat, sd, ast-grep, zstd); tier-2 conditional (Playwright, duckdb, qsv, taplo, glab, az-devops, Docker, llm, fzf, lazygit, difftastic); tier-3 opt-in (RTK, Stagehand, aichat, mods, Comby, miller, csvkit, Podman) -- emitted as per-tool canonical skills + a decision-tree overview |
|
|
33
33
|
| **MCP Servers** | 10 (opt-in) | Playwright, Context7, Filesystem, GitHub, Brave Search, Sentry, Postgres, Linear, Azure DevOps, GitLab -- pure opt-in since 2.0.0: `init --mcp` or `npx hatch3r mcp setup` (interactive init does not prompt for MCP; `features.mcp` defaults to false) |
|
|
34
34
|
| **Platforms** | 3 | GitHub, Azure DevOps, GitLab -- auto-detected from git remote |
|
|
@@ -150,7 +150,7 @@ A four-phase pipeline (Research, Implement, Review Loop with reviewer + fixer at
|
|
|
150
150
|
AGENTS.md (Linux Foundation AAIF spec, 60K+ repos as of January 2026) is the greatest-common-denominator markdown standard for agent instructions; it is consumed by 20+ tools including Cursor, Copilot, Codex, and Gemini CLI. hatch3r is complementary: AGENTS.md describes one file's content; hatch3r owns the entire generation pipeline that emits tool-native configurations across 5 artifact classes (rules, skills, commands, hooks, MCP servers) for 3 supported platforms (Claude Code, Cursor, GitHub Copilot). Three measurable differences:
|
|
151
151
|
|
|
152
152
|
- **Scope:** AGENTS.md is one flat instruction file per repo; hatch3r generates platform-specific structured output (`.mdc` rules with frontmatter scoping for Cursor, `CLAUDE.md` with managed blocks for Claude Code, `.github/instructions/` + `.github/prompts/` for Copilot) plus board commands, MCP server configs, and event-driven hooks.
|
|
153
|
-
- **Currency:** AGENTS.md content is hand-edited per project; hatch3r ships canonical content (29 agents + 66 rules + 53 skills +
|
|
153
|
+
- **Currency:** AGENTS.md content is hand-edited per project; hatch3r ships canonical content (29 agents + 66 rules + 53 skills + 31 commands + 7 hooks + 10 MCP servers — see [`governance/inventory.json`](governance/inventory.json)) audited weekly across 24 governance domains.
|
|
154
154
|
- **Adoption path:** AGENTS.md remains the spec hatch3r-emitted Cursor / Claude / Copilot configurations align with — the 1.9.0 hard-cut withdrew direct AGENTS.md emission per CONSTITUTION §6 Decision #12, but AAIF spec evolution feeds per-adapter feature work for the 3 supported adapters. Use AGENTS.md alone when one flat file suffices for your project; use hatch3r when you need the full content + tooling stack.
|
|
155
155
|
|
|
156
156
|
## Customization
|
package/dist/cli/index.js
CHANGED
|
@@ -18,7 +18,7 @@ var __export = (target, all) => {
|
|
|
18
18
|
// src/version.ts
|
|
19
19
|
function resolveVersion() {
|
|
20
20
|
try {
|
|
21
|
-
return "2.
|
|
21
|
+
return "2.2.0";
|
|
22
22
|
} catch (defineMissing) {
|
|
23
23
|
void defineMissing;
|
|
24
24
|
try {
|
|
@@ -1031,9 +1031,9 @@ async function applyCustomizationImpl(projectRoot, file, contentKey) {
|
|
|
1031
1031
|
warnings.push(`Scope override on ${file.type} "${file.id}" has no effect \u2014 ${file.type}s do not use scope. Ignoring.`);
|
|
1032
1032
|
delete overrides.scope;
|
|
1033
1033
|
}
|
|
1034
|
-
const TYPES_WITHOUT_MODEL = /* @__PURE__ */ new Set(["
|
|
1034
|
+
const TYPES_WITHOUT_MODEL = /* @__PURE__ */ new Set(["rule", "prompt", "hook"]);
|
|
1035
1035
|
if (overrides.model !== void 0 && TYPES_WITHOUT_MODEL.has(file.type)) {
|
|
1036
|
-
warnings.push(`Model override on ${file.type} "${file.id}" has no effect \u2014 only agents carry a model. Ignoring.`);
|
|
1036
|
+
warnings.push(`Model override on ${file.type} "${file.id}" has no effect \u2014 only agents, skills, and commands carry a model. Ignoring.`);
|
|
1037
1037
|
delete overrides.model;
|
|
1038
1038
|
}
|
|
1039
1039
|
for (const field of ["description", "scope", "model"]) {
|
|
@@ -6324,13 +6324,15 @@ function collectManifestErrors(data) {
|
|
|
6324
6324
|
if (models.default !== void 0 && typeof models.default !== "string") {
|
|
6325
6325
|
errors.push("`models.default` is not a string");
|
|
6326
6326
|
}
|
|
6327
|
-
|
|
6328
|
-
|
|
6329
|
-
|
|
6327
|
+
for (const cls of ["agents", "skills", "commands"]) {
|
|
6328
|
+
const map = models[cls];
|
|
6329
|
+
if (map === void 0) continue;
|
|
6330
|
+
if (typeof map !== "object" || map === null || Array.isArray(map)) {
|
|
6331
|
+
errors.push(`\`models.${cls}\` is not an object`);
|
|
6330
6332
|
} else {
|
|
6331
|
-
for (const [
|
|
6333
|
+
for (const [artifactId, model] of Object.entries(map)) {
|
|
6332
6334
|
if (typeof model !== "string") {
|
|
6333
|
-
errors.push(`\`models
|
|
6335
|
+
errors.push(`\`models.${cls}.${artifactId}\` is not a string`);
|
|
6334
6336
|
}
|
|
6335
6337
|
}
|
|
6336
6338
|
}
|
|
@@ -7098,10 +7100,13 @@ function resolveModelAlias(input) {
|
|
|
7098
7100
|
}
|
|
7099
7101
|
|
|
7100
7102
|
// src/models/resolve.ts
|
|
7101
|
-
function
|
|
7102
|
-
const raw = customize?.model ?? manifest.models?.
|
|
7103
|
+
function resolveArtifactModel(cls, id, frontmatterModel, manifest, customize) {
|
|
7104
|
+
const raw = customize?.model ?? manifest.models?.[cls]?.[id] ?? frontmatterModel ?? (cls === "agents" ? manifest.models?.default : void 0);
|
|
7103
7105
|
return raw ? resolveModelAlias(raw) : void 0;
|
|
7104
7106
|
}
|
|
7107
|
+
function resolveAgentModel(agentId, agent, manifest, customize) {
|
|
7108
|
+
return resolveArtifactModel("agents", agentId, agent.model, manifest, customize);
|
|
7109
|
+
}
|
|
7105
7110
|
|
|
7106
7111
|
// src/adapters/base.ts
|
|
7107
7112
|
init_managedBlocks();
|
|
@@ -9065,7 +9070,7 @@ All tasks use this four-phase pipeline. Never implement inline; always delegate.
|
|
|
9065
9070
|
**Phase 1 \u2014 Research:** Spawn \`hatch3r-researcher\`. Skip only for trivial edits. Score complexity per \`hatch3r-deep-context\` and add tier modes.
|
|
9066
9071
|
**Phase 2 \u2014 Implement:** Spawn \`hatch3r-implementer\` (one per task). Pass research context.
|
|
9067
9072
|
**Phase 3 \u2014 Review Loop:** \`hatch3r-reviewer\` \u2192 if Critical/Warning: \`hatch3r-fixer\` \u2192 re-review \u2192 repeat (max 3). After clean verdict: one confirmation pass (regressions, acceptance criteria). Remaining findings after max iterations \u2192 surface to user.
|
|
9068
|
-
**Phase 4 \u2014 Final Quality** (after clean review): \`hatch3r-testability\` + \`hatch3r-security\` (always), \`hatch3r-docs-writer\` (evaluate),
|
|
9073
|
+
**Phase 4 \u2014 Final Quality** (after clean review): \`hatch3r-testability\` + \`hatch3r-security\` (always), \`hatch3r-docs-writer\` (evaluate), \`hatch3r-ui\` + \`hatch3r-ux\` (mandatory-on-match \u2014 when triggered, each MUST spawn as its own dedicated sub-agent instance at Tier 2/3; Tier 1 keeps the Phase Skip Criteria skip), then conditional CQ specialists: \`hatch3r-reliability\`, \`hatch3r-scalability\`, \`hatch3r-performance\`, \`hatch3r-maintainability\`, \`hatch3r-enhancability\`, plus \`hatch3r-lint-fixer\`.
|
|
9069
9074
|
|
|
9070
9075
|
## Mandatory Behaviors
|
|
9071
9076
|
|
|
@@ -10004,6 +10009,7 @@ function substituteVerificationGateTokens(content, manifest) {
|
|
|
10004
10009
|
}
|
|
10005
10010
|
|
|
10006
10011
|
// src/adapters/base.ts
|
|
10012
|
+
var SAFE_MODEL_RE = /^[A-Za-z0-9._/-]+$/;
|
|
10007
10013
|
function output(path, content, managedContent, sourceFiles) {
|
|
10008
10014
|
return { path, content, managedContent, action: "create", sourceFiles };
|
|
10009
10015
|
}
|
|
@@ -10518,6 +10524,18 @@ ${wrapManagedFor(pathFn(skill.id), content)}`, content, this.singleSource(skill)
|
|
|
10518
10524
|
* is false or the skill declares no tools, the stub is the historical
|
|
10519
10525
|
* `name: + description:` shape and output is byte-identical to the prior
|
|
10520
10526
|
* behavior.
|
|
10527
|
+
*
|
|
10528
|
+
* release/2.2.0 — `opts.emitModel`: per-adapter opt-in for a `model:` line
|
|
10529
|
+
* in the frontmatter stub, resolved via `resolveArtifactModel("skills",
|
|
10530
|
+
* ...)` (customize > `models.skills[id]` > skill frontmatter; NO
|
|
10531
|
+
* `models.default` fallback — that stays agents-only). The predicate
|
|
10532
|
+
* receives the alias-expanded value and returns whether the target
|
|
10533
|
+
* platform's skill surface recognizes it (e.g.
|
|
10534
|
+
* `isClaudeRecognizableModel`). Same opt-in rationale as
|
|
10535
|
+
* `emitAllowedTools`: Cursor SKILL.md documents no `model` field and
|
|
10536
|
+
* Copilot SKILL.md model support is unverified, so an adapter that does not
|
|
10537
|
+
* opt in stays byte-identical. `inherit` is never emitted — an omitted
|
|
10538
|
+
* field IS the inherit semantic on every skill surface.
|
|
10521
10539
|
*/
|
|
10522
10540
|
async processSkillsWithFmCliFiltered(ctx, pathFn, opts) {
|
|
10523
10541
|
if (!ctx.features.skills) return [];
|
|
@@ -10531,6 +10549,10 @@ ${wrapManagedFor(pathFn(skill.id), content)}`, content, this.singleSource(skill)
|
|
|
10531
10549
|
const content = this.substituteCanonicalContent(raw, ctx);
|
|
10532
10550
|
const desc = overrides.description ?? skill.description;
|
|
10533
10551
|
const fmLines = [`name: ${skill.id}`, `description: ${toYamlDoubleQuotedScalar(desc)}`];
|
|
10552
|
+
const model = resolveArtifactModel("skills", skill.id, skill.model, ctx.manifest, overrides);
|
|
10553
|
+
if (model && model !== "inherit" && SAFE_MODEL_RE.test(model) && opts?.emitModel?.(model)) {
|
|
10554
|
+
fmLines.push(`model: ${model}`);
|
|
10555
|
+
}
|
|
10534
10556
|
if (opts?.emitAllowedTools && skill.allowedTools && skill.allowedTools.length > 0) {
|
|
10535
10557
|
fmLines.push(`allowed-tools: [${skill.allowedTools.map((t) => `"${t}"`).join(", ")}]`);
|
|
10536
10558
|
}
|
|
@@ -10585,8 +10607,19 @@ ${wrapManagedFor(pathFn(skill.id), content)}`, content, this.singleSource(skill)
|
|
|
10585
10607
|
* metadata like `orchestrator`/`agentPipeline`/`triage_tiers`) is
|
|
10586
10608
|
* intentionally NOT hoisted: it is hatch3r-authoring data with no runtime or
|
|
10587
10609
|
* picker consumer.
|
|
10610
|
+
*
|
|
10611
|
+
* release/2.2.0 — `opts.emitModel`: per-adapter opt-in for a `model:` line
|
|
10612
|
+
* (after `argument-hint`), resolved via `resolveArtifactModel("commands",
|
|
10613
|
+
* ...)` (customize > `models.commands[id]` > command frontmatter; NO
|
|
10614
|
+
* `models.default` fallback — a command-level model switches the whole
|
|
10615
|
+
* conversation model, so it must be an explicit per-id choice). The
|
|
10616
|
+
* predicate gates to platform-recognizable values
|
|
10617
|
+
* (`isClaudeRecognizableModel` / `isCopilotRecognizableModel`); Cursor
|
|
10618
|
+
* passes no opts — its `.cursor/commands/*.md` surface documents no `model`
|
|
10619
|
+
* field — and stays byte-identical. `inherit` is never emitted (omitted
|
|
10620
|
+
* field == inherit).
|
|
10588
10621
|
*/
|
|
10589
|
-
async processCommandsWithFm(ctx, pathFn) {
|
|
10622
|
+
async processCommandsWithFm(ctx, pathFn, opts) {
|
|
10590
10623
|
if (!ctx.features.commands) return [];
|
|
10591
10624
|
const results = [];
|
|
10592
10625
|
const commands = await this.readUserFacingCanonicalFiles(ctx.canonicalRoot, "commands", ctx.userRepoRoot);
|
|
@@ -10600,6 +10633,10 @@ ${wrapManagedFor(pathFn(skill.id), content)}`, content, this.singleSource(skill)
|
|
|
10600
10633
|
const fmLines = [`name: ${cmd.id}`, `description: ${toYamlDoubleQuotedScalar(desc)}`];
|
|
10601
10634
|
const argumentHint = extractArgumentHint(cmd.rawContent);
|
|
10602
10635
|
if (argumentHint) fmLines.push(`argument-hint: ${toYamlDoubleQuotedScalar(argumentHint)}`);
|
|
10636
|
+
const model = resolveArtifactModel("commands", cmd.id, cmd.model, ctx.manifest, overrides);
|
|
10637
|
+
if (model && model !== "inherit" && SAFE_MODEL_RE.test(model) && opts?.emitModel?.(model)) {
|
|
10638
|
+
fmLines.push(`model: ${model}`);
|
|
10639
|
+
}
|
|
10603
10640
|
const fm = `---
|
|
10604
10641
|
${fmLines.join("\n")}
|
|
10605
10642
|
---`;
|
|
@@ -11485,12 +11522,14 @@ ${wrapManagedFor(agentPath, body)}`, body, claudeSingleSource(agent)));
|
|
|
11485
11522
|
));
|
|
11486
11523
|
const skillOutputs = await this.processSkillsWithFmCliFiltered(
|
|
11487
11524
|
ctx,
|
|
11488
|
-
(id) => `.claude/skills/${toPrefixedId(id)}/SKILL.md
|
|
11525
|
+
(id) => `.claude/skills/${toPrefixedId(id)}/SKILL.md`,
|
|
11526
|
+
{ emitModel: isClaudeRecognizableModel }
|
|
11489
11527
|
);
|
|
11490
11528
|
results.push(...skillOutputs.map(rewrapWithCacheBreakpoints));
|
|
11491
11529
|
const commandOutputs = await this.processCommandsWithFm(
|
|
11492
11530
|
ctx,
|
|
11493
|
-
(id) => `.claude/commands/${toPrefixedId(id)}.md
|
|
11531
|
+
(id) => `.claude/commands/${toPrefixedId(id)}.md`,
|
|
11532
|
+
{ emitModel: isClaudeRecognizableModel }
|
|
11494
11533
|
);
|
|
11495
11534
|
results.push(...commandOutputs.map(rewrapWithCacheBreakpoints));
|
|
11496
11535
|
const companionMappings = [
|
|
@@ -11805,7 +11844,11 @@ ${wrapManagedFor(agentPath, content)}`, content, copilotSingleSource(agent)));
|
|
|
11805
11844
|
}
|
|
11806
11845
|
}
|
|
11807
11846
|
results.push(
|
|
11808
|
-
...await this.processCommandsWithFm(
|
|
11847
|
+
...await this.processCommandsWithFm(
|
|
11848
|
+
ctx,
|
|
11849
|
+
(id) => `.github/prompts/${toPrefixedId(id)}.prompt.md`,
|
|
11850
|
+
{ emitModel: isCopilotRecognizableModel }
|
|
11851
|
+
)
|
|
11809
11852
|
);
|
|
11810
11853
|
if (ctx.features.githubAgents && !ctx.features.agents) {
|
|
11811
11854
|
const ghAgents = await this.readTrackedCanonicalFiles(ctx.canonicalRoot, "github-agents", ctx.userRepoRoot);
|
|
@@ -13552,7 +13595,16 @@ var REQUIRED_GITIGNORE_ENTRIES = [
|
|
|
13552
13595
|
".hatch3r/handoffs/",
|
|
13553
13596
|
".hatch3r/provenance.json",
|
|
13554
13597
|
".init-workspace/",
|
|
13555
|
-
".sync-workspace/"
|
|
13598
|
+
".sync-workspace/",
|
|
13599
|
+
".pr-resolve-workspace/",
|
|
13600
|
+
".hatch3r/telemetry/",
|
|
13601
|
+
".hatch3r/efficiency-events.jsonl",
|
|
13602
|
+
".hatch3r/.failure-log.jsonl",
|
|
13603
|
+
".hatch3r/.breaker-state.jsonl",
|
|
13604
|
+
".hatch3r/.lock",
|
|
13605
|
+
".hatch3r/calibration-state.json",
|
|
13606
|
+
".hatch3r/calibration-log.jsonl",
|
|
13607
|
+
".hatch3r/archive/"
|
|
13556
13608
|
];
|
|
13557
13609
|
function isCoveredByGitignore(entry, lines) {
|
|
13558
13610
|
const trimmedEntries = lines.map((l) => l.trim());
|
|
@@ -25979,10 +26031,16 @@ async function validateModels(manifest, result) {
|
|
|
25979
26031
|
if (manifest.models.default && typeof manifest.models.default !== "string") {
|
|
25980
26032
|
result.errors.push("hatch.json: models.default must be a string");
|
|
25981
26033
|
}
|
|
25982
|
-
|
|
25983
|
-
|
|
26034
|
+
for (const cls of ["agents", "skills", "commands"]) {
|
|
26035
|
+
const map = manifest.models[cls];
|
|
26036
|
+
if (!map) continue;
|
|
26037
|
+
if (typeof map !== "object" || Array.isArray(map)) {
|
|
26038
|
+
result.errors.push(`hatch.json: models.${cls} must be an object mapping ids to model strings`);
|
|
26039
|
+
continue;
|
|
26040
|
+
}
|
|
26041
|
+
for (const [artifactId, model] of Object.entries(map)) {
|
|
25984
26042
|
if (typeof model !== "string") {
|
|
25985
|
-
result.errors.push(`hatch.json: models
|
|
26043
|
+
result.errors.push(`hatch.json: models.${cls}.${artifactId} must be a string`);
|
|
25986
26044
|
}
|
|
25987
26045
|
}
|
|
25988
26046
|
}
|
|
@@ -100,6 +100,7 @@ Beyond this once-per-run gate, surface relevant learnings *mid-edit* per `rules/
|
|
|
100
100
|
|
|
101
101
|
- Extract all Critical and Warning items from the reviewer output.
|
|
102
102
|
- Note file paths, line numbers, and suggested fixes for each finding.
|
|
103
|
+
- Each finding carries a ledger `finding_id` (`rules/hatch3r-findings-ledger.md` → Finding IDs) — preserve it verbatim in every output line.
|
|
103
104
|
- Ignore Suggestion items — those are surfaced to the user by the orchestrator.
|
|
104
105
|
- Prioritize Critical findings before Warnings.
|
|
105
106
|
|
|
@@ -110,7 +111,7 @@ For each Critical and Warning finding:
|
|
|
110
111
|
- Read the referenced file and surrounding context.
|
|
111
112
|
- Understand the root cause of the issue.
|
|
112
113
|
- Determine the minimal fix that addresses the finding without introducing new issues.
|
|
113
|
-
-
|
|
114
|
+
- When the fix touches a shared contract, run the consumer census per `rules/hatch3r-contract-census.md` (Step 5b) — blast-radius input, when provided, seeds the grep list but never substitutes for the self-run grep.
|
|
114
115
|
- If reference conventions are available, verify the fix follows established patterns rather than introducing divergent approaches.
|
|
115
116
|
- Use Context7 MCP (`resolve-library-id` then `query-docs`) for API patterns relevant to the fix.
|
|
116
117
|
- Use web research for security advisories, CVE details, or best practices when the finding involves security or novel patterns.
|
|
@@ -155,6 +156,14 @@ ${HATCH3R:VERIFY_GATE_ALL}
|
|
|
155
156
|
|
|
156
157
|
The placeholder above is rewritten by the adapter pipeline (`substituteVerifyGateTokens` in `src/adapters/base.ts`) from the project manifest's detected `languages[]` plus its package manager. The literal fallback when detection is unknown is `npm run lint && npm run typecheck && npm run test`; for a Python project the rendered command becomes `ruff check . && mypy . && pytest`, etc. (Adapt only if the project carries non-standard scripts in addition to the resolver output.)
|
|
157
158
|
|
|
159
|
+
### 5b. Consumer Census (shared-contract fixes)
|
|
160
|
+
|
|
161
|
+
**Trigger:** the fix renames, removes, or re-signatures an exported symbol; changes a persisted collection/table/field name; adds, renames, or drops a client↔server wire-field key; changes an event name or payload key; moves or revalues a shared constant; or renames a CLI flag or config/env key (`rules/hatch3r-contract-census.md` → Shared-Contract Taxonomy). No trigger → record `Consumer census: N/A (no shared-contract change)` in the fix result and skip the rest of this step.
|
|
162
|
+
|
|
163
|
+
**Census:** for each changed contract, run a repo-wide grep of the OLD identifier and the NEW identifier — never limited to the findings' file list or the blast-radius consumer map. Reconciled and justification definitions, plus grep patterns: `rules/hatch3r-contract-census.md` → Consumer Census.
|
|
164
|
+
|
|
165
|
+
**Gate:** `Status: SUCCESS` requires census ∈ {`clean`, `reconciled(N)`, `N/A`}; any `unreconciled` consumer without a named justification caps Status at `PARTIAL`, with the unreconciled consumers listed under Notes.
|
|
166
|
+
|
|
158
167
|
### 6. Return Structured Result
|
|
159
168
|
|
|
160
169
|
Report back to the parent orchestrator with:
|
|
@@ -173,11 +182,11 @@ The `Reviewer re-run required` field is an **advisory** signal to the parent orc
|
|
|
173
182
|
**Reviewer re-run required:** true | false (advisory — orchestrator derives the authoritative value as `Files changed` non-empty; print `true` whenever the `Files changed` list below has ≥1 entry, `false` only when it is empty)
|
|
174
183
|
|
|
175
184
|
**Findings addressed:**
|
|
176
|
-
- [CRITICAL #1] file:line
|
|
177
|
-
- [WARNING #1] file:line
|
|
185
|
+
- [<finding_id>] [CRITICAL #1] file:line — <fix summary>
|
|
186
|
+
- [<finding_id>] [WARNING #1] file:line — <fix summary>
|
|
178
187
|
|
|
179
188
|
**Findings unresolved:**
|
|
180
|
-
-
|
|
189
|
+
- [<finding_id>] [WARNING #2] file:line — <reason: blocked | failed | out-of-scope>
|
|
181
190
|
|
|
182
191
|
**Files changed:**
|
|
183
192
|
- path/to/file.ts -- description of change
|
|
@@ -190,6 +199,8 @@ The `Reviewer re-run required` field is an **advisory** signal to the parent orc
|
|
|
190
199
|
- Typecheck: PASS | FAIL (details)
|
|
191
200
|
- Tests: PASS | FAIL (details)
|
|
192
201
|
|
|
202
|
+
**Consumer census:** clean | reconciled(N) | N unreconciled — justification | N/A (no shared-contract change)
|
|
203
|
+
|
|
193
204
|
**Consulted Learnings:**
|
|
194
205
|
- (learning IDs matched in Step 0b, or "none available" / "none matched")
|
|
195
206
|
|
|
@@ -245,9 +256,9 @@ When producing fix results, be aware that a PARTIAL status with unresolved findi
|
|
|
245
256
|
**Reviewer re-run required:** true
|
|
246
257
|
|
|
247
258
|
**Findings addressed:**
|
|
248
|
-
- [CRITICAL #1] src/routes/billing.ts:42
|
|
249
|
-
- [CRITICAL #2] src/routes/billing.ts:38
|
|
250
|
-
- [WARNING #1] src/routes/billing.ts:45
|
|
259
|
+
- [b4e2a9c7-F1] [CRITICAL #1] src/routes/billing.ts:42 — added toInvoiceResponse() DTO to filter internal billing IDs and provider tokens from response
|
|
260
|
+
- [b4e2a9c7-F2] [CRITICAL #2] src/routes/billing.ts:38 — added requireOwnership(req.user.id, params.userId) guard before invoice lookup
|
|
261
|
+
- [b4e2a9c7-F3] [WARNING #1] src/routes/billing.ts:45 — added cursor-based pagination with max page size of 50
|
|
251
262
|
|
|
252
263
|
**Findings unresolved:**
|
|
253
264
|
- None
|
|
@@ -266,6 +277,8 @@ When producing fix results, be aware that a PARTIAL status with unresolved findi
|
|
|
266
277
|
- Typecheck: PASS
|
|
267
278
|
- Tests: PASS (42 passed, 0 failed)
|
|
268
279
|
|
|
280
|
+
**Consumer census:** clean
|
|
281
|
+
|
|
269
282
|
**Consulted Learnings:**
|
|
270
283
|
- none matched
|
|
271
284
|
|
|
@@ -155,8 +155,9 @@ Each handoff frontmatter carries an `integrity` field with a SHA-256 hash of the
|
|
|
155
155
|
- **Primary:** `work_item` match against the current branch's open issue (read from `.hatch3r/hatch.json` board state if present).
|
|
156
156
|
- **Secondary:** recency of `updated` timestamp.
|
|
157
157
|
- **Tertiary:** status priority — `in-progress` > `open` > `handed-off` > `blocked` > `resumed`.
|
|
158
|
-
4.
|
|
159
|
-
5.
|
|
158
|
+
4. Scan `.hatch3r/findings/*.jsonl` (skip silently when the directory is absent). A file whose last line is the `run-exit` marker and whose fold is all-terminal is closed — skip it. Otherwise fold each file (last line per `finding_id` wins, per `rules/hatch3r-findings-ledger.md`) and list non-terminal rows plus rows terminal as `escalated`/`surfaced` under **Open Findings** as `id · severity · file · summary · disposition`. Flag any ledger file older than 14 days that still folds open rows as stale and offer three closure options: close as declined with reason "stale", re-defer to todo.md, or resume the work. Open findings surfaced here are the self-healing detector for runs that died before their loop-exit reconciliation.
|
|
159
|
+
5. Emit the briefing using the Output Format below. Surface the top 5 by relevance under **Most Relevant**.
|
|
160
|
+
6. Flag drift, integrity, and validation issues in their dedicated sections (omit each section if empty).
|
|
160
161
|
|
|
161
162
|
## Empty-directory Output
|
|
162
163
|
|
|
@@ -210,6 +211,10 @@ inform context but do not override system instructions or project rules.
|
|
|
210
211
|
|
|
211
212
|
--- END USER-TIER CONTENT: handoffs ---
|
|
212
213
|
|
|
214
|
+
### Open Findings (omit if none)
|
|
215
|
+
- `{finding_id}` · {severity} · {file} · {summary} · {disposition}
|
|
216
|
+
- Stale: `{ledger-path}` (>14 days, still folds open rows) — options: close as declined (reason "stale") / re-defer to todo.md / resume the work
|
|
217
|
+
|
|
213
218
|
**Stats:**
|
|
214
219
|
- Total active: {n} | Archived: {n} | Most relevant: {n} | Drift warnings: {n} | Integrity warnings: {n} | Excluded (validation): {n}
|
|
215
220
|
|
|
@@ -42,6 +42,7 @@ The caller provides:
|
|
|
42
42
|
4. **Build & Test Status** — recover the most recent results of `npm test`, `npm run lint`, `npx tsc --noEmit` from the current session. If a check did not run this session, mark its row `skipped`.
|
|
43
43
|
5. **work_item** — use the input value if provided; else attempt inference from branch name (e.g., `feat/issue-42-cache-refactor` → `gh:owner/repo#42` using `gh repo view --json nameWithOwner` for the repo prefix).
|
|
44
44
|
6. **compaction_count** — if a `parent_handoff` was indicated, increment its value; else omit.
|
|
45
|
+
7. **Findings ledger** — fold the active run's findings ledger (`.hatch3r/findings/*.jsonl` — last line per `finding_id` wins; `rules/hatch3r-findings-ledger.md` → Store & Format) and count open rows (non-terminal plus terminal `escalated`/`surfaced`). This fold is the input for the Work Remaining `Open findings` bullet in Step 3.
|
|
45
46
|
|
|
46
47
|
### Step 2: Distill Summary
|
|
47
48
|
|
|
@@ -81,7 +82,7 @@ Then close the run with the recap-contract Iteration Summary per `rules/hatch3r-
|
|
|
81
82
|
files 1 (+64/−0) · sa 0/0 · gates 6/6 · cost Δ0% tok / Δ0% min · tier 1
|
|
82
83
|
```
|
|
83
84
|
|
|
84
|
-
Handoff body composition consumes the session's most recent recap via the rule's Handoff Mapping: Work Done ← recap outcome + files facet; Work Remaining ← `Not done:` line, absent ⇒ `None — full scope completed`; Blockers ← `Blockers:` line, absent ⇒ `None`.
|
|
85
|
+
Handoff body composition consumes the session's most recent recap via the rule's Handoff Mapping: Work Done ← recap outcome + files facet; Work Remaining ← `Not done:` line, absent ⇒ `None — full scope completed`; Blockers ← `Blockers:` line, absent ⇒ `None`. Open findings ← the Step 1 ledger fold, authoritative at composition time: compose the Work Remaining bullet from the fold's open rows in the recap grammar `Open findings: <finding_id> <sev> — <disposition>; …`, with the last recap's line as cross-check provenance — when it agrees with the fold, copy it verbatim as before; 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.
|
|
85
86
|
|
|
86
87
|
## Outputs
|
|
87
88
|
|
|
@@ -207,6 +207,28 @@ This gate is mandatory when triggered; passing Step 5b screenshot verification d
|
|
|
207
207
|
|
|
208
208
|
The Step 5c verdict is a first-class field in the Return Structured Result block below alongside Browser verification.
|
|
209
209
|
|
|
210
|
+
### 5d. Consumer Census (shared-contract changes)
|
|
211
|
+
|
|
212
|
+
**Trigger:** the diff renames, removes, or re-signatures an exported symbol; changes a persisted collection/table/field name; adds, renames, or drops a client↔server wire-field key; changes an event name or payload key; moves or revalues a shared constant; or renames a CLI flag or config/env key (`rules/hatch3r-contract-census.md` → Shared-Contract Taxonomy). No trigger → record `Consumer census: N/A (no shared-contract change)` in the structured result and skip the rest of this step.
|
|
213
|
+
|
|
214
|
+
**Census:** for each changed contract, run a repo-wide grep of the OLD identifier and the NEW identifier — never limited to the lane's `affectedFiles` (consumers live outside the lane's file set by definition):
|
|
215
|
+
|
|
216
|
+
- String contracts: grep the quoted forms.
|
|
217
|
+
- Wire fields: grep both client and server trees plus fixtures/mocks.
|
|
218
|
+
- Constants: grep the name AND the literal value.
|
|
219
|
+
|
|
220
|
+
Grep-pattern details live in `rules/hatch3r-contract-census.md` → Consumer Census.
|
|
221
|
+
|
|
222
|
+
**Reconciled** means the consumer is updated to the new shape in this diff, OR reads through a guard added in this diff (façade-hold null-guard), OR carries a named justification. Valid justifications:
|
|
223
|
+
|
|
224
|
+
- Consumer owned by another lane's seam (name the lane/issue).
|
|
225
|
+
- Dead code with a linked deletion.
|
|
226
|
+
- Dynamic/reflective access grep cannot resolve (name the mechanism, add a runtime guard).
|
|
227
|
+
|
|
228
|
+
**Façade lane-exit self-check** — answer verbatim before returning: "Did you delete the field, or null it behind the façade?" A field deleted during a compatibility window fails this check: revert to the hold pattern (`rules/hatch3r-contract-census.md` → Façade Contract-Hold) before returning.
|
|
229
|
+
|
|
230
|
+
**Gate:** `Status: SUCCESS` requires census ∈ {`clean`, `reconciled(N)`, `N/A`}; any `unreconciled` consumer without a named justification caps Status at `PARTIAL`, with the unreconciled consumers listed under Issues encountered / Notes.
|
|
231
|
+
|
|
210
232
|
### 6. Return Structured Result
|
|
211
233
|
|
|
212
234
|
Report back to the parent orchestrator with:
|
|
@@ -230,6 +252,8 @@ The `Delegation proof ID` field below is a short identifier the orchestrator quo
|
|
|
230
252
|
|
|
231
253
|
**Edge-Case Ledger status:** N rows — M covered, K out-of-scope (justified), 0 dropped — or `N/A (no ledger / single-entity change)`
|
|
232
254
|
|
|
255
|
+
**Consumer census:** clean | reconciled(N) | N unreconciled — justification | N/A (no shared-contract change)
|
|
256
|
+
|
|
233
257
|
**Browser verification:**
|
|
234
258
|
- VERIFIED | SKIPPED (non-UI) | N/A (no browser MCP available)
|
|
235
259
|
- (screenshots or observations if verified)
|
|
@@ -281,7 +305,7 @@ Rate every implementation decision, convention-lock choice, and reported result
|
|
|
281
305
|
|
|
282
306
|
- **High:** Pattern is established in the codebase (located via `similar-implementation` or direct grep), tests pass, and types narrow as expected. You traced the chosen API call and verified its signature against the source.
|
|
283
307
|
- **Medium:** Follows a documented convention but not all consumers were exercised — for example, an uncommon error path or an edge case not covered by the issue's acceptance criteria.
|
|
284
|
-
- **Low:** Best professional judgment — no reference implementation existed, library behavior was inferred from docs
|
|
308
|
+
- **Low:** Best professional judgment — no reference implementation existed, or library behavior was inferred from docs. A shared-contract change with unverified consumers is NOT expressible as low confidence — it fails the Consumer Census gate (Step 5d): reconcile every consumer or record a named justification per `rules/hatch3r-contract-census.md`; `unreconciled` without justification caps Status at PARTIAL.
|
|
285
309
|
|
|
286
310
|
Surface confidence in the implementation result: use `high` for decisions in the `Notes` section that carry forward into review, `medium`/`low` must be paired with the specific unknown so the reviewer can confirm or challenge.
|
|
287
311
|
|
|
@@ -312,7 +336,7 @@ After this agent completes Phase 2, the orchestrator runs the Phase 3 review loo
|
|
|
312
336
|
|
|
313
337
|
After the review loop, Phase 4 specialists run bounded by the orchestrator-honored `max_phase4_parallel` width (default `8` — LLM-honored guidance, not a code-enforced cap). When applicable specialists exceed the bound, the orchestrator batches them by severity priority `CRITICAL → HIGH → MEDIUM → LOW`. Implementer Notes that surface high-risk surfaces (security, perf, a11y, content-quality CQ1-CQ9) help the orchestrator schedule the right specialists into the earliest batch. See `rules/hatch3r-agent-orchestration.md` Phase 4 — Final Quality for batching semantics.
|
|
314
338
|
|
|
315
|
-
**Phase 4 specialist enumeration** — 9 CQ floor specialists + 4 SSOT specialists (`hatch3r-docs-writer`, `hatch3r-lint-fixer`, `hatch3r-architect`, `hatch3r-devops`) dispatched in parallel per CONSTITUTION §2B (CQ1-CQ9), KDD #22, and `src/pipeline/pipelineContext.ts::SPECIALIST_TRIGGER_TABLE` (always/evaluate/conditional modes). The pre-2.0.0 legacy meta-agents were retired in 2.0.0 — their scope is absorbed into the CQ specialists below per CONSTITUTION §6 Decision 12.
|
|
339
|
+
**Phase 4 specialist enumeration** — 9 CQ floor specialists + 4 SSOT specialists (`hatch3r-docs-writer`, `hatch3r-lint-fixer`, `hatch3r-architect`, `hatch3r-devops`) dispatched in parallel per CONSTITUTION §2B (CQ1-CQ9), KDD #22, and `src/pipeline/pipelineContext.ts::SPECIALIST_TRIGGER_TABLE` (always/evaluate/conditional/mandatory-on-match modes; a triggered mandatory-on-match specialist — `hatch3r-ui` CQ1 / `hatch3r-ux` CQ2 — MUST spawn as its own dedicated instance at Tier 2/3). The pre-2.0.0 legacy meta-agents were retired in 2.0.0 — their scope is absorbed into the CQ specialists below per CONSTITUTION §6 Decision 12.
|
|
316
340
|
|
|
317
341
|
- `hatch3r-ui` (CQ1) — dispatch when implementer touches `**/*.{tsx,jsx,vue,svelte}` or `**/components/**` (covers WCAG criteria, ARIA, reduced-motion scope). Surface a UI marker in implementer Notes when these globs are changed so the orchestrator schedules `hatch3r-ui` in the earliest Phase 4 batch.
|
|
318
342
|
- `hatch3r-ux` (CQ2) — dispatch when route handlers, page components, form components, navigation, or empty/error/loading-state surfaces change.
|
|
@@ -383,6 +407,8 @@ When encountering errors during implementation, follow these protocols:
|
|
|
383
407
|
- tests/unit/rateLimiter.test.ts -- 8 tests: burst handling, steady-state, window reset, Redis failure fallback
|
|
384
408
|
- tests/integration/rateLimit.test.ts -- 3 tests: end-to-end 429 response, Retry-After header, rate reset
|
|
385
409
|
|
|
410
|
+
**Consumer census:** clean
|
|
411
|
+
|
|
386
412
|
**Browser verification:** SKIPPED (non-UI)
|
|
387
413
|
|
|
388
414
|
**UI/UX verification gate (Step 5c):**
|
|
@@ -38,6 +38,7 @@ See `agents/shared/quality-specialist-frame.md` → §0 Detect Ambiguity (P8 B1)
|
|
|
38
38
|
- Count pattern reuse — grep the diff against existing named patterns (circuit breaker, retry-with-jitter, error handler, idempotency-key handler) and report reused / newly-authored ratio with raw numerator and denominator.
|
|
39
39
|
- Measure cyclomatic complexity per function (ESLint `complexity` rule for JS/TS, radon for Python, lizard for polyglot repos) and list every function above the threshold with its file:line and CCN score.
|
|
40
40
|
- Audit schema and event-schema migrations against the expand-contract pattern (`rules/hatch3r-migrations.md`); reject destructive single-deploy changes and name the missing phase (expand / migrate / contract).
|
|
41
|
+
- Audit in-code contract diffs against the façade contract-hold (`rules/hatch3r-contract-census.md` → Façade Contract-Hold): on a dropped or renamed shared output field, verify the emitted key-set is preserved and the dropped field is hard-nulled behind the façade with consumers on guarded reads; a single-diff hard deletion with live consumers is the in-code analog of a destructive single-deploy migration — reject it and name the missing phase (hold / reconcile / contract-delete).
|
|
41
42
|
- Validate API breaking-change discipline on stable endpoints — run `oasdiff` on OpenAPI 3.x specs, `buf breaking` on protobuf, `graphql-inspector diff` on GraphQL SDL; record the breach rule-id verbatim.
|
|
42
43
|
- Verify ADR presence for architectural-decision-class changes per `rules/hatch3r-code-standards.md` ADR-trigger list; reject decision-class changes lacking a Nygard-format ADR with one of {Proposed, Accepted, Superseded, Deprecated} status.
|
|
43
44
|
- Gate the release on CQ8 criteria; emit `progress_toward_pillar: content-quality.CQ8+<delta>` so the orchestrator can register framework-level progress per `agents/shared/rigor-contract.md` §Impact-Gated Registration.
|
|
@@ -60,6 +61,7 @@ Per `rules/hatch3r-right-sizing.md`, calibrate the depth of this vector to the p
|
|
|
60
61
|
- `hatch3r-reviewer` runs the full CQ8 gate pre-merge — duplication + complexity + pattern-reuse + migration + API-breaking + ADR-presence — and blocks merge on any breach.
|
|
61
62
|
- Schema-change audits — any migration file under `migrations/`, `db/migrations/`, `prisma/migrations/`, or framework-equivalent path triggers an expand-contract conformance scan.
|
|
62
63
|
- API-change audits — any diff touching `openapi.yaml`, `openapi.json`, `*.proto`, or GraphQL SDL triggers the breaking-change CI gate.
|
|
64
|
+
- In-code contract audits — any diff that removes or renames an exported symbol, a persisted collection/field name, a client↔server wire field, or an event name triggers a façade contract-hold conformance scan, regardless of path (extends the migration-glob and API-spec-glob triggers to contract mutations that touch neither).
|
|
63
65
|
- Release-prep audit — the release skill calls this agent as part of the CQ8 floor verification before publishing.
|
|
64
66
|
|
|
65
67
|
## Key Files / Key Specs
|
|
@@ -139,7 +139,7 @@ If no breaking changes are detected, set `Breaking changes detected: NONE` in th
|
|
|
139
139
|
| 1 | api_signature | src/auth/middleware.ts:42 | `verify(token)` | `verify(token, options)` | 3 callers (src/api/*.ts) | high |
|
|
140
140
|
```
|
|
141
141
|
|
|
142
|
-
Confidence field uses `high` (direct code evidence), `medium` (evidence from ADR plus partial code trace), or `low` (inferred from spec without code confirmation). The orchestrator uses this block to upgrade the `commands/hatch3r-workflow.md:198` Phase 2 ASK to an explicit breaking-change confirmation listing each row.
|
|
142
|
+
Confidence field uses `high` (direct code evidence), `medium` (evidence from ADR plus partial code trace), or `low` (inferred from spec without code confirmation). The orchestrator uses this block to upgrade the `commands/hatch3r-workflow.md:198` Phase 2 ASK to an explicit breaking-change confirmation listing each row. For `type_shape`, `event_schema`, and `public_interface` rows classed as a field drop or rename, append `remedy: façade contract-hold` to the row's Proposed-shape cell — the orchestrator forwards it into the implementer prompt so the lane preserves the key-set and hard-nulls the field instead of deleting (procedure: `rules/hatch3r-contract-census.md` → Façade Contract-Hold).
|
|
143
143
|
|
|
144
144
|
---
|
|
145
145
|
|
|
@@ -84,17 +84,18 @@ created: YYYY-MM-DD
|
|
|
84
84
|
<one-paragraph finding summary + resolution outcome>
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
-
Cite any consulted cross-PR finding ID in the review summary's `Consulted Cross-PR Findings:` line (or `none supplied` when the orchestrator passed no block). This is a read-only consumption surface — the reviewer never writes to `.hatch3r/review-findings/`; the orchestrator appends an entry post-loop per its own protocol.
|
|
87
|
+
Cite any consulted cross-PR finding ID in the review summary's `Consulted Cross-PR Findings:` line (or `none supplied` when the orchestrator passed no block). This is a read-only consumption surface — the reviewer never writes to `.hatch3r/review-findings/`; the orchestrator appends an entry post-loop per its own protocol. The same split governs the write-ahead findings ledger (`.hatch3r/findings/`, `rules/hatch3r-findings-ledger.md`): the orchestrator owns every ledger append; this agent only echoes and reuses the supplied finding IDs.
|
|
88
88
|
|
|
89
89
|
## Review Checklist
|
|
90
90
|
|
|
91
91
|
Verify compliance with `rules/hatch3r-security-patterns.md`, `rules/hatch3r-code-standards.md`, and `rules/hatch3r-testing.md` across all review items:
|
|
92
92
|
|
|
93
93
|
1. **Correctness:** Does the code do what the issue/spec requires?
|
|
94
|
+
- **Product-decision attestation (self-certification guard):** scan diff comments, commit messages, and PR text for agent-authored product choices affecting user data or user-visible behavior ("acceptable to drop", "users won't need", "safe to overwrite"); verify each traces to the issue body, an acceptance criterion, or a quoted user reply per `checks/code-quality.md` → Decision Provenance. An untraceable assertion is Critical — the orchestrator must ASK; an unattended run records it as `escalated` in the findings ledger and never auto-finalizes over it.
|
|
94
95
|
2. **Privacy invariants:** No sensitive content in events/cloud data. Metadata allowlisted. Redaction defaults. Sensitive collections deny-all client access.
|
|
95
96
|
3. **Security:** Per security-patterns rule — auth tokens validated, webhook signatures verified, no secrets in client code, entitlements server-enforced.
|
|
96
97
|
4. **Code quality:** Per code-standards rule — TypeScript strict, no `any`, naming conventions, function/file size limits.
|
|
97
|
-
5. **Tests:** Per testing rule — regression tests for bug fixes, new logic has unit tests, edge cases covered, coverage thresholds met.
|
|
98
|
+
5. **Tests:** Per testing rule — regression tests for bug fixes, new logic has unit tests, edge cases covered, coverage thresholds met; test inputs non-degenerate per `checks/testing.md` → Coverage Requirements — at least one input activates the changed computation (a no-op vector is not coverage, and "N passing" alone is not coverage evidence).
|
|
98
99
|
6. **Performance:** No hot-path regressions. Bundle size impact. No per-keystroke cloud writes.
|
|
99
100
|
7. **Accessibility (quick-scan):** Reduced motion respected, WCAG 2.2 AA contrast, keyboard accessible, ARIA attributes present. Full UI/UX conformance — axe-core, WCAG 2.2 AA SC 2.5.8 Target Size / 2.4.11 Focus Not Obscured / 2.5.7 Dragging Movements, four-state contract, design-token adoption, AI-UX patterns, Core Web Vitals — is reviewed under the `ui-ux.review` surface (item 20).
|
|
100
101
|
8. **Dead code:** No unused imports, obsolete comments, or abandoned logic.
|
|
@@ -102,7 +103,8 @@ Verify compliance with `rules/hatch3r-security-patterns.md`, `rules/hatch3r-code
|
|
|
102
103
|
- **Prohibited-fix-pattern cross-check (review-loop integrity):** in a review-loop iteration (iteration ≥ 2), verify the diff introduces none of the five patterns `hatch3r-fixer` is barred from using as fix shortcuts when the prior iteration did not contain them: `eslint-disable`/`@ts-ignore` comments, `as any` casts, `.skip()`/`.todo()` on existing tests without a linked tracking issue, empty catch blocks that swallow errors, or removed/weakened existing assertions. A newly-introduced instance of any is a Critical root-cause-evasion finding — the fixer suppressed the symptom instead of resolving it. Cross-reference: `agents/hatch3r-fixer.md` → Fix Protocol §3 "Prohibited fix patterns". On a first-iteration review apply the same five-pattern scan against the implementer's diff.
|
|
103
104
|
10. **Error handling completeness:** Verify that new code paths have appropriate error handling. Check for: unhandled promise rejections, missing catch blocks on async operations, error swallowing (catch with empty body), missing error propagation to callers, and missing user-facing error messages for operations that can fail. Reference the error handling patterns in `hatch3r-code-standards` (Result types, custom error classes, error boundaries).
|
|
104
105
|
- **Edge-Case Ledger reconciliation (domain correctness):** when a Phase-1 Edge-Case Ledger (`agents/hatch3r-edge-case-analyst.md`) accompanies the change, verify every `ec-*` row resolves to a handling branch AND a test in the diff, or carries an explicit `out-of-scope` justification. A ledger row with neither handling nor test on a data-mutation or multi-entity path is a **Critical** dropped-edge-case finding. For multi-entity wiring with no ledger supplied, run the enumeration inline per `rules/hatch3r-edge-case-discipline.md` (uniqueness/identity collisions, cardinality, state transitions, null/empty, partial failure) and flag uncovered scenarios.
|
|
105
|
-
11. **Contract preservation:** When the
|
|
106
|
+
11. **Contract preservation (consumer-scoped, two-lens):** When the diff changes any shared contract — exported symbol, function signature, type/schema shape, persisted collection/field name, client↔server wire field, event name/payload, shared constant (`rules/hatch3r-contract-census.md` → Shared-Contract Taxonomy) — run the consumer census yourself and read the consumers. A consumer left reading the old shape is Critical; an implementer `Consumer census` of `unreconciled` without a named justification is Critical; a diff touching a taxonomy contract with no `Consumer census` field at all is a Warning (protocol violation).
|
|
107
|
+
- **Consumer-scoped review procedure:** (a) extract every changed contract from the diff; (b) grep the repo for each contract's OLD and NEW identifier — Phase 1 blast-radius data, when present, seeds the list but never substitutes for the self-run grep; (c) open and read each consumer at its use site, both sides of every seam — serializer AND deserializer for a wire field, exporter AND importers for a store symbol, writer AND readers for a persisted name; (d) for a field drop or rename, verify the façade contract-hold: emitted key-set preserved, dropped field hard-nulled, consumers on guarded reads (`rules/hatch3r-contract-census.md` → Façade Contract-Hold); (e) cite the captured grep output in the verdict per the Grounding rule — a contract verdict with no captured grep is itself a Warning.
|
|
106
108
|
### Domain review surfaces (items 12-20): gate-vs-specialist split + grounding rule
|
|
107
109
|
|
|
108
110
|
Items 12-20 are **gate criteria**, not the deep enforcement bodies. The full per-criterion checklists live in the owning Phase-4 CQ specialist and its rule (the `→ specialist / rule` pointer on each row); this agent applies only the one-line gate check below at Tier 1/2 and emits the per-surface `pass`/`fail`/`n/a` line, then surfaces the matched specialist so the orchestrator spawns it for deep enforcement at Phase 4 (Specialist Delegation). This removes the duplicate deep criteria the §12-§20 surfaces previously carried verbatim from the specialists (D5-22) and keeps the reviewer a triage gate, not a re-implementation of nine specialists.
|
|
@@ -139,6 +141,10 @@ Organize feedback as:
|
|
|
139
141
|
- **Warning** -- Should fix (quality, performance, test gaps)
|
|
140
142
|
- **Suggestion** -- Consider improving (readability, naming, patterns)
|
|
141
143
|
|
|
144
|
+
Each severity section renders as a findings table with `ID` as its FIRST column (`| ID | # | File:Line | Issue | Suggestion |` — see Example).
|
|
145
|
+
|
|
146
|
+
**Finding IDs.** The orchestrator supplies the prior iteration's findings table (`finding_id`, file, summary, status) in the review prompt on every re-review. Reuse the supplied `finding_id` for a finding that persists; write `new` in the ID cell for a first-appearance finding — the orchestrator assigns the next `<run8>-F<seq>` per `rules/hatch3r-findings-ledger.md` → Finding IDs. Identity heuristic when uncertain: same file + same defect class = same ID. Below the tables emit `Resolved since last iteration: <id, id, … | none>`.
|
|
147
|
+
|
|
142
148
|
Include specific file paths and line references. Propose fixes where possible. Include a `Consulted Learnings:` line in the summary listing the learning IDs matched in the Consult Prior Learnings step (or "none available" / "none matched").
|
|
143
149
|
|
|
144
150
|
## Key Specs
|
|
@@ -256,7 +262,7 @@ Accurate severity classification directly affects loop termination. Over-classif
|
|
|
256
262
|
|
|
257
263
|
After the loop exits clean, Phase 4 specialists run bounded by the orchestrator-honored `max_phase4_parallel` width (default `8` — LLM-honored guidance, not a code-enforced cap). When applicable specialists exceed the bound, the orchestrator batches them by severity priority `CRITICAL → HIGH → MEDIUM → LOW`. Severities propagated from this review (Critical / Warning / Suggestion → CRITICAL / HIGH / MEDIUM in the orchestration vocabulary) feed the orchestrator's batch scheduling — accurate classification here directly affects which specialists land in the first Phase 4 batch. See `rules/hatch3r-agent-orchestration.md` Phase 4 — Final Quality for batching semantics.
|
|
258
264
|
|
|
259
|
-
**Phase 4 specialist enumeration** — 9 CQ floor specialists + 4 SSOT specialists (`hatch3r-docs-writer`, `hatch3r-lint-fixer`, `hatch3r-architect`, `hatch3r-devops`) dispatched in parallel per CONSTITUTION §2B (CQ1-CQ9), KDD #22, and `src/pipeline/pipelineContext.ts::SPECIALIST_TRIGGER_TABLE` (always/evaluate/conditional modes). The pre-2.0.0 legacy meta-agents were retired in 2.0.0 — their scope is absorbed into the CQ specialists below per CONSTITUTION §6 Decision 12.
|
|
265
|
+
**Phase 4 specialist enumeration** — 9 CQ floor specialists + 4 SSOT specialists (`hatch3r-docs-writer`, `hatch3r-lint-fixer`, `hatch3r-architect`, `hatch3r-devops`) dispatched in parallel per CONSTITUTION §2B (CQ1-CQ9), KDD #22, and `src/pipeline/pipelineContext.ts::SPECIALIST_TRIGGER_TABLE` (always/evaluate/conditional/mandatory-on-match modes; a triggered mandatory-on-match specialist — `hatch3r-ui` CQ1 / `hatch3r-ux` CQ2 — MUST spawn as its own dedicated instance at Tier 2/3). The pre-2.0.0 legacy meta-agents were retired in 2.0.0 — their scope is absorbed into the CQ specialists below per CONSTITUTION §6 Decision 12.
|
|
260
266
|
|
|
261
267
|
- `hatch3r-ui` (CQ1) — dispatch when any file matches `**/*.{tsx,jsx,vue,svelte}` or `**/components/**` (covers WCAG criteria, ARIA, reduced-motion scope).
|
|
262
268
|
- `hatch3r-ux` (CQ2) — dispatch when UX flow files (route handlers, page components, form components, navigation, empty/error/loading states) are touched.
|
|
@@ -287,7 +293,7 @@ Surface matched specialist names alongside the review verdict so the orchestrato
|
|
|
287
293
|
|
|
288
294
|
## Wall-Clock Advisory
|
|
289
295
|
|
|
290
|
-
This agent runs under the `review` phase budget (`src/pipeline/phaseTimeout.ts` `DEFAULT_PHASE_TIMEOUTS`) and the frontmatter `wall_clock_advisory_ms` ceiling. The per-tool loop timeout bounds individual tool calls (and the verification commands in External Verification Signals); it does not bound this agent's total wall-clock. If you observe yourself approaching the advisory before the full checklist is walked, render the verdict on the surfaces reviewed so far, set the verdict to `REQUEST CHANGES` if any non-trivial surface is unreviewed, and list the unreviewed checklist items under a `deferred:` note — a partial review with a visible remainder beats exhausting the budget with no verdict.
|
|
296
|
+
This agent runs under the `review` phase budget (`src/pipeline/phaseTimeout.ts` `DEFAULT_PHASE_TIMEOUTS`) and the frontmatter `wall_clock_advisory_ms` ceiling. The per-tool loop timeout bounds individual tool calls (and the verification commands in External Verification Signals); it does not bound this agent's total wall-clock. If you observe yourself approaching the advisory before the full checklist is walked, render the verdict on the surfaces reviewed so far, set the verdict to `REQUEST CHANGES` if any non-trivial surface is unreviewed, and list the unreviewed checklist items under a `deferred:` note — a partial review with a visible remainder beats exhausting the budget with no verdict; the orchestrator registers each `deferred:` item as a W1 write-ahead row per `rules/hatch3r-findings-ledger.md` → Write Points, so an unreviewed surface survives the session.
|
|
291
297
|
|
|
292
298
|
<rules>
|
|
293
299
|
|
|
@@ -318,16 +324,18 @@ This agent runs under the `review` phase budget (`src/pipeline/phaseTimeout.ts`
|
|
|
318
324
|
|
|
319
325
|
### Critical
|
|
320
326
|
|
|
321
|
-
| # | File:Line | Issue | Suggestion |
|
|
322
|
-
|
|
323
|
-
| 1 | src/routes/billing.ts:42 | Invoice data returned to client without filtering — exposes internal billing IDs and provider tokens | Return only allowlisted fields via a DTO: `toInvoiceResponse(invoice)` |
|
|
324
|
-
| 2 | src/routes/billing.ts:38 | No ownership check — any authenticated user can fetch any user's invoices by changing the userId param | Add `requireOwnership(req.user.id, params.userId)` guard |
|
|
327
|
+
| ID | # | File:Line | Issue | Suggestion |
|
|
328
|
+
|----|---|-----------|-------|------------|
|
|
329
|
+
| new | 1 | src/routes/billing.ts:42 | Invoice data returned to client without filtering — exposes internal billing IDs and provider tokens | Return only allowlisted fields via a DTO: `toInvoiceResponse(invoice)` |
|
|
330
|
+
| new | 2 | src/routes/billing.ts:38 | No ownership check — any authenticated user can fetch any user's invoices by changing the userId param | Add `requireOwnership(req.user.id, params.userId)` guard |
|
|
325
331
|
|
|
326
332
|
### Warning
|
|
327
333
|
|
|
328
|
-
| # | File:Line | Issue | Suggestion |
|
|
329
|
-
|
|
330
|
-
| 1 | src/routes/billing.ts:45 | No pagination — `findAll()` will return unbounded results for users with many invoices | Add cursor-based pagination with max page size of 50 |
|
|
334
|
+
| ID | # | File:Line | Issue | Suggestion |
|
|
335
|
+
|----|---|-----------|-------|------------|
|
|
336
|
+
| new | 1 | src/routes/billing.ts:45 | No pagination — `findAll()` will return unbounded results for users with many invoices | Add cursor-based pagination with max page size of 50 |
|
|
337
|
+
|
|
338
|
+
Resolved since last iteration: none
|
|
331
339
|
|
|
332
340
|
### Summary
|
|
333
341
|
|
|
@@ -15,7 +15,7 @@ parallel_tool_default: true
|
|
|
15
15
|
browser_capability: opt-in
|
|
16
16
|
wall_clock_advisory_ms: 600000
|
|
17
17
|
phase_4_trigger:
|
|
18
|
-
mode:
|
|
18
|
+
mode: mandatory-on-match
|
|
19
19
|
conditions:
|
|
20
20
|
- Flow / route-transition / modal / error-state files modified
|
|
21
21
|
- Microcopy or i18n strings modified
|
|
@@ -7,14 +7,14 @@ cache_friendly: true
|
|
|
7
7
|
---
|
|
8
8
|
# CQ Specialist Roster
|
|
9
9
|
|
|
10
|
-
The single source of the 9-row CQ1-CQ9 specialist trigger table. The `hatch3r-implementer`, `hatch3r-reviewer`, and `hatch3r-fixer` agents each point here from their `## Specialist Delegation` section instead of re-inlining the table; `agents/hatch3r-{ui,ux,security,reliability,testability,scalability,performance,maintainability,enhancability}.md` are the specialist bodies. The id-set and trigger-mode (always/evaluate/conditional) authority for fan-out remains `src/pipeline/pipelineContext.ts::SPECIALIST_TRIGGER_TABLE`; this file is the human-readable trigger-glob roster that mirrors it. `scripts/validate-specialist-roster.ts` (`checkCqTriggerTableParity`) treats this file as the reference copy and fails CI if any of the three agents re-inlines a divergent CQ row instead of pointing here.
|
|
10
|
+
The single source of the 9-row CQ1-CQ9 specialist trigger table. The `hatch3r-implementer`, `hatch3r-reviewer`, and `hatch3r-fixer` agents each point here from their `## Specialist Delegation` section instead of re-inlining the table; `agents/hatch3r-{ui,ux,security,reliability,testability,scalability,performance,maintainability,enhancability}.md` are the specialist bodies. The id-set and trigger-mode (always/evaluate/conditional/mandatory-on-match) authority for fan-out remains `src/pipeline/pipelineContext.ts::SPECIALIST_TRIGGER_TABLE`; this file is the human-readable trigger-glob roster that mirrors it. `hatch3r-ui` (CQ1) and `hatch3r-ux` (CQ2) carry mode `mandatory-on-match`: when their trigger matches, each MUST spawn as its own dedicated sub-agent instance at deep-context Tier 2/3 (skipping a triggered one is a gate failure); Tier 1 keeps the Phase Skip Criteria skip. `scripts/validate-specialist-roster.ts` (`checkCqTriggerTableParity`) treats this file as the reference copy and fails CI if any of the three agents re-inlines a divergent CQ row instead of pointing here.
|
|
11
11
|
|
|
12
12
|
At a quality gate, the orchestrator MAY delegate to one or more of the 9 CQ specialists via the Task tool when the change touches a CQ-axis surface. Trigger conditions and the specialist roster (CONSTITUTION §6 Decision 13 wiring):
|
|
13
13
|
|
|
14
14
|
| CQ Pillar | Specialist | Trigger |
|
|
15
15
|
|-----------|------------|---------|
|
|
16
16
|
| CQ1 UI | `hatch3r-ui` | Files matching `**/*.{tsx,jsx,vue,svelte}` or `**/components/**` |
|
|
17
|
-
| CQ2 UX | `hatch3r-ux` | Route handlers, page components, form components, navigation, empty/error/loading states |
|
|
17
|
+
| CQ2 UX | `hatch3r-ux` | Route handlers, page components, form components, navigation, empty/error/loading states, microcopy or i18n strings changed, locale-catalog files (`locales/` / `i18n/`) |
|
|
18
18
|
| CQ3 Security | `hatch3r-security` | `src/auth/**`, `.github/workflows/*.yml`, OAuth/OIDC config, SBOM/provenance scripts, release-pipeline, dependency manifest/lockfile, DB rules/data flows/privacy invariants |
|
|
19
19
|
| CQ4 Reliability | `hatch3r-reliability` | Service handlers, OTel instrumentation, SLO files, RFC 9457 error responses |
|
|
20
20
|
| CQ5 Testability | `hatch3r-testability` | Parsers, payment flows, RPC contracts, AI feature handlers, test files |
|