@deftai/directive-content 0.106.0 → 0.107.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/Taskfile.yml +13 -0
- package/UPGRADING.md +2 -2
- package/commands.md +6 -3
- package/contracts/design-critique.md +268 -14
- package/contracts/issue-eval.md +77 -0
- package/contracts/path-write-fence.md +126 -1
- package/contracts/runtime-authority.md +2 -0
- package/contracts/scm-readiness.md +2 -2
- package/docs/scope-provenance.md +1 -1
- package/package.json +1 -1
- package/packs/skills/skills-pack-0.1.json +19 -5
- package/scm/github.md +34 -1
- package/skills/deft-directive-build/SKILL.md +1 -1
- package/skills/deft-directive-design-critique/SKILL.md +14 -5
- package/skills/deft-directive-feedback/SKILL.md +11 -2
- package/skills/deft-directive-issue-eval/SKILL.md +48 -0
- package/skills/deft-directive-triage/SKILL.md +3 -2
- package/tasks/engine.yml +2 -0
- package/tasks/feedback.yml +1 -1
- package/tasks/occupancy.yml +11 -0
- package/tasks/scm.yml +14 -2
- package/tasks/session.yml +11 -0
- package/tasks/triage-evaluate.yml +22 -0
- package/tasks/verify.yml +10 -0
- package/templates/agent-prompt-preamble.md +19 -2
- package/templates/agents-entry.md +5 -5
- package/templates/design-critique-brief.md +19 -5
package/Taskfile.yml
CHANGED
|
@@ -257,6 +257,10 @@ includes:
|
|
|
257
257
|
triage-classify:
|
|
258
258
|
taskfile: ./tasks/triage-classify.yml
|
|
259
259
|
optional: true
|
|
260
|
+
# #3648: `task triage:evaluate` Stage A isolated validity + parent WIP census.
|
|
261
|
+
triage-evaluate:
|
|
262
|
+
taskfile: ./tasks/triage-evaluate.yml
|
|
263
|
+
optional: true
|
|
260
264
|
# D2 (#1122): `task triage:summary` one-liner -- status surface invoked by
|
|
261
265
|
# the session-start ritual (N9 / #1149). Inner task `summary` is exposed
|
|
262
266
|
# as the user-facing alias `task triage:summary` in the alias block below.
|
|
@@ -444,6 +448,7 @@ tasks:
|
|
|
444
448
|
- verify:pack-drift
|
|
445
449
|
- verify-wip-cap-framework-self-check
|
|
446
450
|
- verify:orphan-active
|
|
451
|
+
- verify:completed-write-guard
|
|
447
452
|
- verify:agents-md-budget
|
|
448
453
|
- verify-eval-health-relocation-framework-check
|
|
449
454
|
- verify-eval-triggers-relocation-framework-check
|
|
@@ -475,6 +480,7 @@ tasks:
|
|
|
475
480
|
- verify:cache-fresh
|
|
476
481
|
- verify:wip-cap
|
|
477
482
|
- verify:orphan-active
|
|
483
|
+
- verify:completed-write-guard
|
|
478
484
|
- verify:test-boundary
|
|
479
485
|
- verify:scope-provenance
|
|
480
486
|
- verify:consumer-check-contract
|
|
@@ -991,6 +997,13 @@ tasks:
|
|
|
991
997
|
vars:
|
|
992
998
|
CLI_ARGS: "{{.CLI_ARGS}}"
|
|
993
999
|
|
|
1000
|
+
triage:evaluate:
|
|
1001
|
+
desc: "Evaluate issues off origin/master (validity + parent WIP + value). -- task triage:evaluate -- <N...> [--concurrency N] [--repo OWNER/NAME] [--json] (#3648)"
|
|
1002
|
+
cmds:
|
|
1003
|
+
- task: triage-evaluate:evaluate
|
|
1004
|
+
vars:
|
|
1005
|
+
CLI_ARGS: "{{.CLI_ARGS}}"
|
|
1006
|
+
|
|
994
1007
|
triage:queue:
|
|
995
1008
|
desc: "Print the ranked triage queue (#1128 / D11). -- task triage:queue [-- --repo OWNER/NAME] [--limit N]"
|
|
996
1009
|
cmds:
|
package/UPGRADING.md
CHANGED
|
@@ -365,9 +365,9 @@ It is common after a manual folder rename or when agents stamp the current key n
|
|
|
365
365
|
`migrate:xbrief` touches your `AGENTS.md` in two distinct regions:
|
|
366
366
|
|
|
367
367
|
- **Managed section** (between the `<!-- deft:managed-section ... -->` / `<!-- /deft:managed-section -->` markers): regenerated wholesale by `agents:refresh`, so it always reflects the current framework layout. This region is rendered from the framework template — do not hand-edit it.
|
|
368
|
-
- **Unmanaged header/tail** (everything outside those markers — your project-specific `Session orientation`, `Lifecycle` examples, `Local dev` notes): preserved verbatim across upgrades so your consumer notes survive. Because it is preserved, a rename migration would otherwise leave stale `vbrief/` path literals here. `migrate:xbrief` now applies a **bounded, idempotent** rewrite over the unmanaged region only
|
|
368
|
+
- **Unmanaged header/tail** (everything outside those markers — your project-specific `Session orientation`, `Lifecycle` examples, `Local dev` notes): preserved verbatim across upgrades so your consumer notes survive. Because it is preserved, a rename migration would otherwise leave stale `vbrief/` path literals here. `migrate:xbrief` now applies a **bounded, idempotent** rewrite over the unmanaged region only after a first-time `vbrief/` → `xbrief/` conversion, replacing `.vbrief.json`, `vbrief:preflight`, and left-bounded `vbrief/` with a child segment (`vbrief/active/...`). Bare `vbrief/` directory mentions and `x-vbrief/` leftover prefixes are left in place. It prints a summary of the replacements.
|
|
369
369
|
|
|
370
|
-
If you upgraded before this fix landed and
|
|
370
|
+
If you upgraded before this fix landed and the unmanaged header still carries child-path `vbrief/` literals, `.vbrief.json`, or `vbrief:preflight`, `deft doctor` emits an `AGENTS.md header drift:` signpost. Hand-edit those path literals. `deft migrate:xbrief` does not patch AGENTS.md on an already-xbrief tree.
|
|
371
371
|
|
|
372
372
|
**Option A (canonical, #2065):** new installs scaffold a **bounded** unmanaged header only — a project one-liner plus a **Session orientation** pointer at the canonical sources below. Do **not** add freeform `Status`, `Next:`, or `Known Issues` blocks; they are retired because the framework preserves the header verbatim while `deft doctor` only checks the managed section (#794, #1308). Session orientation comes from:
|
|
373
373
|
|
package/commands.md
CHANGED
|
@@ -293,6 +293,7 @@ Current status: the validation, extractor, provider, registry, generated MAP, an
|
|
|
293
293
|
- `task verify:capacity`, `task verify:wip-cap`, and `task verify:judgment-gates` -- policy/capacity gates.
|
|
294
294
|
- `task verify:orphan-active` -- fail closed when active/running xBRIEFs still point at closed issues or merged PRs (#2321). After merge, `task verify:orphan-active -- --issue N` scans briefs that reference that issue. Confirmed shipped prints `task scope:complete -- <path>`; unresolved lookup prints a retry remediation and still exits 1 (#3429). PR-only briefs stay on the unscoped scan or `task swarm:complete-cohort`.
|
|
295
295
|
- `task verify:lifecycle-visible` -- warn when a clone's ignore configuration hides `xbrief/` / `vbrief/` lifecycle roots (#3505). Uses `git check-ignore -v` on the stage dirs, a matching-extension sentinel under each, and bounded probes derived from ignore-rule globs in root, exclude, `core.excludesFile`, and nested lifecycle `.gitignore` files (so `2026-06-*.xbrief.json` / `2025-*.xbrief.json` cannot report clean), plus `git ls-files -v` for skip-worktree / assume-unchanged. Names the matching rule and source file. Warn-first from `session:start` (per-clone, not on `task check`). Selective `.triage-cache/*.jsonl` entries do not trip. Pass `--enforce` to fail closed.
|
|
296
|
+
- `task verify:completed-write-guard` -- fail closed when a newly added `xbrief/completed/` (or `vbrief/completed/`) artifact was not written by `scope:complete` / `scope:fail` (#3679). Artifacts larger than 1 MiB fail closed before read. Historical corpus is advisory via doctor. Remediation names the leftover land PR after a scope-provenance strip (#3476). `scope:complete` can stamp a brief already in `completed/`. Does not change `verify:completed-tracked`.
|
|
296
297
|
- `task verify:completed-tracked` -- fail closed when closed scoped issues lack a tracked `xbrief/completed/` or `xbrief/cancelled/` artifact on the delivery tip (#3264 / #3476); remediate with `task swarm:finalize-cohort` or a lifecycle PR. `task verify:completed-tracked -- --issue N` is the drive-to DONE form (delivery tip `origin/<deliveryBranch>`, not feature HEAD). Standalone verb (not part of `task check`); use `--tip HEAD` when validating an in-flight land branch. An unresolvable delivery tip fails closed (no silent HEAD fallback) -- fetch the delivery branch or pass an explicit `--tip`. Under `--skip-gh`, a named `--issue` with no cached state fails closed; the unscoped corpus scan keeps the offline allowance. Lifecycle-only lands (completed/cancelled xBRIEFs + optional CHANGELOG) use that verb plus finalize-cohort or the lifecycle PR. ⊗ Full `task check` / the TypeScript suite. ⊗ The drive-to story envelope (pre-pr + review-cycle + suite) for a file-copy land.
|
|
297
298
|
- `task verify:ac` -- product-first acceptance gate (#3284). Runs `plan.acceptance.commands` (or #3267 literal ledger) **verbatim** before done; records AC-source rung (`stated`/`derived`/`project_floor`). Empty commands require `none_stated: true`. Empty resolution is not a green run when the project has no suite floor (`soft_empty` + stamp-acceptance remedy, #3334). Primary name used first in `task check` (fail-fast); `--soft-missing-xbrief` for check composition. Rapid ceremony = AC-only; pressure/degraded makes hygiene advisory. `--capture-only` lists resolved commands without executing. Extends #3267 / #973.
|
|
298
299
|
- `task verify:literal-ac` -- #3267 mechanism alias for verbatim stated-command run (same flags/cwd); prefer `verify:ac` for product-first done-gate.
|
|
@@ -367,7 +368,7 @@ When the workflow needs an Approach 1 monitor, scope the Cursor leaf `stop-at: p
|
|
|
367
368
|
- Shared checklist SoT: `packages/core/src/session/compact-ritual.ts` (all host deposits derive from it).
|
|
368
369
|
- Codex project hooks are trust-gated by Codex. Directive can verify structural registration and command functionality, but reports trust separately as `manual-review-required` and interception as `not-directly-verified`; after an install or changed hook hash, open `/hooks` in Codex and review/approve the exact project hook commands. Runtime trust and real host interception cannot be inferred from the file or live shim probe alone.
|
|
369
370
|
- Directive writes only `.codex/hooks.json`; it does not parse or modify `.codex/config.toml`. Codex can also load inline hooks from `config.toml`, so avoid defining duplicate Directive commands there or they may run more than once. See the [Codex hooks documentation](https://learn.chatgpt.com/docs/hooks).
|
|
370
|
-
-
|
|
371
|
+
- Recognized Shell dest-forms (`git checkout -- <paths>`, `git restore`, `rm`/`rmdir`) share the active-xBRIEF write gate with Edit/Write, including assist/scratch, proposed-lifecycle, and story `file_scope` exemptions (#3438). Other shell-mediated file writes (`python -c`, `cmd /c copy`, obfuscated bash), richer unified-exec calls, and WebSearch stay unclassifiable and fail open. **Runtime authority (#1394 / #2711)** adds opt-in path allow/deny lists and graduated `scopes` (`edits`, `push`, `merge`) under `plan.policy.runtimeAuthority` — inspect with `deft policy:show --field=runtimeAuthority`. When `enabled: true`, PreToolUse denies classifiable direct-write targets outside `allowPaths` or matching `denyPaths` after ritual/scope/read-only gates; `scopes.edits` gates all direct writes. `scopes.push` / `scopes.merge` deny classifiable Shell/Bash (`git push`, `gh pr merge`) and classifiable MCP push/merge tool names; unclassifiable non-dest shell/MCP calls fail open (see `content/contracts/runtime-authority.md`). **Unified path write fence (#516 / #2443 / #2948 Wave 3):** PreToolUse also intersects project allow/deny with the active story’s `plan.metadata.swarm.file_scope` via `resolveWriteFence` (single evaluation SoT; optional `writeScope` alias normalizes at read-time only). Full contract: `content/contracts/path-write-fence.md`.
|
|
371
372
|
- **Human-origin authz + UAT mutation lease (#2944 / #2948 Wave 1)** — `deft authz:uat-start` / `authz:grant` / `authz:show`. When UAT is active, PreToolUse denies product/UI edits, push, PR create/advance, and merge without a named fix-cohort human-origin grant; tests, issue filing, and evidence/defect-capture writes stay allowed. Self-authored xBRIEF/lifecycle/dispatch tokens never satisfy implement gates. Contract: `content/contracts/human-origin-authz.md`.
|
|
372
373
|
- **Closed-verb release gates + AFK templates (#1095 / #2948 Wave 4 / #3527)** — `deft authz:grant -- --template release-publish --target <ver>` (also `release-cut`, `release-rollback`) mints Wave 1 operator-cli grants only. `task release` fails closed at the Step 10–11 tag-push / npm-publish boundary unless a matching grant exists or `DEFT_ALLOW_RELEASE_PUBLISH=1`. `deft release-publish` / `task release:publish` still fails closed before draft→public (same verb; not deleted). `--skip-tag` and dry-run stay ungated. No second session-auth mint engine. Contract: `content/contracts/closed-verb-authz.md`.
|
|
373
374
|
- **Structural scope:decompose apply grant (#3239 / #3291)** — after `scope:decompose --check` validates a draft, mint with `deft authz:grant -- --parent <parent.xbrief.json> --draft <draft.json> [--repo owner/name] [--single-use] --confirm` (typed phrase `mint` on a real TTY). Digests exact draft bytes and binds parent/target/worktree (and optional repo). Then `deft scope:decompose -- <parent> --draft <draft>`. `--check` stays ungated. Apply denies print the exact mint command.
|
|
@@ -395,7 +396,7 @@ After CLI/deposit upgrade, disk can show the new generation while a long-lived s
|
|
|
395
396
|
- ! **USER.md path (#2544):** resolve via `deft session:start` output (`USER.md resolved …`); default platform paths: Windows `%APPDATA%\deft\USER.md`, Unix `~/.config/deft/USER.md`; override `$DEFT_USER_PATH`; workspace `<project>/.deft/USER.md`. ⊗ Invent or search `~/.config/deft` on Windows — AppData Roaming is canonical.
|
|
396
397
|
- ! At mutation boundaries (code-writing, scope lifecycle moves, `start_agent`, commits, pushes, PR-from-local-changes, release work): run the mutable quick tier then gated verifier below before proceeding.
|
|
397
398
|
- ? Explicit read-only alignment only: `deft session:start -- --read-only` (no ritual-state write).
|
|
398
|
-
- ! **Worktree occupancy (#3433):** mutation `session:start` / `session:ready` claim a gitignored `.deft/occupancy.json` lease. A second mutation session on the same tree with a different `DEFT_SESSION_ID` fails closed (occupant id, intent, heartbeat age + remediation). Same-session re-arm heartbeats and keeps that id — it does not mint a new UUID. Steal with `occupancy:steal --confirm --occupant <id>` (or `session:start --steal --confirm --occupant <id>`). Expired heartbeat (20 min) is free. `--read-only` does not claim. Join (`occupancy:request`) is named in the remediation only. `swarm:launch` persists `occupancy_session_id` in a cohort-keyed record; close-out must use that cohort's entry (or `DEFT_SESSION_ID`), never a slot another launch can overwrite and never the live lease file.
|
|
399
|
+
- ! **Worktree occupancy (#3433 / #3604):** mutation `session:start` / `session:ready` claim a gitignored `.deft/occupancy.json` lease. A second mutation session on the same tree with a different `DEFT_SESSION_ID` fails closed (occupant id, intent, heartbeat age + remediation). Same-session re-arm heartbeats and keeps that id — it does not mint a new UUID. Steal with `occupancy:steal --confirm --occupant <id>` (or `session:start --steal --confirm --occupant <id>`); steal stays confirm-gated for a **live** occupant and may print existing `claimed_at` / `heartbeat_at`. The occupant drops a live lease with `occupancy:release` or `session:end`; a non-owner cannot clear a live lease. Expired heartbeat (20 min) is free (claim-over-expired); leftover files after TTL are residue, not a blocked entry path, and the same release path may clear them. No `reap` verb. `--read-only` does not claim. Join (`occupancy:request`) is named in the remediation only. `swarm:launch` persists `occupancy_session_id` in a cohort-keyed record; close-out must use that cohort's entry (or `DEFT_SESSION_ID`), never a slot another launch can overwrite and never the live lease file. Swarm close-out stays `releaseSwarmOccupancy` on complete-cohort.
|
|
399
400
|
- ~ Operators MAY still explicitly request full `deft session:start`, `deft triage:welcome`, sync, or doctor in read-only sessions.
|
|
400
401
|
|
|
401
402
|
### Assist / research posture (#1802)
|
|
@@ -451,7 +452,7 @@ Agents use this signal to prefer portable syntax and quote zsh-sensitive data su
|
|
|
451
452
|
- Shallow probe (default hot path): PATH ladder `ghx` > `gh`, injected-token env presence, short `gh auth status`.
|
|
452
453
|
- Deep probe when `--with-network` / `DEFT_SESSION_START_NETWORK=1`: full `github-auth-modes` validation (API + optional repo).
|
|
453
454
|
- Session-start never hard-blocks on SCM absence (framework-local gates still run). When not ready it lists skipped SCM-dependent gates (`triage:queue`, `issue:ingest`, `pr:*`, `reconcile:issues`, `cache:fetch-all`, `scm:*`, ...).
|
|
454
|
-
- Explicit probe: `deft scm:status` (alias `scm:readiness`) -- exit `0` ready / `1` not ready / `2` config; flags `--json`, `--deep` / `--shallow`.
|
|
455
|
+
- Explicit probe: `deft scm:status` (alias `scm:readiness`) -- exit `0` ready / `1` not ready / `2` config; flags `--json`, `--deep` / `--shallow`, `--repo OWNER/REPO`, `--expected-login`. Deep validation derives the target repo and compares an expected user login when one is supplied (#3665). GitHub App installation identity is deferred to #3693.
|
|
455
456
|
- Credential bridging: host-gh (`gh auth login` in the execution env) or injected-token (`GH_TOKEN` / `GITHUB_TOKEN` / `GH_ENTERPRISE_TOKEN`). Never put token values in prompts or transcripts.
|
|
456
457
|
- Contract: `content/contracts/scm-readiness.md`; operator docs: `content/scm/github.md` § Mismatched/headless SCM readiness.
|
|
457
458
|
|
|
@@ -549,6 +550,7 @@ Directive does not guess your mix. Either you name the next units in order (**or
|
|
|
549
550
|
### Triage Tasks
|
|
550
551
|
|
|
551
552
|
- `task triage:bootstrap -- [--repo OWNER/NAME] [--limit N] [--state {open|closed|all}] [--batch-size N] [--delay-ms N]` -- seed the local triage cache and audit layer.
|
|
553
|
+
- `task triage:evaluate -- <N...> [--concurrency N] [--repo OWNER/NAME] [--json]` -- Stage A isolated issue-eval (#3648). Detached `origin/master` worktrees own validity; the parent owns WIP census (`xbrief/active`, `xbrief/pending`, `plan-sequence`); GitHub REST owns open PRs/issues. Verdicts land under `.deft-scratch/issue-eval/<sha12>/<invocation-id>/`. No GitHub writes. Fan-out default 4. Value may set `critique-recommend:`; it must not emit `design-critique: warranted | not warranted, because …`. Decisions stay existing `triage:*` verbs.
|
|
552
554
|
- `deft triage:queue --limit=10 [--author LOGIN|@me]` -- show ranked candidate work from cache-backed state. Optional `--author` / `--author-mine` filters to cache `author.login` (exact match; `@me` resolves via authenticated `gh`; comma allow-list; missing author disclosed as unknown) (#3129 / #1318 Layer 1). When the cache is empty, auto-populates from GitHub first (#2575) — do not conclude "nothing to do" from xBRIEF folders or live `gh issue list` alone (#2576).
|
|
553
555
|
- **Ordered-plan precedence (#2402):** when `.deft/plan-sequence.json` is active, bare "what's next?" / "next PR" / "proceed" bind to the current sequence entry via `deft plan-sequence:current` — they do **not** authorize `triage:queue` or adjacent backlog picks. Use `deft verify:plan-sequence --target-kind <kind> --target <id>` before opening a PR/branch/story/sub-agent. Sequence exhaustion fails closed until the operator names a new target or explicitly asks for queue/backlog selection ("what's the queue?", "build a cohort"). Set a sequence with `deft plan-sequence:set --file <json>`; advance with `deft plan-sequence:advance`; clear with `deft plan-sequence:clear`. Do not reuse triage queue `continuationNumbers` / `continuationOrder` for this state.
|
|
554
556
|
- `task triage:accept -- --issue <N> --repo OWNER/NAME [--auto-promote] [--force]` -- accept a candidate and ingest it as a proposed scope xBRIEF. Opt-in `--auto-promote` also promotes proposed→pending in the same action (#1136); `--force` is the WIP-cap override for that promote leg.
|
|
@@ -563,6 +565,7 @@ Directive does not guess your mix. Either you name the next units in order (**or
|
|
|
563
565
|
- `task triage:summary`, `task triage:scope`, `task triage:scope-drift`, `task triage:subscribe`, `task triage:unsubscribe`, `task triage:classify`, `task triage:welcome`, and `task triage:smoketest` -- supporting workflow and onboarding commands.
|
|
564
566
|
- `task triage:classify -- --mirror [--apply] [--re-enrich] [--include-closed] [--author LOGIN|@me] [--repo owner/name] [--batch-size N] [--delay-ms N] [--sample-limit N] [--json]` -- **Bootstrap mass-triage / Tier-1 SCM label mirror (#1423 Wave 1–2 / #3125, #3129, #3197).** Runs the existing classify engine over the github-issue cache and mirrors outcomes as labels (`triaged` idempotency marker + optional `plan.policy.triageLabelMirror.actionLabels`). **Default state filter is open-only** (opt-in `--include-closed` for closed archive stamps). Optional `--author` / `--author-mine` scopes plan/apply to matching `author.login` (AND with open-only; digest surfaces the filter) (#3129). Dry-run by default: operator digest with totals (scanned/planned/already_triaged/no_match/closed_skipped/author_skipped/errors), breakdown by **state / rule / action**, and samples (not a full dump as primary UX); `--json` includes the same aggregates. `--apply` writes via the SCM label client / repo-mutation boundary in **batches** (`--batch-size`, default 10) with **rate-limit delay** (`--delay-ms`, default 1000), reports partial failures, and is idempotent on re-run (already-`triaged` skip). **Re-run vs re-enrich (#3124 / #3197):** default re-run keeps the one-shot stamp (`skipped_already_triaged`). After `actionLabels` / auto-classify rule / hold-marker changes, opt in with **`--re-enrich`** (still dry-run by default; pair with `--apply` to write) to re-classify already-stamped issues and plan **additive** label deltas only (v1 never removes obsolete chips; never full reconcile). Digest distinguishes `kind=first-time` vs `kind=re-enrich` planned/applied rows (`planned_kind` / `re_enrich_planned`). Missing labels fail closed per issue with a create-label hint. **Never** calls `triage:accept` and **never** writes `proposed/` xBRIEFs. Wave 3 (agent Tier-2 comments) remains out of scope.
|
|
565
567
|
- **Triage write-back pairing (#1423 / ADR-005).** When the author stamps that a lean is mechanism-shaped, write **both**: body-text field `mechanism-shaped: true` (the artifact) **and** mirrored label `design-critique:mechanism-shaped` (what `plan.policy.judgmentGates` matches and lists show). Do not compute the classification. No stamp -> the design-critique gate never fires. Clearance is a separate line on the thread: `design-critique: warranted | not warranted, because ...` -- engine evaluates presence, shape, and authority, never the because-clause content. Advisory/observe; `verify:judgment-gates --enforce` stays opt-in unused; `scope:promote` does not gain `--enforce` in this story.
|
|
568
|
+
- **Design-critique catalog chip (#3642).** Parent attach of `triage-ready` / recut `mechanism-shaped` MUST use `task scm:issue:design-critique-chip -- --issue N --chip triage-ready|mechanism-shaped [--repo OWNER/NAME]` (or `deft scm issue design-critique-chip`). Closed catalog remaining-set replace, one write. ⊗ `gh api POST .../labels`. ⊗ additive `scm:issue:edit --add-label`.
|
|
566
569
|
- **Operator discovery for SCM label mirror (#3124).** Cold `session:start` (via `triage:welcome` default mode) surfaces a **throttled** tip until the first successful `--mirror` dry-run or operator ack — **not** on every re-arm. Tip teaches existence **and** get-the-most: dry-run `deft triage:classify -- --mirror` (open-only; `--include-closed` opt-in); `--apply` batches writes and **never** auto-accepts into `proposed/`; defaults only stamp **`triaged` on matches** (control stamp, not disposition); **board usability is greatly decreased without `actionLabels`** — recommend full five-chip map (`defer→triage:deferred`, `archive→triage:archived`, `accept→triage:lifecycle-linked`, `escalate→triage:needs-human` + always `triaged`); more matches → `plan.policy.triageAutoClassify` in PROJECT-DEFINITION; inspect via `deft policy:show --field=plan.policy.triageLabelMirror`; labels must exist on GitHub; applying `triaged` before action chips skips re-enrichment on re-run (use `--re-enrich`); point at consumer kit **#2611** (`content/docs/consumer-issue-label-kit.md`) — do not invent vocabulary. Dismiss without dry-run: `deft triage:classify -- --ack-discovery` (production entry for tip ack). Dry-run digests SHOULD footer-hint when `actionLabels` is empty or open `no_match` dominates. **Anti-swallow:** when the tip fires, agents MUST restate existence + get-the-most in the **user-visible** message (not absorb ceremony alone).
|
|
567
570
|
|
|
568
571
|
### Cache Tasks
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Design-critique contract
|
|
2
2
|
|
|
3
|
-
Sole normative source of truth for the design-critique motion: charter, variant table, envelope and ceiling, and synthesis
|
|
3
|
+
Sole normative source of truth for the design-critique motion: charter, critic method, variant table, envelope and ceiling, synthesis format, and the operator-gated loop until synthesis is accepted. The copyable dispatch envelope is [`templates/design-critique-brief.md`](../templates/design-critique-brief.md). Phase 1 (the judgment gate) lives in [`docs/decisions/ADR-005-design-critique-judgment-gate.md`](../../docs/decisions/ADR-005-design-critique-judgment-gate.md). Parent-side substantiation principle: [`docs/decisions/ADR-006-parent-side-substantiation.md`](../../docs/decisions/ADR-006-parent-side-substantiation.md).
|
|
4
4
|
|
|
5
5
|
Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
|
|
6
6
|
|
|
@@ -11,7 +11,7 @@ This contract scaffolds the motion. Only the ADR-005 judgment gate and the conte
|
|
|
11
11
|
- ! Use `scaffolds` for protocol steps in this document.
|
|
12
12
|
- ⊗ Use the verb "enforces" here for anything other than the ADR-005 judgment gate and the content-contract tests.
|
|
13
13
|
- ⊗ Pin this contract or `skills/deft-directive-design-critique` into `templates/agents-entry.md` or the AGENTS.md always-pin list. Discovery is on-demand via the Skills Index.
|
|
14
|
-
- ⊗ Auto-dispatch critics from this contract
|
|
14
|
+
- ⊗ Auto-dispatch critics from this contract (#3578 / #1702). Operator (or parent after an operator verb) dispatches the next envelope from the brief template.
|
|
15
15
|
|
|
16
16
|
## Stop 1 — Gate
|
|
17
17
|
|
|
@@ -21,43 +21,139 @@ ADR-005 is vehicle-invariant. The gate never computes "is this triage mechanism-
|
|
|
21
21
|
2. `plan.policy.judgmentGates` matches that label. Pure syntax.
|
|
22
22
|
3. The clearance line on the thread is `design-critique: warranted | not warranted, because …`. `verify:judgment-gates` checks presence, shape, and authority. It never scores the because-clause.
|
|
23
23
|
|
|
24
|
+
The write-back first two lines name the model and role (Stop 3).
|
|
25
|
+
|
|
26
|
+
The Stop 1 write-back records `refutation-target:` naming the triage author's highest-leverage asserted premise.
|
|
27
|
+
|
|
28
|
+
- ! Record `refutation-target:` on the Stop 1 write-back.
|
|
29
|
+
- ⊗ Treat `refutation-target:` as an `audit:` marker. The field creates no unresolved-marker state and never blocks bind.
|
|
30
|
+
|
|
24
31
|
`verify:judgment-gates --enforce` stays opt-in unused in this rollout. Advisory observe first. No marker means the gate never fires. Voluntary critiques stay legal.
|
|
25
32
|
|
|
26
33
|
## Stop 2 — Variant selection
|
|
27
34
|
|
|
28
|
-
Record one line per arc:
|
|
35
|
+
Record one line per arc: the **charter** (`refutation` | `open critique`), the **spend** (`N=1`, or `N≥3` when the permission is used), and why.
|
|
36
|
+
|
|
37
|
+
- ! Record the charter and the spend as two fields. The charter is what the critic is given. The spend is how many critics that charter may use.
|
|
38
|
+
- ⊗ Record `panel` as the variant or charter. The panel row is spend permission, not a third charter.
|
|
29
39
|
|
|
30
40
|
### Variant table
|
|
31
41
|
|
|
32
|
-
| Condition |
|
|
42
|
+
| Condition | Charter | N | Exemplar |
|
|
33
43
|
|---|---|---|---|
|
|
34
44
|
| Issue body names a defensible presumption with a refutation target | refutation | N=1 | #3462 |
|
|
35
45
|
| Otherwise (default) | open critique | N=1 | #3547 |
|
|
36
|
-
| No defensible presumption, and a genuinely open solution space or high blast radius | panel | N≥3 | #3383 |
|
|
37
46
|
|
|
38
|
-
|
|
47
|
+
| Condition | Spend | N | Exemplar |
|
|
48
|
+
|---|---|---|---|
|
|
49
|
+
| A genuinely open solution space or high blast radius | panel permission (not a charter) | N≥3 permitted | #3383 |
|
|
50
|
+
|
|
51
|
+
Supersedes #3434 disposition comment 5364365428 item 4, which accepted "no defensible presumption + genuinely open solution space / high blast radius → N≥3 panel" on 2026-08-20. The conjunct treated a drafted proposal and high blast radius as mutually exclusive, so a well-specified high-blast-radius issue could not earn a panel. This table drops that conjunct and grants N≥3 as permitted, not selected.
|
|
52
|
+
|
|
53
|
+
### Evaluation rule
|
|
54
|
+
|
|
55
|
+
Charter selection and spend permission are evaluated independently.
|
|
56
|
+
|
|
57
|
+
- The first two rows select the **charter**: refutation when the issue names a defensible presumption with a refutation target; otherwise open critique. Those rows are unchanged in behaviour.
|
|
58
|
+
- The panel row grants **permission** for N≥3 when the solution space is genuinely open or blast radius is high. It does not select the charter and does not override charter.
|
|
59
|
+
- An issue that matches both a refutation charter and the panel condition is refutation with N≥3 permitted.
|
|
60
|
+
- A drafted-MUSTs issue with no refutation target and whole-motion blast radius is open critique with N≥3 permitted.
|
|
61
|
+
|
|
62
|
+
**Why permission rather than selection.** Serial reiteration is anchored by a parent-authored disagreement map correlated with round 1 by construction — the same correlation Decorrelation refuses to count as confirmation. Parallel critics carry independent priors, which is worth buying when being wrong is expensive and hard to reverse. That argues for making N≥3 available. One arc in which a panel added unique value does not establish that every high-blast-radius issue must spend it.
|
|
63
|
+
|
|
64
|
+
⊗ Add a Stop 2 variant-table trigger for "the author is the party the proposed rule would constrain." Raising N changes spend; who may substantiate and clear an interested party's claims is a role-and-clearance problem owned by Decorrelation and Non-self-arbitration. Neither requires N≥3. If constrained-party risk needs stronger treatment, it belongs in Stop 5 disclosure and non-self-clearance (#3651).
|
|
65
|
+
|
|
66
|
+
Default motion after a mechanism-shaped stamp: N=1 fresh open critique. If residual remains, one reiterating pass with a fresh critic that reads a disagreement map, then verified synthesis. Resume is optional sharpening ("does my prior finding still hold"), not the default reiterating agent. A permitted N≥3 does not change that default; the parent records the spend when it uses the permission.
|
|
39
67
|
|
|
40
68
|
## Stop 3 — Critic envelope
|
|
41
69
|
|
|
42
|
-
###
|
|
70
|
+
### Parent-facing dispatch rules
|
|
43
71
|
|
|
44
72
|
Process-only. The critic audits the lean, the protocol fit, and the recording obligations. It does not implement product work.
|
|
45
73
|
|
|
46
|
-
- ! Give the critic
|
|
74
|
+
- ! Give the critic process-only dispatch rules.
|
|
47
75
|
- ⊗ Load parent hypotheses into the envelope.
|
|
48
76
|
- ⊗ Name a refutation target unless the recorded variant is refutation.
|
|
49
77
|
- ⊗ Edit critic text after dispatch. The parent records; it does not rewrite.
|
|
50
78
|
|
|
79
|
+
### Critic method
|
|
80
|
+
|
|
81
|
+
How a critic critiques. Method-reconciliation stays at Stop 5; critics issue verdicts and therefore read it.
|
|
82
|
+
|
|
83
|
+
Strengths are not one level. Token presence is not behavioral evidence. Classification has a mechanized consumer; re-verification and inventory change the search. An empty road-not-taken or a perfunctory steelman satisfies a pin while changing nothing.
|
|
84
|
+
|
|
85
|
+
- ! Re-verify the triage's anchors by running checks. Line cites are claims, not evidence.
|
|
86
|
+
- ! Inventory existing mechanisms before proposing new ones.
|
|
87
|
+
- ! Classify every finding with the exact three tokens: `blocks-the-design`, `sharpens-framing`, or `footnote`.
|
|
88
|
+
- ! Every classified finding names evidence, a concrete failure mode, and the disposition consequence — or it is a footnote.
|
|
89
|
+
|
|
90
|
+
The three tokens are the blocking, sharpening, and footnote classes `walk all` already consumes in that order. `blocks-the-design` means the lean cannot bind as written. `sharpens-framing` means the lean can bind, but the finding changes how it is stated or scoped. That distinction is the disposition consequence the anatomy MUST already requires, not a separate evidence rubric. Two critics may still disagree; that disagreement is residual, not a contract defect. This contract does not add a decision table of evidence. A `footnote` cannot carry disposition weight: it is in the census, it is not residual, and it is not in the auto-stamp denominator. Anatomy is required of blocking and sharpening findings; a finding that cannot name evidence, a failure mode, and a disposition consequence is a footnote, not a silent skip of classification. A footnote-only post is not a stub.
|
|
91
|
+
- ! Apply the injection / swarm lens when the target changes authority, untrusted input, prompts or envelopes, identity, concurrency, worktrees, or shared state. An `N/A` paragraph on a local constant change is theater.
|
|
92
|
+
- ⊗ Close a finding with "a reviewer would catch it". That is a failed finding. If a safety case ends at reviewer attention, name a deterministic control or leave the finding unresolved.
|
|
93
|
+
- ~ When the critic actually chose among plausible mechanisms, state a road-not-taken.
|
|
94
|
+
- ~ When the critic actually chose among plausible mechanisms, steelman the strongest rejected position and name what would flip the verdict.
|
|
95
|
+
|
|
96
|
+
The injection / swarm lens is a triggered MUST: it fires only on those target changes. The reviewer-catch rule is a prohibition, not a required recital. Road-not-taken and steelman are SHOULD, and fire only on a real fork.
|
|
97
|
+
|
|
51
98
|
### Envelope and ceiling
|
|
52
99
|
|
|
53
100
|
The envelope is [`templates/design-critique-brief.md`](../templates/design-critique-brief.md). Fill fields. Do not copy rule bodies from this contract into the envelope.
|
|
54
101
|
|
|
55
102
|
- ! State an id ceiling (GitHub comment id, inclusive) at dispatch.
|
|
56
|
-
- ! Honor that ceiling. Comments after the id ceiling are out of envelope.
|
|
57
|
-
- !
|
|
103
|
+
- ! Honor that ceiling. Comments after the id ceiling are out of envelope, except the critic's own Stop 4 retry post (including after the disagreement-map input ceiling), which stays in the auto-stamp denominator.
|
|
104
|
+
- ! Critics dispatched in the same round share one issue-comment input ceiling, fixed before any sibling dispatch. A sibling's post is out of envelope for every other sibling in that round.
|
|
105
|
+
- ! That MUST claims only that siblings cannot read each other through the issue thread. It does not claim decorrelation.
|
|
106
|
+
- ! Round-1 ceiling is the triage write-back when one exists. The "thread head at dispatch" fallback applies only to a single-critic round with no triage write-back. When two or more critics share the round, take one round-start snapshot before the first sibling dispatch and use that snapshot (or the triage write-back) as the shared ceiling.
|
|
107
|
+
- ! Before dispatching two or more critics in the same round, parent posts a panel-deposit comment (`role: parent`) that names `round:`, `siblings:`, and `input-ceiling:` (the shared GitHub comment id). That comment is the durable record. A missing or malformed deposit is a contract defect.
|
|
58
108
|
- ! Round-2 ceiling is the disagreement-map comment.
|
|
59
109
|
- ! Resolve SHAs from the tree. Do not invent them.
|
|
60
110
|
|
|
111
|
+
Canonical panel-deposit:
|
|
112
|
+
|
|
113
|
+
```text
|
|
114
|
+
model: grok-4.6
|
|
115
|
+
role: parent
|
|
116
|
+
|
|
117
|
+
panel-deposit
|
|
118
|
+
round: 1
|
|
119
|
+
siblings: 3
|
|
120
|
+
input-ceiling: 5390001612
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Comment lead (model then role)
|
|
124
|
+
|
|
125
|
+
Comment-lead field. The first two lines of the triage write-back and of every critic, parent, and #3640 auto-posted comment name the LLM and the posting role. Keep the first line as `model: <slug>`. The second line is `role: triage|critic|parent`.
|
|
126
|
+
|
|
127
|
+
Canonical lead:
|
|
128
|
+
|
|
129
|
+
```text
|
|
130
|
+
model: grok-4.6
|
|
131
|
+
role: critic
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Closed role set (do not invent chips or extra roles in v1): `role: triage|critic|parent`.
|
|
135
|
+
|
|
136
|
+
| role | Who posts |
|
|
137
|
+
| --- | --- |
|
|
138
|
+
| `triage` | Stop 1 write-back |
|
|
139
|
+
| `critic` | Stop 3 / Stop 4 critic comments |
|
|
140
|
+
| `parent` | successor lean, walk decisions, verified-claims table, synthesis-accepted line, halt line, panel-deposit, disposition map if not folded into the successor lean |
|
|
141
|
+
|
|
142
|
+
- ! First line of the triage write-back comment is `model: <slug>`.
|
|
143
|
+
- ! Second line of the triage write-back comment is `role: triage`.
|
|
144
|
+
- ! First line of every critic comment is `model: <slug>` for the model that produced that comment.
|
|
145
|
+
- ! Second line of every critic comment is `role: critic`.
|
|
146
|
+
- ! Same first-two-lines on a Stop 4 retry critic (`role: critic`).
|
|
147
|
+
- ! Same first-two-lines on #3640 auto-posted table / synthesis-accepted comments (`role: parent`).
|
|
148
|
+
- ! Parent comments (successor lean, walk decisions, halt line, verified-claims table, synthesis-accepted, panel-deposit) use `role: parent`.
|
|
149
|
+
- ! Synthesis comments use the same first-two-lines (`model: <slug>` then `role: parent`).
|
|
150
|
+
- ⊗ Put the model in an issue label.
|
|
151
|
+
- ⊗ Put role in an issue label (`design-critique:critic`, author/role chips).
|
|
152
|
+
- ⊗ Put a GitHub login, author name, or role name in that lead line in place of the model.
|
|
153
|
+
- ⊗ Replace the model line with a role or GitHub login.
|
|
154
|
+
- ⊗ Infer the model from `verify:routing` or spawn metadata and omit it from the comment.
|
|
155
|
+
- ⊗ Infer role from `verify:routing` or spawn metadata and omit it from the comment.
|
|
156
|
+
|
|
61
157
|
## Stop 4 — Residual reiteration
|
|
62
158
|
|
|
63
159
|
Use this stop only when round 1 leaves residual disagreement that still changes disposition.
|
|
@@ -65,14 +161,143 @@ Use this stop only when round 1 leaves residual disagreement that still changes
|
|
|
65
161
|
- ! Dispatch a fresh critic against a disagreement map. Do not default to resume.
|
|
66
162
|
- ? Resume the same critic when the question is "does my prior finding still hold?"
|
|
67
163
|
- ! Keep the id ceiling at the disagreement-map comment for that pass.
|
|
68
|
-
-
|
|
164
|
+
- ! First-two-lines (model then `role: critic`) on the retry critic comment (Stop 3).
|
|
165
|
+
- ⊗ Run a third critic pass as the default. An N=3 panel is not a recorded why for a Stop 4 retry. See Dual stop.
|
|
166
|
+
|
|
167
|
+
## Operator-gated loop
|
|
168
|
+
|
|
169
|
+
Keep the arc in this contract until a verified synthesis is accepted.
|
|
170
|
+
|
|
171
|
+
- ! Each critic dispatch EXITs after posting.
|
|
172
|
+
- ! Operator (or parent after an operator verb) dispatches the next envelope.
|
|
173
|
+
- ! After each critic EXIT, parent posts a successor lean with proposed per-heading takes **before** printing `accept` / `retry differences` / `walk` / `walk all`. That posted lean is the first operator surface. Chat is not the record.
|
|
174
|
+
- ! Operator confirm or amend binds the proposed takes on that posted lean. Binding takes is not synthesis bind and does not stamp `design-critique:triage-ready`.
|
|
175
|
+
- ⊗ Bind synthesis or stamp `design-critique:triage-ready` while a panel-deposit for this round names `siblings:` N and fewer than N critic posts for that round exist. The first lean after one critic EXIT is the take-offer, not the bind.
|
|
176
|
+
- ! Later successor leans follow accept-X or walk-end, or land before synthesis. This supersedes #3627's "successor lean only after accept-X" for the first lean after critic EXIT. Later leans may still follow accept-X / walk-end.
|
|
177
|
+
- ⊗ Print `accept` / `retry differences` / `walk` / `walk all` when no successor lean is posted for this critic EXIT. An empty-lean verb menu is a contract miss.
|
|
178
|
+
- ⊗ Auto-dispatch critics (#3578 / #1702).
|
|
179
|
+
- ⊗ Hand the arc to `triage:accept` / `scope:promote` until `design-critique:triage-ready`.
|
|
180
|
+
- ⊗ Stamp `design-critique:triage-ready` at critic-post.
|
|
181
|
+
- ⊗ Add a `design-critique:critic-posted` chip or any author/role chip.
|
|
182
|
+
- ⊗ Critic writes issue labels.
|
|
183
|
+
- ⊗ Add a #3607 thread interlock in this contract.
|
|
184
|
+
|
|
185
|
+
## Successor lean
|
|
186
|
+
|
|
187
|
+
After each critic EXIT, parent posts a successor `**Lean:**` comment with proposed per-heading takes. That posted lean is the first operator surface. Later successor leans follow accept-X or walk-end, or land before synthesis.
|
|
188
|
+
|
|
189
|
+
- ! After critic EXIT, post the successor lean before printing `accept` / `retry differences` / `walk` / `walk all`.
|
|
190
|
+
- ! Operator confirm or amend is what makes those takes bindable. An all-accept draft still goes through this offer. Confirming or amending an all-accept first lean binds those takes. It does not auto-stamp synthesis or `design-critique:triage-ready` while same-round siblings named on the panel-deposit remain unposted.
|
|
191
|
+
- ! Cite accepted critic ids/headings, the still-open residual, and the write-back or prior lean it supersedes.
|
|
192
|
+
- ! Carry a per-heading take on the successor lean: `accept-into-contract` | `disagree` | `defer`. Defer is not accepted.
|
|
193
|
+
- ! The successor lean is the disposition map. Do not post a third map type.
|
|
194
|
+
- ! The first posted map is an ADR-006 arbitration surface. Record a substantiation token when takes introduce load-bearing premises. Non-self-arbitration applies when the same party authored the triage and the proposed takes.
|
|
195
|
+
- ! Bind synthesis and `design-critique:triage-ready` to the latest successor lean, never a superseded write-back.
|
|
196
|
+
- ! Full template (accepted set, residual, supersedes-id, ceiling if retrying) lives only on the successor lean and on a retry disagreement map.
|
|
197
|
+
- ! Walk comments stay slim (model and role lines, Accept X, critic id, heading, decision, and when needed a token plus pointer).
|
|
198
|
+
- ⊗ Edit the ceiling write-back in place.
|
|
199
|
+
- ⊗ Fold the successor lean into the critic comment.
|
|
200
|
+
- ⊗ Paraphrase critic findings as new claims.
|
|
201
|
+
|
|
202
|
+
## Parent-side substantiation
|
|
203
|
+
|
|
204
|
+
A `role: parent` artifact that introduces a load-bearing premise while adjudicating a critic finding records a substantiation token at that point. The token records the premise. It does not decide whether the reading is true.
|
|
205
|
+
|
|
206
|
+
A load-bearing premise introduced before any critic exists is outside this obligation. At Stop 1 nobody has spoken and the entire critic pass is the audit. ADR-006 addresses post-critic arbitration where the critic gets no reply. #3651's round-1 critic named a pre-critic premise and instructed: state expressly that the initial triage remains outside this amendment, or widen scope deliberately. The successor lean widened the trigger. This paragraph is the other half.
|
|
207
|
+
|
|
208
|
+
Token grammar:
|
|
209
|
+
|
|
210
|
+
```text
|
|
211
|
+
audit:<id> sha=<git-sha> pointer=<path:start-end|comment:<id>> reading=measured|asserted
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
- ! Record dispatch SHA, source pointer, and measured-versus-asserted at the point of use.
|
|
215
|
+
- ⊗ Push substantiation prose into walk comments. A token plus pointer satisfies this at the walk surface. The substantiation lives in the parent artifact or its linked successor lean.
|
|
216
|
+
- ! A premise under this section that changes classification, residual, or next-build contract stays unaudited until a later `role: critic` artifact targets its marker.
|
|
217
|
+
- ! The predicate is independence, not provenance. Primary-source citation by the parent does not clear the marker.
|
|
218
|
+
- ⊗ A `role: parent` artifact clears its own marker.
|
|
219
|
+
- ⊗ Mixed-basis laundering: one independently reproduced premise does not clear an unaudited load-bearing one.
|
|
220
|
+
- ! An unresolved marker is residual and blocks verified-synthesis bind.
|
|
221
|
+
- ⊗ Discharge a marker by promising a later pass.
|
|
222
|
+
- ! Auto-bind requires an all-accept disposition map AND zero unresolved audit markers AND the operator has confirmed or amended that map AND no unposted same-round siblings named on the panel-deposit remain. This conjunct applies at Operator verbs auto-stamp and at Bind after accepted synthesis path 1.
|
|
223
|
+
- ! The brief envelope names unresolved marker ids as `audit-targets` (ids only, or `none`). It does not carry parent rationale.
|
|
224
|
+
- ! `evaluateParentAudit` fails closed on a missing token, a silently cleared marker, a parent self-clear, or an envelope that omits a named audit target.
|
|
225
|
+
|
|
226
|
+
## Operator verbs
|
|
227
|
+
|
|
228
|
+
Contract stops stay internal. Parent prints these phrases when they apply. They apply only after a successor lean is posted for this critic EXIT. Printing the verb menu with no posted successor lean is a contract miss. The operator does not have to remember them.
|
|
229
|
+
|
|
230
|
+
- **accept** (cite findings)
|
|
231
|
+
- **retry differences**
|
|
232
|
+
- **walk**
|
|
233
|
+
- **walk all**
|
|
234
|
+
- **post the verified-claims table**
|
|
235
|
+
- **accept synthesis**
|
|
236
|
+
|
|
237
|
+
**walk** iterates recorded parent-disagree headings (successor-lean take is `disagree`). **walk all** is the census of every classified finding in existing order (blocking then sharpening then footnotes — or the critic's numbering). For one release, `walk findings one at a time` is an alias of **walk all**. Short forms of accept synthesis are valid: `accept synt`, `synt accepted`, `synt approved`, `accept synthesis`, `synthesis accepted`, `synthesis approved`. Same idea for other printed verbs when the short form is unambiguous (`retry` for `retry differences`). If the operator types a bare word that could be either **walk** or **walk all** and only one was offered, map it to the offered one. If ambiguous, parent re-prints the offered phrases and waits.
|
|
238
|
+
|
|
239
|
+
- ! Print the phrases when they apply. An empty-lean verb menu is a miss.
|
|
240
|
+
- ! Do not print **walk** until at least one proposed take on the posted lean is `disagree`.
|
|
241
|
+
- ! Do not print **retry differences** until residual headings are named on that map.
|
|
242
|
+
- ! Do not skip the first-lean offer because the draft is all-accept.
|
|
243
|
+
- ! Non-empty disagree set: print **walk** / **walk all** / **retry differences** / **accept**. Walk is an option, not the only path. Do not auto-start the walk.
|
|
244
|
+
- ! When the successor lean's per-heading map is total over a **non-empty** in-envelope classified-finding set, every heading is `accept-into-contract` (no `disagree`, no `defer`), AND zero unresolved audit markers, AND the operator has confirmed or amended that map, AND no unposted same-round siblings named on the panel-deposit remain: parent auto-posts the verified-claims table as its own comment, then auto-posts `design-critique: synthesis accepted, because agents agreed (empty disagreement set)` and remaining-set-replaces the chip via `task scm:issue:design-critique-chip -- --issue N --chip triage-ready`. Do not print **accept synthesis**, **post the verified-claims table**, **walk**, or **walk all**.
|
|
245
|
+
- ⊗ Auto-stamp a parent-drafted all-accept map that the operator has not confirmed or amended.
|
|
246
|
+
- ⊗ Auto-stamp while a panel-deposit for this round still has unposted siblings.
|
|
247
|
+
- ⊗ Auto-stamp when any audit marker is unresolved.
|
|
248
|
+
- ! The auto-stamp denominator is the union of (a) classified headings from critic comments posted in this arc and (b) still-open residual headings on the latest successor lean. Classified headings in (a) are blocking and sharpening; footnotes stay in the walk-all census and are not in (a). Each critic's own post is in-envelope for the pass that dispatched it, including a Stop 4 retry that posts after the disagreement-map input ceiling. The input id ceiling bounds what the critic may read; it does not exclude that critic's own post from the denominator. Headings already `accept-into-contract` remain in the accepted set. Still-open residual headings persist in the denominator until they receive an explicit take on a successor lean. A retry may add headings. A retry that omits, renames, splits, or merges a still-open heading does not drop the prior heading unless the successor lean cites that prior heading and records the take. Uncited still-open headings remain `disagree` (walkable) and the map is not total. A successor-lean map is total only when every heading in that union has a take. Do not auto-stamp on a partial map.
|
|
249
|
+
- ! Parse classified headings only.
|
|
250
|
+
- ⊗ Stamp when the critic posts zero classified headings (stub / blank). Stop and inform. Do not stamp.
|
|
251
|
+
- ⊗ Treat a footnote-only post as a stub. Stub is zero headings with any of the three class tokens. Footnote-only is a valid census; (a) is empty, so do not auto-stamp.
|
|
252
|
+
- ⊗ Stamp on dispatch-fail. Stop and inform. Do not stamp.
|
|
253
|
+
- ⊗ Use Phase 3 or Stop 5 as operator commands.
|
|
254
|
+
- ⊗ Infer accept-synthesis from looks-good, ok, proceed, or bare **accept**. Looks-good still does not bind.
|
|
255
|
+
- ⊗ Mix walk and retry on the same finding in one turn.
|
|
256
|
+
- ⊗ Auto-post the verified-claims table on a non-empty disagree set.
|
|
257
|
+
|
|
258
|
+
Walk order for **walk all**: classified findings in order (blocking first, then sharpening, then footnotes — or the critic's numbering). For **walk**: only headings whose successor-lean take is `disagree`. For each: restated critic claim, parent take if it differs, then wait. Each decision is a thread comment (`Accept X` / skip / amend), citing critic comment id and finding heading. Chat is not the record. When the walk ends, parent offers to post a successor lean. The walk is not synthesis. When that successor lean is later total and all `accept-into-contract` over a non-empty classified-finding set AND zero unresolved audit markers AND the operator has confirmed or amended that map AND no unposted same-round siblings named on the panel-deposit remain, the auto-table + auto-stamp path runs with no extra verb.
|
|
259
|
+
|
|
260
|
+
## Dual stop
|
|
261
|
+
|
|
262
|
+
Numbered dual stop (#2442):
|
|
263
|
+
|
|
264
|
+
- Default critic posts without extra record: 2 (round 1 plus one Stop 4 retry).
|
|
265
|
+
- A third critic only with a recorded why (panel already N≥3, or operator raises the cap for this arc). Otherwise halt.
|
|
266
|
+
- An N=3 panel is permitted three round-1 posts and no default retry. A fourth post requires the operator to raise the cap for this arc and record it.
|
|
267
|
+
- Panels larger than three (N>3) are unaddressed. The variant table permits N≥3; this section names only a third critic.
|
|
268
|
+
- Fingerprint: the set of still-open finding headings/ids on the disagreement map. Two retries in a row with that set unchanged and no new successor lean = same-fingerprint halt.
|
|
269
|
+
- Dispatch failure (no comment posted, spawn died) is a separate halt. It does not spend a retry slot. Stop and inform. Do not stamp.
|
|
270
|
+
|
|
271
|
+
### Audited residuals (panel bookkeeping)
|
|
272
|
+
|
|
273
|
+
These are not rules. They record open protocol questions with the working default one arc used. A parent that leans on any of them MUST carry an audit marker (`## Parent-side substantiation`).
|
|
274
|
+
|
|
275
|
+
- **Round-3+ ceiling.** The round-1 and round-2 ceiling rules cover those rounds. Stop 4 pins a retry to the disagreement-map comment. Round 3 and later have no stated ceiling. *Working default:* the most recent parent artifact that supersedes the map.
|
|
276
|
+
- **Amendment supersession.** The round-2 ceiling is the disagreement-map comment. An amendment that supersedes a stale map has been used as the ceiling instead. *Working default:* that amendment becomes the ceiling.
|
|
277
|
+
- **Pass-4 accounting.** Where the optional pass-4 synthesis audit counts against the budget is unaddressed. At N=3 it would be a fifth post. *Working default:* both panel arcs declined it.
|
|
278
|
+
- **Parallel fingerprint.** The halt fingerprint is the still-open headings on the disagreement map. Parallel critics merge into one map. The same-fingerprint halt assumes sequential retries against a stable finding set and is untested with a panel. *Working default:* the merged map.
|
|
279
|
+
|
|
280
|
+
## Halt line
|
|
281
|
+
|
|
282
|
+
At dual-stop halt (cap, same-fingerprint, or dispatch-fail), parent posts:
|
|
283
|
+
|
|
284
|
+
```text
|
|
285
|
+
design-critique: halted, because …
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Presence, shape, and authority only. Do not score the because-clause.
|
|
289
|
+
|
|
290
|
+
- ⊗ Add a `design-critique:halted` issue label.
|
|
291
|
+
- ! Resume after halt is a new operator verb, not a silent retry.
|
|
69
292
|
|
|
70
293
|
## Stop 5 — Verified synthesis
|
|
71
294
|
|
|
72
295
|
### Synthesis format
|
|
73
296
|
|
|
74
|
-
|
|
297
|
+
On the #3640 all-accept path, parent auto-posts the verified-claims table as its own comment (`role: parent`). On a non-empty disagree set, parent does not auto-post the table. Each quantitative row names its method.
|
|
75
298
|
|
|
299
|
+
- ! Synthesis comments start with the same first-two-lines (`model: <slug>` then `role: parent`).
|
|
300
|
+
- ! #3640 auto-posted verified-claims table and synthesis-accepted comments use `role: parent`.
|
|
76
301
|
- ! Put a method column in every verified-claims table.
|
|
77
302
|
- ! Decorrelation: a row whose only evidence is prior critics' agreement MUST NOT be marked verified. Require primary-source re-derivation or a cross-family re-check.
|
|
78
303
|
- ! Method-reconciliation: when verifying, upholding, or issuing any verdict that a measurement or count claim is false, first reproduce the original claimant's method. A different number under a different method is a discrepancy to explain, not a refutation.
|
|
@@ -82,9 +307,38 @@ Post a verified-claims table. Each quantitative row names its method.
|
|
|
82
307
|
|
|
83
308
|
Distinguish measured evidence from endorsed evidence. Same-family agreement is correlated, not confirmatory.
|
|
84
309
|
|
|
310
|
+
## Bind after accepted synthesis
|
|
311
|
+
|
|
312
|
+
Two bind paths authorize:
|
|
313
|
+
|
|
314
|
+
```text
|
|
315
|
+
design-critique: synthesis accepted, because …
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
1. #3640 auto-stamp: when the successor lean map is total over the auto-stamp denominator (critic posts in this arc, including Stop 4 retry output, plus still-open residual headings) and that set is non-empty and every heading is `accept-into-contract` AND zero unresolved audit markers AND the operator has confirmed or amended that map AND no unposted same-round siblings named on the panel-deposit remain, parent posts `design-critique: synthesis accepted, because agents agreed (empty disagreement set)` and remaining-set-replaces the chip to `design-critique:triage-ready` via `task scm:issue:design-critique-chip -- --issue N --chip triage-ready`. Do not print **accept synthesis**. Do not auto-stamp on a partial map, an unconfirmed parent draft, or when any audit marker is unresolved, or while same-round siblings remain unposted.
|
|
319
|
+
2. Explicit operator **accept synthesis** (or a listed short form). Parent may post that line and cite the verb. Then apply `design-critique:triage-ready` as the exclusive catalog chip via remaining-set write.
|
|
320
|
+
|
|
321
|
+
Closed catalog (last chip wins): `design-critique:mechanism-shaped` (in-flight, gate match) and `design-critique:triage-ready` (bound). No halt chip.
|
|
322
|
+
|
|
323
|
+
- ! Exclusive replace is one merged remaining-set write: GET current labels, drop the other catalog names (`design-critique:mechanism-shaped` and `design-critique:triage-ready`), PUT/PATCH that list with the new chip. Other facets stay. Parent write path: `task scm:issue:design-critique-chip -- --issue N --chip triage-ready|mechanism-shaped [--repo OWNER/NAME]` (`deft scm issue design-critique-chip` dual-invoke). The verb GET-drops via `applyDesignCritiqueCatalogChip` / `designCritiqueChipApplyDelta` and one `ScmLabelClient.apply`. Inventory: `LabelClient.apply` / `mergeIssueLabels`.
|
|
324
|
+
- ⊗ `gh api POST .../labels` or additive `scm:issue:edit --add-label` for this facet.
|
|
325
|
+
- ⊗ Intercept mixed `scm issue edit` adds/removes for this facet.
|
|
326
|
+
- ⊗ General-purpose labels CLI.
|
|
327
|
+
- ! After `design-critique:triage-ready`, `triage:accept` / `scope:promote` read the accepted verified synthesis (latest successor lean plus the verified-claims table).
|
|
328
|
+
- ! Keep `plan.policy.judgmentGates` matching only `design-critique:mechanism-shaped`. After `triage-ready` replaces it, the issue leaves the gate match.
|
|
329
|
+
- ! Chip is list-visible state, not consent. Do not drop `mechanism-shaped` without the synthesis-accepted line (or the #3640 empty-disagreement path).
|
|
330
|
+
- ! Write-back `mechanism-shaped: true` is history after replace. Current-state authority is the last catalog chip.
|
|
331
|
+
- ! Recut (new lean) applies `design-critique:mechanism-shaped` with the same remaining-set write and drops `triage-ready`.
|
|
332
|
+
- ~ A live `design-critique:*` count!=1 check is SHOULD, not a new `judgmentGates` match.
|
|
333
|
+
- ⊗ Add `design-critique:triage-ready` to `judgmentGates` labels.any-of.
|
|
334
|
+
- ⊗ Infer consent from looks-good.
|
|
335
|
+
- ⊗ DELETE-then-POST the chip (unchipped window if POST fails).
|
|
336
|
+
- ⊗ PUT a naive full wipe of every label.
|
|
337
|
+
- ⊗ Classify-mirror this facet.
|
|
338
|
+
|
|
85
339
|
## Failure and budget stop
|
|
86
340
|
|
|
87
|
-
- ! Failure/budget stop (#2442):
|
|
341
|
+
- ! Failure/budget stop (#2442): Dual stop and Halt line. If a critic run fails or the arc exhausts its envelope, halt with the halt line. Do not thrash.
|
|
88
342
|
|
|
89
343
|
## Security context (#480)
|
|
90
344
|
|
|
@@ -97,4 +351,4 @@ This motion ingests untrusted issue threads by design.
|
|
|
97
351
|
|
|
98
352
|
## Test surface
|
|
99
353
|
|
|
100
|
-
`packages/core/src/content-contracts/standards/design_critique_contract.test.ts` locks required pointer strings, the scaffolds framing, the brief-template forbidden-inputs list, and the thin router skill (existence, line cap, pointer resolution, no-normative-content).
|
|
354
|
+
`packages/core/src/content-contracts/standards/design_critique_contract.test.ts` locks required pointer strings, the scaffolds framing, the comment-lead field as model then role from the closed set (not an issue label), the operator-gated loop (successor lean, operator verbs including walk / walk all, dual stop, halt line, exclusive remaining-set replace of the two catalog chips, #3640 auto-stamp on a non-empty all-accept map and no-stamp on stubs, first-lean recording obligation after critic EXIT), the parent-side substantiation token and independence rules, the Stop 1 exclusion (pre-critic premises outside the trigger) and `refutation-target:` field tokens rather than full body sentences, the composed auto-bind conjunct (all-accept map AND zero unresolved audit markers) at Operator verbs and Bind path 1, the variant-table evaluation rule (charter selection and spend permission evaluated independently), the critic-method heading and distinctive obligation tokens (exact class tokens, citations-are-claims, existing mechanisms, injection / swarm trigger nouns, failed-reviewer phrase, finding anatomy) rather than full body sentences, the brief-template forbidden-inputs list, and the thin router skill (existence, line cap, pointer resolution, no-normative-content). `evaluateParentAudit` locks the omission failure modes. This suite locks the SoT MUST and the thin skill pointer for the first-lean recording obligation, including the auto-stamp operator-confirm conjunct and the no-bind-while-unposted-same-round-siblings rule. It does not fail-close live parent turns. Runtime parent-turn detection only if `evaluateParentAudit` is extended; that extension is not required to ship the recording obligation.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Issue-eval contract (#3648)
|
|
2
|
+
|
|
3
|
+
Sole normative source of truth for Stage A issue evaluation: isolated validity, parent WIP census, named gitignored sink, and value advice that must not stamp the reserved design-critique clearance line. The thin skill [`skills/deft-directive-issue-eval/SKILL.md`](../skills/deft-directive-issue-eval/SKILL.md) is a pointer only. The verb is `task triage:evaluate`.
|
|
4
|
+
|
|
5
|
+
Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
|
|
6
|
+
|
|
7
|
+
**See also**: [`design-critique.md`](./design-critique.md) (reserved clearance grammar) | [`docs/decisions/ADR-005-design-critique-judgment-gate.md`](../../docs/decisions/ADR-005-design-critique-judgment-gate.md) (gate; not amended here)
|
|
8
|
+
|
|
9
|
+
Stage B (accept-path default-flip stamp) is not this contract. ⊗ Amend ADR-005 vehicle invariance from this surface.
|
|
10
|
+
|
|
11
|
+
## Split read sources
|
|
12
|
+
|
|
13
|
+
! A detached worktree at `origin/master` owns validity and ADR / contract reads.
|
|
14
|
+
|
|
15
|
+
! The parent on the live working set owns the WIP census: `xbrief/active/`, `xbrief/pending/`, and `plan-sequence`.
|
|
16
|
+
|
|
17
|
+
! GitHub REST owns open PRs, open issues, and duplicate linkage. Prefer `ghx` for repeated GETs. ⊗ `gh issue view --json` / `gh pr view --json` (GraphQL).
|
|
18
|
+
|
|
19
|
+
! The evaluator never receives WIP conflict inputs. Parent joins after the evaluator returns.
|
|
20
|
+
|
|
21
|
+
## Verdict sink
|
|
22
|
+
|
|
23
|
+
! The parent writes under `.deft-scratch/issue-eval/<sha12>/<invocation-id>/`.
|
|
24
|
+
|
|
25
|
+
! `<sha12>` is `origin/master` at evaluation start (invalidation key). `<invocation-id>` is a fresh UUID per `triage:evaluate` invocation.
|
|
26
|
+
|
|
27
|
+
! **No assist posture marker on the CLI parent.** The parent writes after join. The evaluator writes nothing durable.
|
|
28
|
+
|
|
29
|
+
! Parent tears down evaluator worktrees on success and on failure. Parent MAY GC `<sha12>` directories that are not the current `origin/master`.
|
|
30
|
+
|
|
31
|
+
⊗ Widen `VALID_DECISIONS` or append a candidates-log row. The audit log is closed and has no SHA field.
|
|
32
|
+
|
|
33
|
+
⊗ Write under `xbrief/.eval/` (eval-health namespace).
|
|
34
|
+
|
|
35
|
+
⊗ Use `xbrief/.triage-cache/candidates.jsonl` as the verdict store.
|
|
36
|
+
|
|
37
|
+
## Evaluator worktrees
|
|
38
|
+
|
|
39
|
+
! Path: `.deft-scratch/worktrees/issue-eval-<issue>-<invocation-id>` (same layout class as `defaultWorktree`).
|
|
40
|
+
|
|
41
|
+
! Parent owns `git worktree add --detach` at `origin/master` and `git worktree remove`. The evaluator never creates or removes worktrees.
|
|
42
|
+
|
|
43
|
+
! Evaluators run `deft session:start --read-only` (never claims occupancy).
|
|
44
|
+
|
|
45
|
+
⊗ Reuse `swarm:launch` until #3649 lands (create-before-claim occupancy defect).
|
|
46
|
+
|
|
47
|
+
⊗ Checkout or commit to `origin/master` on the shared working tree.
|
|
48
|
+
|
|
49
|
+
⊗ Let evaluators read or write the shared working tree.
|
|
50
|
+
|
|
51
|
+
## Value advice grammar
|
|
52
|
+
|
|
53
|
+
! Value MAY recommend a critique via a distinct field `critique-recommend:`.
|
|
54
|
+
|
|
55
|
+
⊗ Emit `design-critique: warranted | not warranted, because …` — that line is the reserved posted clearance shape. The author stamps clearance independently.
|
|
56
|
+
|
|
57
|
+
## No GitHub writes; existing decisions
|
|
58
|
+
|
|
59
|
+
! Evaluation writes nothing to GitHub (no comments, labels, or issue edits).
|
|
60
|
+
|
|
61
|
+
! Operator decisions stay the existing `triage:*` verbs (`accept` / `reject` / `defer` / `needs-ac` / `mark-duplicate`). No new decision verb. No direct `xbrief/proposed/` write.
|
|
62
|
+
|
|
63
|
+
## Fan-out
|
|
64
|
+
|
|
65
|
+
! Default **4** parallel evaluators. Override `--concurrency N`. 4 is a bind, not a measured existing cap.
|
|
66
|
+
|
|
67
|
+
! REST-first reads.
|
|
68
|
+
|
|
69
|
+
## Acceptance-criterion amendment
|
|
70
|
+
|
|
71
|
+
The body AC "shared checkout and master untouched" is recut:
|
|
72
|
+
|
|
73
|
+
! Evaluators never read or write the shared working tree.
|
|
74
|
+
|
|
75
|
+
! The parent MAY write the named gitignored sink and create the named sibling worktrees.
|
|
76
|
+
|
|
77
|
+
! `origin/master` is not checked out and not committed to.
|