@deftai/directive-runtime 0.129.6 → 0.129.8
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 +103 -16
- package/commands.md +8 -3
- package/dist/session-start.d.ts +8 -2
- package/dist/session-start.js +33 -12
- package/dist/vbrief-preflight.d.ts +4 -0
- package/dist/vbrief-preflight.js +34 -0
- package/dist/verify-scope-provenance.d.ts +13 -1
- package/dist/verify-scope-provenance.js +44 -1
- package/docs/getting-started.md +2 -0
- package/docs/scope-provenance.md +15 -1
- package/package.json +1 -1
- package/packs/skills/skills-pack-0.1.json +1 -1
- package/scm/github.md +5 -0
- package/skills/deft-directive-review-cycle/SKILL.md +15 -6
- package/skills/deft-directive-swarm/references/host-claude-code.md +11 -1
- package/skills/deft-directive-swarm/references/host-grok-build.md +3 -2
- package/vendor/directive-content/Taskfile.yml +103 -16
- package/vendor/directive-content/commands.md +8 -3
- package/vendor/directive-content/docs/getting-started.md +2 -0
- package/vendor/directive-content/docs/scope-provenance.md +15 -1
- package/vendor/directive-content/packs/skills/skills-pack-0.1.json +1 -1
- package/vendor/directive-content/scm/github.md +5 -0
- package/vendor/directive-content/skills/deft-directive-review-cycle/SKILL.md +15 -6
- package/vendor/directive-content/skills/deft-directive-swarm/references/host-claude-code.md +11 -1
- package/vendor/directive-content/skills/deft-directive-swarm/references/host-grok-build.md +3 -2
- package/vendor/directive-core/dist/.tsbuildinfo +1 -1
- package/vendor/directive-core/dist/check/context.d.ts.map +1 -1
- package/vendor/directive-core/dist/check/context.js +3 -31
- package/vendor/directive-core/dist/check/context.js.map +1 -1
- package/vendor/directive-core/dist/check/gate-lists.d.ts.map +1 -1
- package/vendor/directive-core/dist/check/gate-lists.js +4 -32
- package/vendor/directive-core/dist/check/gate-lists.js.map +1 -1
- package/vendor/directive-core/dist/check/walk-test-files.d.ts +3 -0
- package/vendor/directive-core/dist/check/walk-test-files.d.ts.map +1 -0
- package/vendor/directive-core/dist/check/walk-test-files.js +67 -0
- package/vendor/directive-core/dist/check/walk-test-files.js.map +1 -0
- package/vendor/directive-core/dist/fs/contained-write.d.ts +8 -2
- package/vendor/directive-core/dist/fs/contained-write.d.ts.map +1 -1
- package/vendor/directive-core/dist/fs/contained-write.js +22 -6
- package/vendor/directive-core/dist/fs/contained-write.js.map +1 -1
- package/vendor/directive-core/dist/hooks/dispatcher.d.ts +7 -1
- package/vendor/directive-core/dist/hooks/dispatcher.d.ts.map +1 -1
- package/vendor/directive-core/dist/hooks/dispatcher.js +180 -10
- package/vendor/directive-core/dist/hooks/dispatcher.js.map +1 -1
- package/vendor/directive-core/dist/hooks/scope.d.ts +54 -0
- package/vendor/directive-core/dist/hooks/scope.d.ts.map +1 -1
- package/vendor/directive-core/dist/hooks/scope.js +83 -2
- package/vendor/directive-core/dist/hooks/scope.js.map +1 -1
- package/vendor/directive-core/dist/init-deposit/agent-hooks.d.ts +26 -1
- package/vendor/directive-core/dist/init-deposit/agent-hooks.d.ts.map +1 -1
- package/vendor/directive-core/dist/init-deposit/agent-hooks.js +52 -3
- package/vendor/directive-core/dist/init-deposit/agent-hooks.js.map +1 -1
- package/vendor/directive-core/dist/init-deposit/host-hook-outer.d.ts +43 -0
- package/vendor/directive-core/dist/init-deposit/host-hook-outer.d.ts.map +1 -1
- package/vendor/directive-core/dist/init-deposit/host-hook-outer.js +148 -0
- package/vendor/directive-core/dist/init-deposit/host-hook-outer.js.map +1 -1
- package/vendor/directive-core/dist/intake/reconcile-issues.d.ts +33 -1
- package/vendor/directive-core/dist/intake/reconcile-issues.d.ts.map +1 -1
- package/vendor/directive-core/dist/intake/reconcile-issues.js +288 -12
- package/vendor/directive-core/dist/intake/reconcile-issues.js.map +1 -1
- package/vendor/directive-core/dist/intake/thin-brief.d.ts +78 -0
- package/vendor/directive-core/dist/intake/thin-brief.d.ts.map +1 -0
- package/vendor/directive-core/dist/intake/thin-brief.js +224 -0
- package/vendor/directive-core/dist/intake/thin-brief.js.map +1 -0
- package/vendor/directive-core/dist/policy/ceremony-dial.d.ts.map +1 -1
- package/vendor/directive-core/dist/policy/ceremony-dial.js +2 -1
- package/vendor/directive-core/dist/policy/ceremony-dial.js.map +1 -1
- package/vendor/directive-core/dist/policy/small-change-lane.d.ts +193 -0
- package/vendor/directive-core/dist/policy/small-change-lane.d.ts.map +1 -0
- package/vendor/directive-core/dist/policy/small-change-lane.js +690 -0
- package/vendor/directive-core/dist/policy/small-change-lane.js.map +1 -0
- package/vendor/directive-core/dist/pr-merge-readiness/slizard-gate.d.ts +10 -5
- package/vendor/directive-core/dist/pr-merge-readiness/slizard-gate.d.ts.map +1 -1
- package/vendor/directive-core/dist/pr-merge-readiness/slizard-gate.js +41 -18
- package/vendor/directive-core/dist/pr-merge-readiness/slizard-gate.js.map +1 -1
- package/vendor/directive-core/dist/preflight/evaluate.d.ts +3 -0
- package/vendor/directive-core/dist/preflight/evaluate.d.ts.map +1 -1
- package/vendor/directive-core/dist/preflight/evaluate.js +15 -0
- package/vendor/directive-core/dist/preflight/evaluate.js.map +1 -1
- package/vendor/directive-core/dist/preflight-gh/pre-push.d.ts +3 -2
- package/vendor/directive-core/dist/preflight-gh/pre-push.d.ts.map +1 -1
- package/vendor/directive-core/dist/preflight-gh/pre-push.js +19 -18
- package/vendor/directive-core/dist/preflight-gh/pre-push.js.map +1 -1
- package/vendor/directive-core/dist/product-first-done-gate/evaluate.d.ts +6 -0
- package/vendor/directive-core/dist/product-first-done-gate/evaluate.d.ts.map +1 -1
- package/vendor/directive-core/dist/product-first-done-gate/evaluate.js +26 -0
- package/vendor/directive-core/dist/product-first-done-gate/evaluate.js.map +1 -1
- package/vendor/directive-core/dist/scope/decomposed-refs.d.ts +7 -0
- package/vendor/directive-core/dist/scope/decomposed-refs.d.ts.map +1 -1
- package/vendor/directive-core/dist/scope/decomposed-refs.js +27 -10
- package/vendor/directive-core/dist/scope/decomposed-refs.js.map +1 -1
- package/vendor/directive-core/dist/scope/delivery-evidence.d.ts +218 -19
- package/vendor/directive-core/dist/scope/delivery-evidence.d.ts.map +1 -1
- package/vendor/directive-core/dist/scope/delivery-evidence.js +973 -107
- package/vendor/directive-core/dist/scope/delivery-evidence.js.map +1 -1
- package/vendor/directive-core/dist/scope/transition.d.ts +7 -1
- package/vendor/directive-core/dist/scope/transition.d.ts.map +1 -1
- package/vendor/directive-core/dist/scope/transition.js +45 -5
- package/vendor/directive-core/dist/scope/transition.js.map +1 -1
- package/vendor/directive-core/dist/scope-provenance/base-fence.d.ts +13 -3
- package/vendor/directive-core/dist/scope-provenance/base-fence.d.ts.map +1 -1
- package/vendor/directive-core/dist/scope-provenance/base-fence.js +25 -2
- package/vendor/directive-core/dist/scope-provenance/base-fence.js.map +1 -1
- package/vendor/directive-core/dist/scope-provenance/evaluate.d.ts +12 -0
- package/vendor/directive-core/dist/scope-provenance/evaluate.d.ts.map +1 -1
- package/vendor/directive-core/dist/scope-provenance/evaluate.js +41 -5
- package/vendor/directive-core/dist/scope-provenance/evaluate.js.map +1 -1
- package/vendor/directive-core/dist/scope-provenance/forge-approval.d.ts +106 -0
- package/vendor/directive-core/dist/scope-provenance/forge-approval.d.ts.map +1 -0
- package/vendor/directive-core/dist/scope-provenance/forge-approval.js +382 -0
- package/vendor/directive-core/dist/scope-provenance/forge-approval.js.map +1 -0
- package/vendor/directive-core/dist/session/orientation-compression.d.ts +18 -2
- package/vendor/directive-core/dist/session/orientation-compression.d.ts.map +1 -1
- package/vendor/directive-core/dist/session/orientation-compression.js +38 -5
- package/vendor/directive-core/dist/session/orientation-compression.js.map +1 -1
- package/vendor/directive-core/dist/session/session-start.d.ts +47 -2
- package/vendor/directive-core/dist/session/session-start.d.ts.map +1 -1
- package/vendor/directive-core/dist/session/session-start.js +149 -1
- package/vendor/directive-core/dist/session/session-start.js.map +1 -1
- package/vendor/directive-core/dist/swarm/approach1-babysitter.d.ts +18 -4
- package/vendor/directive-core/dist/swarm/approach1-babysitter.d.ts.map +1 -1
- package/vendor/directive-core/dist/swarm/approach1-babysitter.js +28 -4
- package/vendor/directive-core/dist/swarm/approach1-babysitter.js.map +1 -1
- package/vendor/directive-core/dist/swarm/finalize-cohort.d.ts +48 -0
- package/vendor/directive-core/dist/swarm/finalize-cohort.d.ts.map +1 -1
- package/vendor/directive-core/dist/swarm/finalize-cohort.js +175 -19
- package/vendor/directive-core/dist/swarm/finalize-cohort.js.map +1 -1
- package/vendor/directive-core/dist/swarm/finalize-owed.d.ts +18 -3
- package/vendor/directive-core/dist/swarm/finalize-owed.d.ts.map +1 -1
- package/vendor/directive-core/dist/swarm/finalize-owed.js +139 -32
- package/vendor/directive-core/dist/swarm/finalize-owed.js.map +1 -1
- package/vendor/directive-core/dist/swarm/launch.d.ts.map +1 -1
- package/vendor/directive-core/dist/swarm/launch.js +4 -8
- package/vendor/directive-core/dist/swarm/launch.js.map +1 -1
- package/vendor/directive-core/dist/swarm/worker-auth-assignment.d.ts +7 -0
- package/vendor/directive-core/dist/swarm/worker-auth-assignment.d.ts.map +1 -1
- package/vendor/directive-core/dist/swarm/worker-auth-assignment.js +16 -1
- package/vendor/directive-core/dist/swarm/worker-auth-assignment.js.map +1 -1
- package/vendor/directive-core/dist/task-surface/index.d.ts.map +1 -1
- package/vendor/directive-core/dist/task-surface/index.js +41 -0
- package/vendor/directive-core/dist/task-surface/index.js.map +1 -1
- package/vendor/directive-core/dist/triage/evaluate/worktrees.d.ts.map +1 -1
- package/vendor/directive-core/dist/triage/evaluate/worktrees.js +219 -60
- package/vendor/directive-core/dist/triage/evaluate/worktrees.js.map +1 -1
- package/vendor/directive-core/dist/vbrief-reconcile/types.d.ts +5 -1
- package/vendor/directive-core/dist/vbrief-reconcile/types.d.ts.map +1 -1
- package/vendor/directive-core/dist/vbrief-reconcile/umbrellas.d.ts.map +1 -1
- package/vendor/directive-core/dist/vbrief-reconcile/umbrellas.js +19 -7
- package/vendor/directive-core/dist/vbrief-reconcile/umbrellas.js.map +1 -1
package/scm/github.md
CHANGED
|
@@ -722,6 +722,11 @@ Up-to-date-required branch protection plus a required `Merge gate (task check)`
|
|
|
722
722
|
|
|
723
723
|
⊗ Mutate GitHub `mergeable_state` to encode semantic/policy readiness — forge enrollment + local probe are the dispositioned alternatives (#4888 Prefer-A Bound Reject E).
|
|
724
724
|
|
|
725
|
+
### Lifecycle PRs: CHANGELOG and spec-drift ledger (#680)
|
|
726
|
+
|
|
727
|
+
- `verify:changelog-unreleased` skips the new-entry compare when the change set versus merge-base (`git diff --name-only --no-renames`) is non-empty and every path is a lifecycle brief (`xbrief|vbrief/<lifecycle>/`), `CHANGELOG.md`, or `xbrief/.audit/spec-drift-ledger.json`. Activation and completion PRs need no operator CHANGELOG line. Product changes and an empty change set keep the requirement.
|
|
728
|
+
- `scope:complete` writes the spec-drift ledger; `swarm:finalize-cohort` commits it with the completed briefs. Membership admits exactly that ledger path only when the whole change set is a completion move. The verbs own these writes, so agents do not hand-write CHANGELOG or ledger lines on a lifecycle PR.
|
|
729
|
+
|
|
725
730
|
### Before flipping (operator)
|
|
726
731
|
|
|
727
732
|
1. Confirm the required context name is exactly `Merge gate (task check)` (the aggregator). Do not require primary or failover lane names.
|
|
@@ -536,13 +536,21 @@ REDISPATCH_OK: yes|no
|
|
|
536
536
|
⊗ Treat `ci_never_scheduled` as ordinary Greptile latency (`sha_match` / `terminal_check_run` only).
|
|
537
537
|
⊗ Silent `--skip-ci` / admin merge without the outage playbook audit trail below.
|
|
538
538
|
|
|
539
|
-
### SLizard advisory-only for merge-ready wait (#3167)
|
|
539
|
+
### SLizard advisory-only for merge-ready wait (#3167) — weather vs residual (#5102 / #4387)
|
|
540
540
|
|
|
541
|
-
!
|
|
541
|
+
! SLizard is advisory only for the Greptile merge-ready confidence floor; parseable blocking tip fingerprints are unfinished residual (#5102 / #3167).
|
|
542
542
|
|
|
543
|
-
!
|
|
543
|
+
! Required bot for **merge-ready wait** / Step 6 exit ownership is **Greptile**. SLizard is **advisory only** for weather (timeout / cancelled / unparseable / zero-finding / missing-check): those MUST NOT gate the review-cycle wait loop (#3167). Parseable blocking tip fingerprints are unfinished residual (#5102).
|
|
544
544
|
|
|
545
|
-
|
|
545
|
+
! When `pr:merge-ready` / wait-mergeable reports **SLizard blocked** (parseable `request_changes` or `merge_impact=blocking` with non-zero findings) — especially Greptile CLEAN + SLizard blocked — before re-arming merge-ready wait or `pr:wait-mergeable-and-merge` the owner MUST read the tip SLizard **review body** in full, enumerate new and Previously mentioned fingerprints / deterministic tool names, and for each open P0/P1 falsify with `git show <head>:<path>` (slizard#2694) or fix in one residual batch. Do not idle-poll. Keep `pr:watch` Greptile ownership unchanged (#5102 / #2189 / #4387).
|
|
546
|
+
|
|
547
|
+
! Compose existing head-blob check, same-fingerprint stop (#3448), and `--skip-slizard` override. Do not invent a third poller. `--skip-slizard` is explicit override only — not the default babysit escape.
|
|
548
|
+
|
|
549
|
+
! Parseable blocking findings with open tip fingerprints are **unfinished residual**, not weather. Cross-link: `packages/core/src/pr-merge-readiness/slizard-gate.ts` (`evaluateSlizardGate`).
|
|
550
|
+
|
|
551
|
+
⊗ Re-arm wait-mergeable / idle-poll while SLizard still has parseable blocking findings with open tip fingerprints (#5102).
|
|
552
|
+
⊗ Treat parseable blocking SLizard findings as #3167 weather when Greptile Step 6 is clean (#5102 / #4387).
|
|
553
|
+
⊗ Default to `--skip-slizard` to clear a merge-ready SLizard block (#5102).
|
|
546
554
|
|
|
547
555
|
### Outage admin-merge playbook (opt-in / human, #3167)
|
|
548
556
|
|
|
@@ -725,7 +733,7 @@ Cross-links: swarm decision tree `skills/deft-directive-swarm/references/core-ph
|
|
|
725
733
|
|
|
726
734
|
! When the platform descriptor indicates Tier 1 (sub-agent support) **and this agent owns the primitive as parent/orchestrator**, spawn a review-monitor sub-agent using the primitive matching the descriptor. ⊗ A grok-build / grok-bot / Cursor / Claude Code implementation leaf MUST NOT run these spawn steps.
|
|
727
735
|
|
|
728
|
-
1. ! Launch via the matching primitive: `start_agent` (Warp), `spawn_subagent` (grok-build / TUI / non-Warp **parent**), the Cursor `Task` tool with `run_in_background: true` (`cursor-composer` / `cursor-cloud-agent`, #1877), the Claude Code `Agent` tool with `run_in_background: true` (`claude-code` / register `claude-agent`, #3134), OpenClaw `sessions_spawn` (`openclaw`, #2876), **or Grok Bot Task/executor/CloudAgent (`grok-bot` / register `grok-bot-executor`, #4201)** with a prompt that instructs it to poll for Greptile completion. For `spawn_subagent`, Cursor `Task`, Claude Code `Agent`, OpenClaw `sessions_spawn`, and Grok Bot executor the prompt MUST reference the canonical poller template `templates/swarm-greptile-poller-prompt.md` (with placeholders filled) plus the agent preamble; the working directory / context must be the PR branch (worktree or equivalent for hybrid).
|
|
736
|
+
1. ! Launch via the matching primitive: `start_agent` (Warp), `spawn_subagent` (grok-build / TUI / non-Warp **parent**), the Cursor `Task` tool with `run_in_background: true` (`cursor-composer` / `cursor-cloud-agent`, #1877), the Claude Code `Agent` tool with `run_in_background: true` (`claude-code` / register `claude-agent`, #3134), OpenClaw `sessions_spawn` (`openclaw`, #2876), **or Grok Bot Task/executor/CloudAgent (`grok-bot` / register `grok-bot-executor`, #4201)** with a prompt that instructs it to poll for Greptile completion. For `spawn_subagent`, Cursor `Task`, Claude Code `Agent`, OpenClaw `sessions_spawn`, and Grok Bot executor the prompt MUST reference the canonical poller template `templates/swarm-greptile-poller-prompt.md` (with placeholders filled) plus the agent preamble; the working directory / context must be the PR branch (worktree or equivalent for hybrid). **Grok Approach 1 watch/report (#4781):** before `review-monitor:register` / child `pr:watch`, spawn with advertised `process_only: true` + dest `cwd` for `stop-at: pr-open` + `worker_role: review-monitor` seats only (`formatApproach1ProcessOnlySpawnShape` / `approach1BabysitterCommands`). Implement-class never sets `process_only`; dest-path is not the skip class; do not blanket-flag the fix-capable greptile poller.
|
|
729
737
|
2. ! The sub-agent polls using the mechanism for its primitive: for `spawn_subagent` the **child** owns `pr:watch` / gh poll in its own process (adaptive cadence: ~20-30s first check after push, ~60s second, ~90s thereafter; Greptile typically lands in 3-7 min) — the user-facing parent MUST NOT enter `get_command_or_subagent_output`; a named durable-owner session MAY pull-wait (`host-grok-build.md` Gap D); for `start_agent` the native messaging path; for the Cursor `Task` tool the backgrounded-task completion-notification path; for Claude Code `Agent` the backgrounded-agent completion-notification path; for OpenClaw `sessions_spawn` the host session completion / messaging channel (prefer `task pr:watch` inside the child when available). Front-load the first check to catch fast reviews.
|
|
730
738
|
3. ! When the exit condition is met (Greptile review current on the HEAD commit SHA, confidence meets resolved min (policy/dogfood/default; see Step 6 #3095), no P0/P1 remaining), the sub-agent reports completion back to the parent (via `send_message_to_agent`, the spawn_subagent result channel, or the OpenClaw sessions completion channel).
|
|
731
739
|
4. ! The main conversation pane stays fully interactive during monitoring -- the user (or parent monitor) can continue other work. On Grok Build this is conditional until a measured completion-notify exists: it holds when the parent returns the turn after background spawn, not when the parent pull-waits (`host-grok-build.md` Gap D / #4796).
|
|
@@ -1029,7 +1037,8 @@ task lifecycle:event -- emit plan:approved \
|
|
|
1029
1037
|
- ⊗ Workflow thrash or empty-commit spam during attributed platform outage without status-page probe (#3180)
|
|
1030
1038
|
- ⊗ Tight forge-outage retry / empty-commit thrash without a one-shot human report (#3422)
|
|
1031
1039
|
- ⊗ Merge or `--skip-ci` solely because a status page is red without check-run evidence (#3180)
|
|
1032
|
-
- ⊗
|
|
1040
|
+
- ⊗ Re-arm wait-mergeable or treat parseable blocking SLizard tip fingerprints as #3167 weather when Greptile Step 6 is clean (#5102 / #3167)
|
|
1041
|
+
- ⊗ Idle-poll / skip reading tip SLizard review body while open Previously mentioned fingerprints remain (#5102)
|
|
1033
1042
|
- ⊗ Silent admin / `--skip-ci` merge under Actions outage without audit comment and opt-in authority (#3167)
|
|
1034
1043
|
- ⊗ Leave a deliberate `stop-at: pr-open` (or thin-DONE recovery) open PR without spawning/retaining one review-cycle babysit owner + lease continuity and post-merge `scope:complete` plan (#3153)
|
|
1035
1044
|
- ⊗ Stand down at CLEAN under human-merge policy without a durable owner (sticky lease + live parent/monitor/Phase 6 closer) **and** a post-CLEAN observe path (poller / parent wake / Phase 6 re-poll) for post-merge `scope:complete` (#3153 / #1193 / #2321)
|
|
@@ -46,7 +46,17 @@ Probe order (must match engine `probeMonitoringTier` / `resolveDispatchProvider`
|
|
|
46
46
|
|
|
47
47
|
1. The canonical `templates/agent-prompt-preamble.md` content as the preamble (AGENTS.md read mandate, #810 xBRIEF gate, #798 PowerShell UTF-8, pre-PR + review-cycle mandates).
|
|
48
48
|
2. The standard worktree prompt (STEP 1-6 from the Prompt Template in `references/core-ops.md`).
|
|
49
|
-
3.
|
|
49
|
+
3. ! **Per-worktree story binding (#6233).** Claude Code sub-agents share the parent's hook environment, so a per-worker `DEFT_ACTIVE_SCOPE` pin is not possible. Use this in-session sequence:
|
|
50
|
+
1. The parent launches the cohort through `deft swarm:launch`, so dispatch PREP registers each worker worktree with its story in the worker-auth assignment record.
|
|
51
|
+
2. The parent starts the session ritual in each worker worktree (`deft session:start`, then `deft verify:session-ritual -- --tier=gated`).
|
|
52
|
+
3. The parent holds no `DEFT_ACTIVE_SCOPE` pin. A pin that names a different story than the worktree's assignment is refused.
|
|
53
|
+
4. The parent gives each sub-agent the absolute path of its worktree, and the sub-agent writes only inside it.
|
|
54
|
+
|
|
55
|
+
The write fence then reads the story for a registered linked worktree from its assignment record. A reader failure, or an assigned story that is missing, ineligible or ambiguous, refuses the write with the failure kind and one repair step. An unregistered linked worktree and the main worktree keep the earlier selection.
|
|
56
|
+
|
|
57
|
+
! **Fallback:** one headless Claude Code process per story, each with its own `DEFT_ACTIVE_SCOPE`, until the live two-story run in #6242 passes.
|
|
58
|
+
|
|
59
|
+
! **Guarantee and limits:** this is destination-scoped cooperative fencing. The trusted writer is dispatch PREP (`swarm:launch`). It is not worker isolation: a worker process can still change the record. Coverage is Write/Edit, plus recognized shell destination forms when that policy is set to `enforce`. Other shell writes are not covered.
|
|
50
60
|
4. ! **`run_in_background: true` (or host equivalent)** for any worker or poller whose loop runs longer than a short task (~3 min) — implementation, fix, and review-cycle workers — so the monitor conversation pane stays interactive (#1880 Gap D). The parent is notified on completion.
|
|
51
61
|
5. ! **Deliberate model routing (#1739):** resolve `(dispatch_provider=claude, worker_role)` via `task verify:routing` / `task swarm:routing-set` and pass `resolved_model` into the spawn when non-null — stamping the C2 manifest is prep; the recorded model MUST reach the actual spawn call.
|
|
52
62
|
|
|
@@ -92,14 +92,15 @@ Until a measured callback exists, Grok wording is conditional: background `spawn
|
|
|
92
92
|
|
|
93
93
|
! **Grok through-merge (#4529 / #4821 / #5219):** implement MUST use (b) `stop-at: pr-open`. Path (a) is for non-through-merge Grok leaves only. Named leftover (class A) requires a dest-cwd one-shot residual, stop-at after the push; then Approach 1 wait owner is a **`spawn_subagent` review-monitor sibling** whose `monitor_agent_id` is registered (`review-monitor:register --platform-primitive spawn_subagent`) and whose child-bound `pr:watch --monitor-agent-id <id>` satisfies `verify:review-monitor --merge-path-arm --live-wait`; then Phase 6 / parent-retained squash-merges via `pr:wait-mergeable-and-merge` only after CLEAN. Pass a declared wait budget when the envelope states one (#3984). Parent-retained is the **closer after CLEAN**, not the pre-CLEAN poller/fixer. Dest spawn deny is `BLOCKED` or dest-cwd residual via native implementation-capable spawn (#4215) — not parent-primary. ⊗ Send class-A residual through process-only CLI `grok --cwd`. ⊗ Choose Approach 1 sibling or parent-retained as the first partner without dest residual. ⊗ Dispatch a Grok through-merge implement as (a). ⊗ Harvest a Grok `drive-to: merge-ready` continuation as this closer. ⊗ Treat a parent-owned shell/`bash` `pr:watch` (heartbeat `parent_id=pr-watch`) as Approach 1 babysit when `spawn_subagent` is available (#5219).
|
|
94
94
|
|
|
95
|
-
! **Exclusive lawful waits / cheapest admitted Approach 1 (#5219 P3 / #5229 / #5727):** after `pr-open`, when Tier-1 `spawn_subagent` is available, the **only lawful** pre-CLEAN wait is Approach 1 child `pr:watch --monitor-agent-id` after `review-monitor:register --platform-primitive spawn_subagent` with `verify:review-monitor --merge-path-arm --live-wait` green; after CLEAN, parent-retained `pr:wait-mergeable-and-merge`. Approach 1 is also the **cheapest admitted** path vs parent shell `pr:watch`, host `monitor`, forge-poll, or bespoke `%TEMP%` pollers. Prefer one background `spawn_subagent` babysitter that owns watch → class A residual handoff → re-watch until CLEAN, then hand CLEAN to the parent closer. Child register + watch first (heartbeat live); parent verify after:
|
|
95
|
+
! **Exclusive lawful waits / cheapest admitted Approach 1 (#5219 P3 / #5229 / #5727 / #4781):** after `pr-open`, when Tier-1 `spawn_subagent` is available, the **only lawful** pre-CLEAN wait is Approach 1 child `pr:watch --monitor-agent-id` after `review-monitor:register --platform-primitive spawn_subagent` with `verify:review-monitor --merge-path-arm --live-wait` green; after CLEAN, parent-retained `pr:wait-mergeable-and-merge`. Approach 1 is also the **cheapest admitted** path vs parent shell `pr:watch`, host `monitor`, forge-poll, or bespoke `%TEMP%` pollers. Prefer one background `spawn_subagent` babysitter that owns watch → class A residual handoff → re-watch until CLEAN, then hand CLEAN to the parent closer. **Spawn shape before register/pr:watch (#4781):** for monitor-only seats (`stop-at: pr-open` + `worker_role: review-monitor` watch/report), pass advertised `process_only: true` with dest `cwd` (`formatApproach1ProcessOnlySpawnShape` / `approach1BabysitterCommands`). Implement-class never sets `process_only`; dest-path is not the skip class; do not blanket-flag the fix-capable greptile poller. Dest convention by write need: shared cwd-without-occupy for non-writing monitor/critic seats; one dest per validation seat that writes a report root. Specs/report writes stay on requirements posture (#4444) — do not fold report roots into the spawn skip class. Child register + watch first (heartbeat live); parent verify after:
|
|
96
96
|
```
|
|
97
|
+
# process_only+cwd spawn (monitor-only), then:
|
|
97
98
|
task review-monitor:register -- --pr <N> --monitor-agent-id <id> --platform-primitive spawn_subagent
|
|
98
99
|
DEFT_MONITOR_AGENT_ID=<id> task pr:watch -- <N> --monitor-agent-id <id>
|
|
99
100
|
# parent after child watch is live:
|
|
100
101
|
task verify:review-monitor -- --pr <N> --merge-path-arm --live-wait
|
|
101
102
|
```
|
|
102
|
-
Core helper: `formatApproach1BabysitterOneLiner` / `formatApproach1CheapestAdmissionCard` / `admitClaimedBabysitPath` (`packages/core/src/swarm/approach1-babysitter.ts`). Bounded-form deny: `evaluateBoundedPrWatchDeny` refuses Directive `pr:watch` / `task deft:pr:watch` without `--monitor-agent-id` when Tier 1 is provable. Claimed-wait deny: `evaluateClaimedBabysitPathDeny` / `admitClaimedBabysitPath` refuse `BabysitPathKind` forge-poll / bespoke-temp-poller / host-monitor / directive-pr-watch-bare and Approach 1 without bound evidence / different-PR arm. ⊗ Parent forge-poll / `gh` check-runs+mergeable_state sleep / bespoke `%TEMP%` PowerShell watchers as pre-CLEAN babysit (#5727). ⊗ Parent-shell `pr:watch --monitor-agent-id <leased id>` without spawn-injected `DEFT_MONITOR_AGENT_ID` (or CLI matching `GROK_SESSION_ID`) — that impersonation does not arm. ⊗ Start `pr:wait-mergeable-and-merge` before CLEAN (#4822). ⊗ Treat host `monitor` or bare shell `pr:watch` as the sole babysit when `spawn_subagent` is available (#5229).
|
|
103
|
+
Core helper: `formatApproach1BabysitterOneLiner` / `formatApproach1CheapestAdmissionCard` / `formatApproach1ProcessOnlySpawnShape` / `admitClaimedBabysitPath` (`packages/core/src/swarm/approach1-babysitter.ts`). Bounded-form deny: `evaluateBoundedPrWatchDeny` refuses Directive `pr:watch` / `task deft:pr:watch` without `--monitor-agent-id` when Tier 1 is provable. Claimed-wait deny: `evaluateClaimedBabysitPathDeny` / `admitClaimedBabysitPath` refuse `BabysitPathKind` forge-poll / bespoke-temp-poller / host-monitor / directive-pr-watch-bare and Approach 1 without bound evidence / different-PR arm. ⊗ Parent forge-poll / `gh` check-runs+mergeable_state sleep / bespoke `%TEMP%` PowerShell watchers as pre-CLEAN babysit (#5727). ⊗ Parent-shell `pr:watch --monitor-agent-id <leased id>` without spawn-injected `DEFT_MONITOR_AGENT_ID` (or CLI matching `GROK_SESSION_ID`) — that impersonation does not arm. ⊗ Start `pr:wait-mergeable-and-merge` before CLEAN (#4822). ⊗ Treat host `monitor` or bare shell `pr:watch` as the sole babysit when `spawn_subagent` is available (#5229).
|
|
103
104
|
|
|
104
105
|
! **Durable host→CLI capability stamp (#5229):** Before any CLI `verify:review-monitor` / `pr:watch` subprocess, write `.deft-scratch/host-capability-stamp.json` via `writeHostCapabilityStamp(projectRoot)` / `ensureHostCapabilityStampForBabysit` (and prefer exporting `GROK_BUILD=1` / `DEFT_HAS_SPAWN_SUBAGENT=1` into that subprocess). `review-monitor:register` also writes the stamp on successful claim/renew. Stamps older than 8h or bound to a different `host_session_id` are ignored so a later plain-terminal session cannot inherit Tier 1. Without a fresh stamp, bare `node … verify:review-monitor` can mis-detect Tier 3 / `generic-terminal` and fail-open with "no active review-monitor required" even though this parent owns `spawn_subagent`. `probeMonitoringTier` merges the stamp; `DEFT_MONITOR_TIER=3` is labeled `override-tier3` (not honest `generic-terminal`) and refused when stamp/env already proves Tier 1. `evaluateReviewMonitorGate` consults sticky lease `platform_primitive` before Approach 3 READY and before `!isTier1` READY. Bounded `pr:watch` without `--monitor-agent-id` is refused at the watch entry when Tier 1 is provable.
|
|
105
106
|
|
|
@@ -816,7 +816,9 @@ tasks:
|
|
|
816
816
|
cmds:
|
|
817
817
|
- task: engine:invoke
|
|
818
818
|
vars:
|
|
819
|
-
|
|
819
|
+
# #5805 / #5942: the pin's default project root is its own package dir, so pass the
|
|
820
|
+
# operator root explicitly (an operator --project-root in CLI_ARGS still wins).
|
|
821
|
+
ENGINE_CMD: 'release-publish --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
|
|
820
822
|
|
|
821
823
|
release:rollback:
|
|
822
824
|
desc: "State-aware release unwind (#716) -- task release:rollback -- <version> [--dry-run] [--allow-low-downloads N] [--allow-data-loss] [--force-strict-0]"
|
|
@@ -825,7 +827,9 @@ tasks:
|
|
|
825
827
|
cmds:
|
|
826
828
|
- task: engine:invoke
|
|
827
829
|
vars:
|
|
828
|
-
|
|
830
|
+
# #5805 / #5942: the pin's default project root is its own package dir, so pass the
|
|
831
|
+
# operator root explicitly (an operator --project-root in CLI_ARGS still wins).
|
|
832
|
+
ENGINE_CMD: 'release-rollback --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
|
|
829
833
|
|
|
830
834
|
release:e2e:
|
|
831
835
|
desc: "End-to-end release rehearsal against an auto-created temp repo (#716, #2572 keep+report default) -- task release:e2e [-- --dry-run] [--owner OWNER] [--destroy-repo]"
|
|
@@ -834,7 +838,9 @@ tasks:
|
|
|
834
838
|
cmds:
|
|
835
839
|
- task: engine:invoke
|
|
836
840
|
vars:
|
|
837
|
-
|
|
841
|
+
# #5805 / #5942: the pin's default project root is its own package dir, so pass the
|
|
842
|
+
# operator root explicitly (an operator --project-root in CLI_ARGS still wins).
|
|
843
|
+
ENGINE_CMD: 'release-e2e --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
|
|
838
844
|
|
|
839
845
|
release:wait-npm:
|
|
840
846
|
desc: "Phase 7 wait until both public OVPR packages (@deftai/directive + @deftai/directive-runtime) list the cut version (#4267 / #5490) -- task release:wait-npm -- <version>"
|
|
@@ -945,10 +951,10 @@ tasks:
|
|
|
945
951
|
;;
|
|
946
952
|
esac
|
|
947
953
|
print_deposit_recovery() {
|
|
948
|
-
echo "Phase 7 local closeout INCOMPLETE (#5953)." >&2
|
|
949
|
-
echo "Recovery:
|
|
954
|
+
echo "Phase 7 local closeout INCOMPLETE (#5953 / #6163 Prefer-A Bound 6772886751)." >&2
|
|
955
|
+
echo "Recovery: on the pin candidate, repair/write agent-hook deposit then force-add tip-required Cursor paths (.cursor/hooks.json + .cursor/hooks/deft-hook-<sha8>.mjs) so they co-travel with the pin (preparePinCandidateCursorDeposit / git add -f bounded set); merge that pin+deposit tip, then re-run:" >&2
|
|
950
956
|
echo " task release:local-update -- $VERSION --checkout $CHECKOUT" >&2
|
|
951
|
-
echo "Expected managed deposit paths include: .grok/hooks/ .cursor/hooks.json .claude/settings.json .codex/ (and related deposit files)." >&2
|
|
957
|
+
echo "Expected managed deposit paths include: .grok/hooks/ .cursor/hooks.json .cursor/hooks/deft-hook-<sha8>.mjs .claude/settings.json .codex/ (and related deposit files)." >&2
|
|
952
958
|
echo "Do not auto-commit deposit bytes inside the release flow; do not npm i -g." >&2
|
|
953
959
|
}
|
|
954
960
|
OCC_FILE="$CHECKOUT/.deft/occupancy.json"
|
|
@@ -1015,8 +1021,16 @@ tasks:
|
|
|
1015
1021
|
git status --short >&2
|
|
1016
1022
|
exit 1
|
|
1017
1023
|
fi
|
|
1018
|
-
|
|
1019
|
-
|
|
1024
|
+
# #6164: shell parameter expansion strip (zero sed/awk/cut/grep); then git verify.
|
|
1025
|
+
ORIGIN_HEAD="$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null || true)"
|
|
1026
|
+
DEFAULT_BRANCH="${ORIGIN_HEAD#refs/remotes/origin/}"
|
|
1027
|
+
if [ -z "$DEFAULT_BRANCH" ] || [ "$DEFAULT_BRANCH" = "$ORIGIN_HEAD" ]; then
|
|
1028
|
+
DEFAULT_BRANCH=master
|
|
1029
|
+
fi
|
|
1030
|
+
if ! git rev-parse --verify --quiet "refs/remotes/origin/$DEFAULT_BRANCH" >/dev/null; then
|
|
1031
|
+
echo "release:local-update: refuse; cannot verify refs/remotes/origin/$DEFAULT_BRANCH; run: git remote set-head origin -a" >&2
|
|
1032
|
+
exit 1
|
|
1033
|
+
fi
|
|
1020
1034
|
CURRENT="$(git rev-parse --abbrev-ref HEAD)"
|
|
1021
1035
|
if [ "$CURRENT" != "$DEFAULT_BRANCH" ]; then
|
|
1022
1036
|
echo "release:local-update: refuse; checkout must be on default branch $DEFAULT_BRANCH (on $CURRENT)" >&2
|
|
@@ -1024,14 +1038,54 @@ tasks:
|
|
|
1024
1038
|
fi
|
|
1025
1039
|
echo "release:local-update: ff-only pull on $DEFAULT_BRANCH at $CHECKOUT"
|
|
1026
1040
|
git pull --ff-only
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1041
|
+
# #6164: unconditional dependency-free AgeExclude gate (exact list-item; fail closed; no soft-skip).
|
|
1042
|
+
node -e '
|
|
1043
|
+
const fs = require("fs");
|
|
1044
|
+
const version = process.argv[1] || "";
|
|
1045
|
+
const want = "@deftai/directive-runtime@" + version;
|
|
1046
|
+
let text;
|
|
1047
|
+
try {
|
|
1048
|
+
text = fs.readFileSync("pnpm-workspace.yaml", "utf8");
|
|
1049
|
+
} catch (err) {
|
|
1050
|
+
const detail = err && err.message ? err.message : String(err);
|
|
1051
|
+
console.error("release:local-update: AgeExclude cannot read pnpm-workspace.yaml before frozen install (#6164): " + detail);
|
|
1052
|
+
process.exit(1);
|
|
1053
|
+
}
|
|
1054
|
+
const lines = text.split(/\r?\n/);
|
|
1055
|
+
const KEY_RE = /^(\s*)minimumReleaseAgeExclude:\s*(#.*)?$/;
|
|
1056
|
+
const ITEM_RE = /^(\s*)-\s+(.*)$/;
|
|
1057
|
+
const keyIdx = lines.findIndex((l) => KEY_RE.test(l));
|
|
1058
|
+
if (keyIdx < 0) process.exit(0);
|
|
1059
|
+
const keyLine = lines[keyIdx];
|
|
1060
|
+
const keyIndent = keyLine.length - keyLine.trimStart().length;
|
|
1061
|
+
const itemValue = (raw) => {
|
|
1062
|
+
let v = String(raw || "").trim();
|
|
1063
|
+
const SQ = String.fromCharCode(39);
|
|
1064
|
+
const DQ = String.fromCharCode(34);
|
|
1065
|
+
if (v.startsWith(SQ) || v.startsWith(DQ)) {
|
|
1066
|
+
const q = v[0];
|
|
1067
|
+
const end = v.indexOf(q, 1);
|
|
1068
|
+
return end > 0 ? v.slice(1, end) : v;
|
|
1069
|
+
}
|
|
1070
|
+
const hash = v.search(/\s#/);
|
|
1071
|
+
if (hash >= 0) v = v.slice(0, hash);
|
|
1072
|
+
return v.trim();
|
|
1073
|
+
};
|
|
1074
|
+
let found = false;
|
|
1075
|
+
for (let i = keyIdx + 1; i < lines.length; i++) {
|
|
1076
|
+
const line = lines[i];
|
|
1077
|
+
const trimmed = line.trim();
|
|
1078
|
+
if (trimmed === "" || trimmed.startsWith("#")) continue;
|
|
1079
|
+
const m = ITEM_RE.exec(line);
|
|
1080
|
+
const indent = line.length - line.trimStart().length;
|
|
1081
|
+
if (m === null || indent < keyIndent) break;
|
|
1082
|
+
if (itemValue(m[2]) === want) { found = true; break; }
|
|
1083
|
+
}
|
|
1084
|
+
if (!found) {
|
|
1085
|
+
console.error("release:local-update: AgeExclude missing " + want + " before frozen install (#5953 footnote / #6164)");
|
|
1086
|
+
process.exit(1);
|
|
1087
|
+
}
|
|
1088
|
+
' "$VERSION"
|
|
1035
1089
|
echo "release:local-update: pnpm install --frozen-lockfile"
|
|
1036
1090
|
pnpm install --frozen-lockfile
|
|
1037
1091
|
PIN_PKG="$(node -e 'const fs=require("fs"); const p=JSON.parse(fs.readFileSync("package.json","utf8")); const v=(p.dependencies||{})["@deftai/directive-runtime"]||(p.devDependencies||{})["@deftai/directive-runtime"]||""; console.log(String(v).replace(/^[^0-9]*/, ""));')"
|
|
@@ -1051,6 +1105,39 @@ tasks:
|
|
|
1051
1105
|
print_deposit_recovery
|
|
1052
1106
|
exit 1
|
|
1053
1107
|
fi
|
|
1108
|
+
# #6163 Prefer-A Bound 6772886751: committed-byte HEAD association (no repair/staging).
|
|
1109
|
+
echo "release:local-update: require committed Cursor deposit association on HEAD"
|
|
1110
|
+
if ! node --input-type=module -e '
|
|
1111
|
+
import { pathToFileURL } from "node:url";
|
|
1112
|
+
import { join, resolve } from "node:path";
|
|
1113
|
+
const checkout = process.argv[1];
|
|
1114
|
+
const vendor = join(
|
|
1115
|
+
checkout,
|
|
1116
|
+
"node_modules/@deftai/directive-runtime/vendor/directive-core/dist/init-deposit/agent-hooks.js",
|
|
1117
|
+
);
|
|
1118
|
+
let validate;
|
|
1119
|
+
try {
|
|
1120
|
+
({ validateCursorDepositAssociation: validate } = await import(pathToFileURL(resolve(vendor)).href));
|
|
1121
|
+
} catch (err) {
|
|
1122
|
+
const detail = err && err.message ? err.message : String(err);
|
|
1123
|
+
console.error("release:local-update: cannot load validateCursorDepositAssociation from installed runtime (#6163): " + detail);
|
|
1124
|
+
process.exit(1);
|
|
1125
|
+
}
|
|
1126
|
+
if (typeof validate !== "function") {
|
|
1127
|
+
console.error("release:local-update: installed runtime lacks validateCursorDepositAssociation (#6163); pin must co-travel the Bound helper");
|
|
1128
|
+
process.exit(1);
|
|
1129
|
+
}
|
|
1130
|
+
const result = validate(checkout, { source: "HEAD" });
|
|
1131
|
+
if (!result || result.ok !== true) {
|
|
1132
|
+
console.error("release:local-update: committed Cursor deposit association FAILED on HEAD (#6163)");
|
|
1133
|
+
console.error(result && result.detail ? result.detail : "unknown association failure");
|
|
1134
|
+
process.exit(1);
|
|
1135
|
+
}
|
|
1136
|
+
console.log("release:local-update: committed Cursor deposit association ok (" + result.sha8 + ")");
|
|
1137
|
+
' "$CHECKOUT"; then
|
|
1138
|
+
print_deposit_recovery
|
|
1139
|
+
exit 1
|
|
1140
|
+
fi
|
|
1054
1141
|
UPGRADE_BIN=""
|
|
1055
1142
|
if [ -x "node_modules/.bin/directive" ]; then
|
|
1056
1143
|
UPGRADE_BIN="node_modules/.bin/directive"
|
|
@@ -149,6 +149,8 @@ Common commands:
|
|
|
149
149
|
- Bare `evidence` / `disposition` keys are **not** valid (#1620 / Option B #3305). They fail `verify:vbrief-conformance` and are treated as missing by `scope:complete` (no dual-read). Migrate bare keys or narrative-only `Result`/`Verification` workarounds to the namespaced fields above while items are still non-terminal.
|
|
150
150
|
- Already-terminal items (`completed`/`failed`/`cancelled`/…) are not re-checked for typed evidence; pre-marking items complete to skip the gate is unsupported for the typed path.
|
|
151
151
|
- `merge`/`review` alone cannot satisfy smoke/UAT/deploy/observed_behavior criteria (title/Acceptance text or explicit axis).
|
|
152
|
+
- **Delivery identity (#5710):** with an issue origin, the PR must be associated with the issue as of `merged_at` by one of: (a) a unique sole `deft-story: N` mark in the merge-time PR body (PRs that change only lifecycle briefs, `CHANGELOG.md` and the spec-drift ledger are excluded and never count), (b) a closing keyword (`Closes #N`, `owner/repo#N`, or the issue URL) in the merge-time body, or (c) a Connected issue link at `merged_at`. Brief-in-PR-diff still counts. A mark, keyword or link added after merge does not count, and current `closingIssuesReferences` alone is not enough. Basis (a) scans every merged PR within 20 minutes, `graphql.remaining` ≥ 200 and REST core ≥ 100; any gap refuses. With no issue origin, stamp `plan.metadata.productPullRequest` and complete with `--pr <that number> --merge-commit <sha>`; the repository is the `origin` remote. `--non-delivery` refuses when the stamped PR is merged, and refuses when its merge state cannot be read. `xbrief:preflight` prints one note for a code-bearing brief with no issue origin.
|
|
153
|
+
- **Lifecycle completion (#680):** completion admission uses the merge-time bases above; there is no separate keyword-only refuse. `swarm:finalize-owed` also lists an active issue-less brief with a stamped `productPullRequest` (shown as `pr #P`, no issue number, no origin-issue check or origin-close); briefs that share a product PR finalize together under one claim. In a batched `swarm:finalize-cohort`, a refused `deft-story` mark is not an error: that story stays pending, unstamped and unswept (`refused_marks`, exit 3 incomplete), and the other stories stamp, sweep, commit and land. A failed changed-file lookup and real delivery errors still fail the batch. `scope:complete` writes the spec-drift ledger as verb output; finalize commits it with the completed briefs, and scope-provenance membership admits exactly `xbrief/.audit/spec-drift-ledger.json` only when the whole change set is a completion move. `verify:changelog-unreleased` needs no new `[Unreleased]` line when the change set versus merge-base (`git diff --name-only --no-renames`) is non-empty and only lifecycle briefs, `CHANGELOG.md` and that ledger, so lifecycle verbs write no CHANGELOG line. Product changes and an empty change set still need one.
|
|
152
154
|
- `task scope:fail -- xbrief/active/<file>.xbrief.json` -- mark running work failed when the scope cannot complete.
|
|
153
155
|
- `task scope:cancel -- <path>` -- move a scope to `cancelled/`.
|
|
154
156
|
- `task scope:restore`, `task scope:block`, `task scope:unblock`, `task scope:demote`, and `task scope:undo:*` -- repair or reverse lifecycle transitions.
|
|
@@ -181,6 +183,8 @@ The implementation gate succeeds only for active scope xBRIEFs with `plan.status
|
|
|
181
183
|
|
|
182
184
|
**Hotfix classifier (#1193):** Typed `plan.policy.hotfixCriteria` + pure `evaluateHotfixEligibility`. Small fix / pure revert may propose label `hotfix-candidate` only; a human promotes to `hotfix`. Refactors, new exports/handlers, and forbidden paths (Dockerfile, fly.toml, workflows, migrations, auth/secrets) never qualify.
|
|
183
185
|
|
|
186
|
+
**Small-change lane (#6204):** Under the `rapid` ceremony dial, a scope with stated acceptance commands may use a thin brief: title, issue ref, `file_scope` and acceptance commands only (`emitThinBrief`, `packages/core/src/intake/thin-brief.ts`). The bound defaults to 5 production files and 500 changed lines (added plus deleted, tests included; briefs and CHANGELOG excluded). `plan.policy.ceremonyDial.smallChangeLane` (`maxProductionFiles`, `maxChangedLines`) overrides each field; an invalid value refuses. `scope:promote`, `scope:activate`, `xbrief:preflight`, `verify:ac` and `scope:complete` admit the thin shape, and each one remeasures the cumulative product diff (git, against the lane-admit base in `plan.metadata["x-directive/smallChangeLane"]`; at `scope:complete`, the delivered merge commit against its first parent). A crossed bound, a public-surface change (manifest, entry, task file or export line), an unknown public surface, or a depth other than `rapid` refuses. A crossed bound or public-surface change is recorded on the brief (lane state `crossed`), so every later retry refuses even if the diff shrinks. The public-surface check reads export statements with the TypeScript parser, so a change inside a multi-line export list or exported signature counts. The one remediation is lane exit: convert the scope to the full shape (`escalateThinBriefToFullShape`), which keeps scope identity and acceptance evidence. Raising the dial (#3319) does not clear the refusal. One-PR delivery is not part of this lane; Path B brief-first stays lawful (#6203 / #680).
|
|
187
|
+
|
|
184
188
|
```mermaid
|
|
185
189
|
flowchart TD
|
|
186
190
|
Candidate["Scope xBRIEF exists"] --> Promote{"In proposed?"}
|
|
@@ -494,13 +498,14 @@ Cross-link: spawn three postures and deny recoveries live under § Agent-host di
|
|
|
494
498
|
### Mutable ritual (mutation posture)
|
|
495
499
|
|
|
496
500
|
- ! On **mutation** session start, run `deft session:start` (or `task session:start` in framework source) after loading AGENTS.md. Records quick-tier ritual in `.deft/ritual-state.json`: alignment confirmation, branch-policy disclosure, `deft verify:tools` guidance, default-branch sync warnings, and `deft triage:welcome` one-liner. State is worktree- and HEAD-bound; stale after `plan.policy.sessionRitualStalenessHours` hours (default 8). Mutation start also claims the worktree occupancy lease (`.deft/occupancy.json`); see Session routing (#3433).
|
|
497
|
-
- ! **
|
|
501
|
+
- ! **Quiet-default success stdout (#4966):** mutation `session:start` success human output defaults to one trusted go-signal line with stable prefix `[deft session] ready=…` (ready + branch/HEAD + occupancy). Routine dial/host-surface/effort/orientation/ceremony prose is verbose-only via `deft session:start --verbose` or `DEFT_SESSION_VERBOSE=1`. Non-exhaustive always-on allowlist keeps actionable zero-exit exceptions, non-default policy/bypass and human-merge disclosures, finalize-owed unknown/deferred qualifications, and actionable lifecycle/work-claim notices on the quiet path. Fail/deny/steal/non-zero stay loud. Tip `#3286` `--compact` / `DEFT_SESSION_COMPACT` are deprecated as whole-stdout volume controls (no-op for human stdout selection; `--json` / run-summary unchanged). Exit 0 is not the mutation go-signal — render from structured ready/posture/occupancy state.
|
|
502
|
+
- ! **Orientation compression Now (#3286):** mutation cold `session:start` composes `doctor` + #3282 toolchain preflight (and deposit-sha fast-paths for `agents:refresh` / `verify:cache-fresh`) as inline sections with per-section status lines — composition of existing steps, not a new monolith. When the deposit fingerprint (payload + templates + engine) is unchanged, refresh surfaces print one-line `unchanged - sha match` no-ops. Section formatting may still honor `--compact` / `DEFT_SESSION_COMPACT=1` inside the orientation bundle; whole-stdout volume is `#4966` quiet-default / `--verbose`. #2176 read-only default is unchanged. Dual-path Later (orient) stays open until run-summary telemetry shows ritual+gate share ≥ 25% after Now ships (#2899).
|
|
498
503
|
- ! Cold `session:start` does **not** run the live agent-hook probe. Functional readiness belongs to the gated mutation path so cold ceremony retains the #2990/#2991 latency profile.
|
|
499
504
|
- ! **Hot path latency (#2991):** by default, mutation `session:start` does **not** block ritual-state write on optional network. It skips the npm release-availability probe and triage cache empty-hydrate / self-heal (`ensureTriageCacheHydrated` / `maybeSelfHealCache`). Targets (operator-facing, not CI-hard): warm hot path typically under a few seconds once tools are on PATH; cold path dominated by local `verify:tools` and git, usually well under ~30s when optional network is off. Empty-cache GitHub fetch-all and npm `view` previously accounted for multi-minute hangs in the WWYSYDH pilot — those stay off the critical path unless opted in.
|
|
500
505
|
- ! **Cold vs re-arm ceremony tiers (#2992):** default `session:start` is the **cold** (full) path. After age staleness or compact re-arm (#2113) on the **same worktree** with continuous HEAD and previously-passing quick steps, prefer `deft session:start --rearm` (alias `--tier=rearm`) to refresh the ritual clock + HEAD/worktree bind without `verify:tools`, triage welcome, release probe, or staleness tickler. Full cold remains required for missing/invalid state, worktree change, discontinuous HEAD, first install, or failed/missing quick steps. Compact marks `rearm_needed`; PreToolUse denial and inspect/verify messages prefer re-arm recovery when cold is unnecessary.
|
|
501
506
|
- ? Opt into optional network: `deft session:start --with-network` or `DEFT_SESSION_START_NETWORK=1`. When enabled, the bounded release-availability probe runs against the public npm registry (skips framework source checkouts, non-release pins, and `DEFT_NO_NETWORK=1`; identical latest-version notices throttle for 24 hours in `xbrief/.triage-cache/release-availability-state.json`). Default-mode triage welcome then also hydrates/self-heals the triage cache. This is separate from `deft doctor`, whose bare and gated invocations remain offline by default (#2182). Refs #1692 / #2991. Re-arm never runs optional network.
|
|
502
507
|
- ~ `session:start --json` includes `steps[]` with `name` + `duration_ms` for major phases (`alignment`, `branch_policy`, `verify_tools`, `triage_welcome`, `release_probe`, `ritual_write`), plus total `duration_ms`, `optional_network`, and `ceremony_tier` (`cold` | `rearm`). Skipped optional steps report `skipped: true` and `duration_ms: 0`. Use this for attribution when investigating ceremony wall-clock.
|
|
503
|
-
- ~ **Process-cost events (#2994 / #3508):** on mutation `session:start` completion (cold or re-arm), Directive appends a local `session:start` behavioral event to `.deft-cache/events.jsonl` with `ceremony_tier`, `duration_ms`, `exit_code`, and optional `steps[]` (same labels as `--json`). Mutation `session:start` also
|
|
508
|
+
- ~ **Process-cost events (#2994 / #3508):** on mutation `session:start` completion (cold or re-arm), Directive appends a local `session:start` behavioral event to `.deft-cache/events.jsonl` with `ceremony_tier`, `duration_ms`, `exit_code`, and optional `steps[]` (same labels as `--json`). Mutation `session:start` also emits one operator-visible `ceremony <tier> <ms>` line on the verbose human path (`--verbose` / `DEFT_SESSION_VERBOSE`; quiet-default hides it per #4966). When PreToolUse denies for `ritual-not-ready`, a local `session:ritual-blocked` event records `tool_name`, `code`, and optional `recovery_tier` / `detail`. Always-on best-effort (never blocks ceremony or deny path); not gated on `valueFeedback`; **no remote upload** (Product Insights #2603 is a separate opt-in). Pull the rollup with `task value:show` (composed reader; CLI process time, not agent-turn wall clock). See § Process-cost events below. ⊗ Do not use the printed CLI duration as #3286 Later graduation input.
|
|
504
509
|
- ~ At safe idle points (clean tree, no in-flight story), mutation session start and `deft scope:complete` may also run the staleness tickler: an interactive, consent-based offer to upgrade Directive (`npm i -g @deftai/directive@latest`) and/or migrate xBRIEF (`deft migrate:xbrief`). Escalation tiers, snooze windows, and opt-out live under `plan.policy.stalenessTickler` — inspect with `deft policy:show --field=stalenessTickler`. State persists in `xbrief/.triage-cache/staleness-tickler-state.json`. Skips framework source checkouts, dirty trees, CI/headless (`DEFT_SESSION_RITUAL_SKIP=1`), and typed opt-out. Refs #2488 / #2489.
|
|
505
510
|
- ! Before any code-writing tool call or `start_agent` implementation dispatch, run `deft verify:session-ritual -- --tier=gated`. Gated tier fails closed unless quick-tier state is fresh; lazily records the non-deferrable `agent_hooks` readiness gate plus `deft doctor` and `task verify:cache-fresh` entrypoints. Agent-hook correctness is independent of doctor warnings and throttling. Step 0 of the pre-`start_agent` gate stack.
|
|
506
511
|
- ! **One-shot recovery (#2993 / #3100 / #4399):** when PreToolUse denies writes for a stale/missing gated ritual, run `deft session:ready` (or `task session:ready`). It composes `session:start` (only when quick-tier is not green) + `verify:session-ritual -- --tier=gated` with check-class `cache_fresh` (age + live drift, no `--skip-drift-probe`) + `cache fetch-all --force` when `cache_fresh` is the remaining blocker, then re-verifies. Skip-drift ritual argv is not the ready bar — that is the `task check` / FRAMEWORK_CHECK_GATES evaluate, so stale-by-drift can still fire fetch-all. Even when gated inspect is already fresh, the fast path forces one live `agent_hooks` check and the same check-class `cache_fresh`; it still avoids unnecessary fetch-all when that evaluate is green. Flags: `--json`, `--repo OWNER/NAME`, `--with-network` (forwarded to session:start). Prefer this over juggling the multi-step recovery sequence under hook pressure.
|
|
@@ -550,7 +555,7 @@ Local ceremony cost signal for WWYSYDH / weekly process rollups. Emits to `.deft
|
|
|
550
555
|
| PreToolUse ritual deny | `session:ritual-blocked` | Hook blocks write/spawn because gated ritual is not ready | `tool_name`, `code=ritual-not-ready`, `recovery_tier` (`cold`\|`rearm`) |
|
|
551
556
|
| Per-step wall-clock | (field on `session:start`) | Same emit as session start | `steps[].name` + `steps[].duration_ms` (`alignment`, `scm_readiness`, `branch_policy`, `verify_tools`, `triage_welcome`, `release_probe`, `ritual_write`) |
|
|
552
557
|
|
|
553
|
-
CLI mirror (no JSONL required): `deft session:start --json` already exposes the same `steps` / `duration_ms` / `ceremony_tier` fields for one-shot inspection. Human mutation output adds one `ceremony <tier> <ms>` line
|
|
558
|
+
CLI mirror (no JSONL required): `deft session:start --json` already exposes the same `steps` / `duration_ms` / `ceremony_tier` fields for one-shot inspection. Human mutation output adds one `ceremony <tier> <ms>` line on the verbose path (#3508 / #4966).
|
|
554
559
|
|
|
555
560
|
Composed reader (no new verb): `task value:show` / `deft value:show` prints last cold vs re-arm duration, last per-step breakdown, blocked-ritual count, and recovery-tier distribution from the same ledger. This is **CLI process time**, not agent-turn wall clock (#3500). ⊗ Do not feed the printed CLI duration into #3286 Later graduation.
|
|
556
561
|
|
|
@@ -58,6 +58,8 @@ directive doctor
|
|
|
58
58
|
|
|
59
59
|
After clone or a new worktree: run the project package manager (`npm install` / `pnpm install`), then the first eligible runtime command or registered hook completes local activation.
|
|
60
60
|
|
|
61
|
+
**Dependabot / pin-only bumps (AC14.10):** a PR that changes only the `@deftai/directive-runtime` pin + lockfile is valid. After `pnpm install` / `npm install` brings `node_modules` to the new pin, the first eligible skill, hook, or ordinary runtime command runs local automatic setup (wiring / `GENERATION` / readiness). `directive doctor` stays read-only — dirty doctor output before that eligible invocation is expected. CI may either rely on that first eligible command or run explicit `directive install --repair --yes`. Do not treat "deposit bytes must land in the same pin PR" as product law. Human-test mirror: HT-17 in `docs/installer-refactor-ovpr/install-ovpr-human-test-plan.md`. Schema/data behind the new pin still needs `directive upgrade` (AC14.11), not repair alone.
|
|
62
|
+
|
|
61
63
|
**Repair (pin unchanged):** `npm i -g @deftai/directive`, then `directive install --repair`.
|
|
62
64
|
|
|
63
65
|
**Upgrade version or migrate data:** `directive upgrade` (alias: `update`).
|
|
@@ -45,10 +45,24 @@ Allowance = clamp(count of **concrete** production files on the merge-base `file
|
|
|
45
45
|
When the bound story is in the change set:
|
|
46
46
|
|
|
47
47
|
1. A human-stamped merge-base mint for the **continuity-resolved** story is the allowlist when present (planId match ignores stale `xbriefRelPath`; no-`plan.id` is path-first + basename-keyed mint with matching `xbriefRelPath`).
|
|
48
|
-
2. Otherwise membership evaluates against the merge-base brief's **concrete** `file_scope` as agent precommitment. Head brief cannot widen.
|
|
48
|
+
2. Otherwise membership evaluates against the merge-base brief's **concrete** `file_scope` as agent precommitment. Head brief cannot widen, except under a qualifying forge approval (#6203, below).
|
|
49
49
|
3. Free paths: bound brief, verified peer briefs, `CHANGELOG.md`, and continuity lifecycle paths of the bound identity. An xBRIEF-only change set may omit a mint.
|
|
50
50
|
4. Empty / invalid / unreadable mint records fail closed (they are not absence).
|
|
51
51
|
|
|
52
|
+
#### Forge-approved head brief (#6203)
|
|
53
|
+
|
|
54
|
+
A PR can carry a new or widened brief plus its code when a human approves it on GitHub. With PR context (`--pr N` / `--repo OWNER/NAME`, or `GITHUB_PR_NUMBER` / `GITHUB_REPOSITORY` in CI), a failing membership check under precommitment or missing authority consults the forge. When a qualifying approval exists, membership evaluates against the **head** brief's concrete `file_scope` instead of the merge-base brief.
|
|
55
|
+
|
|
56
|
+
- **Mint wins.** A present mint keeps the mint path. The forge is never consulted.
|
|
57
|
+
- **Auth-hash v1** (`sha256:` over canonical JSON; strings byte-exact, no Unicode normalization) covers `plan.id`, the xbrief path, the concrete `file_scope`, and the acceptanceCriteria array: `plan.acceptance`, `plan.narratives.AcceptanceCriteria`, and each item's `narrative.Acceptance`, in document order. `productPullRequest` and other delivery metadata stay out, so a PPR stamp keeps the approval. Any change to the covered fields drops it.
|
|
58
|
+
- **Qualifying approval:** the reviewer's latest deciding review (APPROVED / CHANGES_REQUESTED / DISMISSED) is APPROVED; the reviewer is a `User` (not Bot or App), not the PR author, and has `write`, `maintain` or `admin` on the repo; the repo is the checkout's `origin` (a `--repo` value may only confirm it, so a fork's approval never counts) and is the PR's base repo; the evaluated HEAD is the PR head (or GitHub's merge commit whose second parent is the PR head); and the brief at the reviewed commit hashes the same as the head brief.
|
|
59
|
+
- **Fallback:** missing PR context, no qualifying approval, a hash mismatch, or an unavailable forge keeps today's Path B or mint finding unchanged. The result message adds one `forge approval (#6203)` line with the reason.
|
|
60
|
+
- **Membership only.** The production fence still reads the merge-base brief. A widened brief can pass membership and still fail `production-scope-over-budget`. A brand-new brief has no production fence (as today).
|
|
61
|
+
- **Re-run after approval.** Approval does not re-trigger CI. Re-run the merge gate (or push) after the approval lands.
|
|
62
|
+
- **Residual (#6207):** an agent that holds a second human forge token can satisfy every predicate above. The hash binds the approved bytes; it does not prove independent human intent and does not close that confused-deputy risk. That posture stays open on #6207.
|
|
63
|
+
|
|
64
|
+
Code: `packages/core/src/scope-provenance/forge-approval.ts`.
|
|
65
|
+
|
|
52
66
|
#### Path A planning split (#5551)
|
|
53
67
|
|
|
54
68
|
When an active implementation brief is **outside** the change set, membership is a no-op for that identity (Path A). Supported planning publication is two change sets, not one:
|