Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
fdeb510
chore(fix-generated-workflow-primer-contradicts-bash-guard-blanket): …
Aug 26, 2026
2cf1cb2
docs(fix-generated-workflow-primer-contradicts-bash-guard-blanket): i…
Aug 26, 2026
e58028f
docs(fix-generated-workflow-primer-contradicts-bash-guard-blanket): c…
Aug 26, 2026
08679aa
chore(fix-generated-workflow-primer-contradicts-bash-guard-blanket): …
Aug 26, 2026
514bb32
docs(fix-generated-workflow-primer-contradicts-bash-guard-blanket): s…
Aug 26, 2026
8150933
docs(fix-generated-workflow-primer-contradicts-bash-guard-blanket): f…
Aug 26, 2026
4a123d7
docs(fix-generated-workflow-primer-contradicts-bash-guard-blanket): f…
Aug 26, 2026
54c07b1
docs(fix-generated-workflow-primer-contradicts-bash-guard-blanket): c…
Aug 26, 2026
245cee7
chore(fix-generated-workflow-primer-contradicts-bash-guard-blanket): …
Aug 26, 2026
7d28b89
docs(fix-generated-workflow-primer-contradicts-bash-guard-blanket): spec
Aug 26, 2026
e68bc2b
docs(fix-generated-workflow-primer-contradicts-bash-guard-blanket): c…
Aug 26, 2026
7e90351
chore(fix-generated-workflow-primer-contradicts-bash-guard-blanket): …
Aug 26, 2026
fc8733f
docs(fix-generated-workflow-primer-contradicts-bash-guard-blanket): s…
Aug 26, 2026
d29cd22
docs(fix-generated-workflow-primer-contradicts-bash-guard-blanket): c…
Aug 26, 2026
672450d
chore(fix-generated-workflow-primer-contradicts-bash-guard-blanket): …
Aug 26, 2026
831c976
docs(fix-generated-workflow-primer-contradicts-bash-guard-blanket): d…
Aug 26, 2026
19c2e9a
docs(fix-generated-workflow-primer-contradicts-bash-guard-blanket): r…
Aug 26, 2026
82b716d
docs(fix-generated-workflow-primer-contradicts-bash-guard-blanket): c…
Aug 26, 2026
9961b83
chore(fix-generated-workflow-primer-contradicts-bash-guard-blanket): …
Aug 26, 2026
0327e01
docs(fix-generated-workflow-primer-contradicts-bash-guard-blanket): t…
Aug 26, 2026
1d3b61f
docs(fix-generated-workflow-primer-contradicts-bash-guard-blanket): c…
Aug 26, 2026
2579c6e
chore(fix-generated-workflow-primer-contradicts-bash-guard-blanket): …
Aug 26, 2026
e5243ac
docs(workflows): scope core rule to mutating commands, acknowledge re…
Aug 26, 2026
58e07d0
docs(guard): add SYNC comments pointing at workflow-primer enumerations
Aug 26, 2026
c2e2879
fix(workflow-primer): scope mandate to mutating commands, document re…
Aug 26, 2026
833aefa
test(refresh): pin read-only subsection in workflow region output
Aug 26, 2026
8778db6
docs(claude-md): regenerate metta:workflow region from corrected primer
Aug 26, 2026
85f818d
docs(fix-generated-workflow-primer-contradicts-bash-guard-blanket): i…
Aug 26, 2026
95052ee
docs(fix-generated-workflow-primer-contradicts-bash-guard-blanket): c…
Aug 26, 2026
2d77e85
docs(fix-generated-workflow-primer-contradicts-bash-guard-blanket): m…
Aug 26, 2026
a2498b5
docs(fix-generated-workflow-primer-contradicts-bash-guard-blanket): v…
Aug 26, 2026
0df1371
docs(fix-generated-workflow-primer-contradicts-bash-guard-blanket): c…
Aug 26, 2026
bc8b826
chore(fix-generated-workflow-primer-contradicts-bash-guard-blanket): …
Aug 26, 2026
1980a4b
docs(fix-generated-workflow-primer-contradicts-bash-guard-blanket): U…
Aug 26, 2026
6da930b
chore(fix-generated-workflow-primer-contradicts-bash-guard-blanket): …
Aug 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .claude/hooks/metta-guard-bash.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import { promisify } from 'node:util';
const execFileAsync = promisify(execFile);

// Explicit ALLOW list: known safe read-only single-subcommand forms.
// SYNC: enumerated in src/delivery/workflow-primer.ts (read-only subsection / Forbidden
// bullet) — edit both together; the seam test in tests/delivery.test.ts fails on drift.
const ALLOWED_SUBCOMMANDS = new Set([
'status', 'instructions', 'progress', 'doctor',
'next', // read-only routing query (`metta next --json`); first Bash call of the metta-next skill body
Expand All @@ -45,6 +47,8 @@ const ALLOWED_SUBCOMMANDS = new Set([
]);

// Explicit ALLOW list for two-word read-only forms.
// SYNC: enumerated in src/delivery/workflow-primer.ts (read-only subsection / Forbidden
// bullet) — edit both together; the seam test in tests/delivery.test.ts fails on drift.
const ALLOWED_TWO_WORD = new Map([
['issues', new Set(['list'])],
['gate', new Set(['list'])],
Expand All @@ -64,6 +68,8 @@ const ALLOWED_TWO_WORD = new Map([
]);

// Explicit BLOCK list: state-mutating single-subcommand forms.
// SYNC: enumerated in src/delivery/workflow-primer.ts (read-only subsection / Forbidden
// bullet) — edit both together; the seam test in tests/delivery.test.ts fails on drift.
const BLOCKED_SUBCOMMANDS = new Set([
'propose', 'quick', 'auto', 'complete', 'finalize', 'ship',
'issue', 'fix-issue', 'fix-gap', 'refresh', 'import', 'init',
Expand All @@ -73,6 +79,8 @@ const BLOCKED_SUBCOMMANDS = new Set([
]);

// Explicit BLOCK list for two-word mutating forms.
// SYNC: enumerated in src/delivery/workflow-primer.ts (read-only subsection / Forbidden
// bullet) — edit both together; the seam test in tests/delivery.test.ts fails on drift.
const BLOCKED_TWO_WORD = new Map([
['backlog', new Set(['add', 'done', 'promote', 'migrate'])],
['changes', new Set(['abandon'])],
Expand All @@ -94,6 +102,8 @@ const BLOCKED_TWO_WORD = new Map([
// Bare `metta release` defaults to the read-only status view (roadmap precedent).
// Bare `metta backlog` defaults to the read-only list view; its mutating two-word
// forms (`add`/`done`/`promote`/`migrate`) stay Tier-2 blocked above.
// SYNC: enumerated in src/delivery/workflow-primer.ts (read-only subsection / Forbidden
// bullet) — edit both together; the seam test in tests/delivery.test.ts fails on drift.
const ALLOWED_BARE = new Set(['roadmap', 'release', 'backlog']);

// Subcommands that require a trusted agent_type (caller identity set by the Claude Code
Expand Down
13 changes: 11 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Stack: **Language:** TypeScript (strict mode, ES2022 target), **Runtime:** Node.

### How to work

**AI orchestrators MUST invoke the matching metta skill — never call the CLI directly.** (Humans running the CLI in a terminal are unaffected — this rule scopes to AI-driven sessions.) The skills wrap artifact authoring, review, and verification with the correct subagent personas; calling the CLI directly bypasses those guarantees and has shipped broken artifacts (see `spec/issues/metta-complete-accepts-stub-placeholder-artifacts-on-intent-.md`).
**State-mutating metta commands MUST go through the matching metta skill — never as direct CLI calls from an AI orchestrator session.** Enforcement authority is the `metta-guard-bash` PreToolUse hook: it blocks mutating and unrecognized commands (fail-closed) but permits a read-only query surface directly. (Humans running the CLI in a terminal are unaffected — this rule scopes to AI-driven sessions.) The skills wrap artifact authoring, review, and verification with the correct subagent personas; calling the CLI directly bypasses those guarantees and has shipped broken artifacts (see `spec/issues/metta-complete-accepts-stub-placeholder-artifacts-on-intent-.md`).

Primary entry points:
- `/metta-quick <description>` — small, scoped fixes (bug fixes, one-file edits, tiny refactors)
Expand All @@ -59,9 +59,18 @@ Doc-only fixes and edits to this workflow section itself are the exceptions.

### Forbidden

- Invoking `metta quick`, `metta propose`, `metta finalize`, `metta complete`, `metta issue`, or any other `metta <cmd>` directly from an AI orchestrator session. Use the matching skill.
- Invoking any state-mutating metta command directly from an AI orchestrator session: `propose`, `quick`, `auto`, `complete`, `finalize`, `ship`, `issue`, `fix-issue`, `fix-gap`, `refresh`, `import`, `init`, `verify`, `backlog add/done/promote/migrate`, `changes abandon`, `milestone create/close/update`, `roadmap add/reorder/next/remove`, `release cut`. Use the matching skill.
- Writing placeholder content like `"intent stub"` or `"summary stub"` to any artifact file to satisfy `metta complete`. Artifacts must carry real content authored by the matching `metta-*` subagent.

### Read-only queries (permitted directly)

The `metta-guard-bash` hook allows these directly — no skill needed. This list mirrors the hook's allow-lists at generation time; the hook, not this text, is authoritative:
- Single-word: `status`, `instructions`, `progress`, `doctor`, `next`, `iteration`, `model-escalation`, `tokens`, `install` (`iteration`/`model-escalation`/`tokens` append instrumentation records and `install` writes scaffolding — guard-allowed, though not strictly read-only)
- Two-word: `issues list`, `gate list`, `changes list`, `backlog list|show`, `gaps list|show`, `milestone list|show`, `release status`
- Bare (flags only): `roadmap`, `release`, `backlog` (e.g. `metta roadmap --json`)

Run bare `metta` for the full current command listing. When in doubt about a command not listed here, attempt it — the guard fails closed and blocks anything unrecognized, so an attempt is always safe and never mutates state.

### Research discipline

When a research-phase or design-phase question has a deterministic answer in public documentation — framework API docs, library reference, CLI tool manual, language spec, SDK changelog — the orchestrator MUST use `WebFetch` (for a known authoritative URL) or `WebSearch` (to discover the authoritative source) to resolve it **before** asking the user. This specifically covers questions about external framework / API / tool documented behavior (e.g. "does Claude Code support `context: fork` in skill frontmatter?", "what fields does the Anthropic Messages API accept?", "is the `--legacy-peer-deps` flag deprecated in npm 10?").
Expand Down
37 changes: 37 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1470,6 +1470,43 @@ Scenarios:
- Baseline/compare module tests cover dirt attribution
- New blocking tests fail against pre-change behavior

### Workflow Primer Mandate Is Scoped to Mutating Commands

Scenarios:
- Mandate is scoped, names the guard, and acknowledges the read-only surface
- Mandate is byte-identical across both variants
- Forbidden section enumerates mutating families instead of a blanket ban
- Primed session is directed to permitted queries for status questions

### Workflow Primer Documents the Permitted Read-Only Surface

Scenarios:
- Long primer enumerates the full allow surface
- Enumerated lists match the hook's current allow-lists exactly
- Short primer carries a one-line read-only pointer

### Workflow Primer Carries Fail-Closed Guidance as a Drift Safety Valve

Scenarios:
- Unlisted command triggers attempt-it guidance, not assumed prohibition
- List is qualified as a generation-time mirror of the guard

### All Workflow-Rule Copies Agree Across Primer, CLAUDE.md, and Docs

Scenarios:
- Metta's own CLAUDE.md region regenerates with corrected wording and preserved structure
- Docs README core-rule section matches the scoped rule
- No copy asserts a blanket ban
- Refresh replaces old blanket-ban wording in a consumer project
- Refresh over local hand-edits yields correct upstream wording

### Cross-Referenced Sync Reminders Between Primer and Guard Allow-Lists

Scenarios:
- Primer lists point at the hook
- Hook allow-lists point back at the primer
- Hook diff is comment-only with zero behavior change

## propose-stop-after

### `metta propose` MUST accept a `--stop-after <artifact>` option
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
34 requirements

### orchestration-guard
36 requirements
41 requirements

### propose-stop-after
13 requirements
Expand Down
75 changes: 74 additions & 1 deletion docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!-- Generated by Metta — do not edit directly -->
<!-- Sources: spec/archive/2026-08-26-fix-milestone-status-write-once-dead-field-no-close/summary.md...and 147 more -->
<!-- Sources: spec/archive/2026-08-26-fix-milestone-status-write-once-dead-field-no-close/summary.md...and 148 more -->
<!-- Run `metta docs generate` to regenerate -->
# Changelog

Expand Down Expand Up @@ -45,6 +45,79 @@ Every task ran `npx tsc --noEmit` (clean) and its focused vitest suites (all gre
- Review follow-up: the quality reviewer's single warning (no direct CLI test for `show` on an abandoned milestone) was closed by commit `26e0703f0`.


### 2026-08-26 — fix-generated-workflow-primer-contradicts-bash-guard-blanket

# Summary: fix-generated-workflow-primer-contradicts-bash-guard-blanket

## What changed

The generated workflow primer claimed a blanket ban on direct `metta` CLI calls while the
`metta-guard-bash` PreToolUse hook actually permits a read-only query surface. This change
scopes the primer's mandate to state-mutating commands, documents the permitted read-only
surface, and syncs all wording copies — hardened by a seam test so the hand-synced lists
cannot silently drift again.

## Implementation (by task)

- **Task 1.1** (`c2e28796a`) — `src/delivery/workflow-primer.ts`: rewrote the shared
`MANDATE` constant (scoped to state-mutating commands, names `metta-guard-bash` as the
enforcement authority, fail-closed framing, humans-in-terminal carve-out preserved); added
`READ_ONLY_POINTER` (short variant) and `READ_ONLY_SURFACE_BULLETS` — the
`### Read-only queries (permitted directly)` subsection (long variant) enumerating the
hook's single-word, two-word, and bare allow surface with a generation-time qualifier,
bare-`metta` discovery pointer, and attempt-it fail-closed guidance; rewrote the Forbidden
bullet to enumerate the full blocked surface (including `verify`, `backlog migrate`,
`milestone`/`roadmap` mutating forms, `release cut`); added SYNC comments.
`tests/delivery.test.ts`: updated the old mandate pin; new "Workflow primer scoped
mandate" describe (byte-identity pin, blanket-wording absence, subsection/authority/
fail-closed pins, preservation pins); new "Workflow primer / guard allow-list seam"
describe extracting the hook's `ALLOWED_*`/`BLOCKED_*` entries from both hook copies and
asserting each appears in the rendered primer (ADR-4 pin pattern).
- **Task 1.2** (`58e07d015`) — comment-only SYNC annotations above all five list
declarations in BOTH `src/templates/hooks/metta-guard-bash.mjs` and
`.claude/hooks/metta-guard-bash.mjs`; copies remain byte-identical; all four guard suites
pass unchanged (zero behavioral diff).
- **Task 1.3** (`e5243acf3`) — `docs/workflows/README.md` "Core rule: skills, not CLI":
scoped mandate + read-only acknowledgment pointing at CLAUDE.md's subsection; mutating
surface enumerated; stub-prohibition sentence and "CLAUDE.md wins" note preserved
verbatim; blanket wording removed.
- **Task 2.1** (`833aefa43`) — `tests/refresh.test.ts`: pinned the read-only subsection in
`buildWorkflowSection()` output.
- **Task 2.2** (`8778db66b`) — metta's own `CLAUDE.md` `metta:workflow` region regenerated
byte-exact from `buildWorkflowSection()` via a scratchpad tsx splice (direct
`metta refresh` is guard-blocked for executors); no edits outside the marker region.
- **Task 3.1** — verification sweep: PASS, no fixes needed.

## Verification evidence

- `npm test`: 135 files, 2812 passed / 2 skipped, 0 failed
- `npx tsc --noEmit`: clean
- Hook copies: `diff` empty (template vs deployed byte-identical)
- CLAUDE.md workflow region: byte-exact match against `buildWorkflowSection()` output

## Notes

- Exported primer API unchanged (`workflowPrimerShort()` / `workflowPrimerLong()`); consumer
projects receive the corrected wording on their next `metta refresh` / install scaffold.
- Known residual (out of scope, per design): `docs/internals/guard-hooks.md` carries a
fourth hand-synced copy of the allow-lists; deployment-level skew (consumer refresh
without reinstall) is not addressed by this change.

## Verification (3 parallel verifiers, iteration 1)

- **Test suite**: no deterministic failures attributable to the change. Full-suite runs on a
loaded machine hit 10s CLI-fixture timeout flakes (SIGTERM/exit 143, different test set
each run); every failed subset passes in isolation (151/151 final), and an earlier
fully green solo run recorded 135 files, 2812 passed / 2 skipped / 0 failed.
- **Typecheck/lint**: `npx tsc --noEmit` clean, `npm run lint` clean (exit 0).
- **Spec coverage**: PASS — all 15 scenarios across the 5 requirements have concrete
evidence (test names in tests/delivery.test.ts / tests/refresh.test.ts, or file/line
citations for doc-content scenarios). Both consumer-refresh scenarios rest on composed
evidence (content-agnostic region replacement + primer content pins) — sound, noted.
- **Review**: correctness PASS_WITH_WARNINGS (minor test-hardening suggestions), security
PASS, quality PASS. No critical or major findings; see review.md.


### 2026-08-23 — enforce-agent-executed-uat-run-results-attached-pr-before

# Summary: enforce-agent-executed-uat-run-results-attached-pr-before
Expand Down
4 changes: 2 additions & 2 deletions docs/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ Each sibling doc is self-contained reference material. Read `walkthroughs.md` fi

## Core rule: skills, not CLI

**AI orchestrators MUST invoke the matching metta skill — never call the CLI directly.** This applies to every AI-driven session. Humans running `metta <cmd>` in a terminal are unaffected; the rule scopes to orchestrator contexts where subagent personas and artifact-quality guarantees are load-bearing.
**State-mutating metta commands MUST go through the matching metta skill — never as direct CLI calls from an AI orchestrator session.** Enforcement authority is the `metta-guard-bash` PreToolUse hook: it blocks mutating and unrecognized commands (fail-closed) but permits a read-only query surface directly (`status`, `progress`, `issues list`, `milestone list|show`, and the rest of the allow surface — see the Read-only queries subsection in `CLAUDE.md`). Humans running `metta <cmd>` in a terminal are unaffected; the rule scopes to orchestrator contexts where subagent personas and artifact-quality guarantees are load-bearing.

Calling `metta quick`, `metta propose`, `metta finalize`, `metta complete`, `metta issue`, or any other `metta <cmd>` directly from an orchestrator bypasses the subagent wrappers. This has shipped broken artifacts in the past — see `spec/issues/metta-complete-accepts-stub-placeholder-artifacts-on-intent-.md`. Placeholder content like `"intent stub"` or `"summary stub"` is explicitly forbidden; artifacts must carry real content authored by the matching `metta-*` subagent.
Running a state-mutating command (`propose`, `quick`, `auto`, `complete`, `finalize`, `ship`, `issue`, `fix-issue`, `fix-gap`, `refresh`, `import`, `init`, `verify`, `backlog add/done/promote/migrate`, `changes abandon`, `milestone create/close/update`, `roadmap add/reorder/next/remove`, `release cut`) directly from an orchestrator bypasses the subagent wrappers. This has shipped broken artifacts in the past — see `spec/issues/metta-complete-accepts-stub-placeholder-artifacts-on-intent-.md`. Placeholder content like `"intent stub"` or `"summary stub"` is explicitly forbidden; artifacts must carry real content authored by the matching `metta-*` subagent.

The source of truth for this rule lives in the project's [`CLAUDE.md`](../../CLAUDE.md) under the `Metta Workflow` section. That file is regenerated by `/metta-refresh`; if this README drifts from it, `CLAUDE.md` wins.

Expand Down
Loading
Loading