@deftai/directive-content 0.94.0 → 0.95.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.
@@ -1,9 +1,10 @@
1
1
  ---
2
2
  name: deft-directive-sync
3
3
  description: >-
4
- Session-start framework sync skill. Pulls latest deft submodule,
5
- validates vBRIEF lifecycle structure, checks folder/status consistency,
6
- detects stale origins (RFC D12), and summarizes changes.
4
+ Session-start framework sync and upgrade handoff. Refreshes deposit via npm
5
+ + directive/deft update, validates xBRIEF lifecycle, detects stale origins
6
+ (RFC D12), and finishes SCM release handoff in released | pr-open |
7
+ blocked:<reason> (#1604).
7
8
  ---
8
9
 
9
10
  Read and follow: skills/deft-directive-sync/SKILL.md
package/QUICK-START.md CHANGED
@@ -164,7 +164,7 @@ Read and follow `../AGENTS.md`. This starts the normal first-session flow (user
164
164
  After a Deft project is set up, the CLI runs a periodic, read-only remote-version probe (issue #801) so you find out when the upstream framework ships a new release. The probe shells out to `git ls-remote --tags --refs <upstream>` against the deft submodule's `origin` remote at most once every 24 hours, parses the highest semver tag, and -- if your local checkout is behind -- prints a single informational warn line below the existing recorded-vs-current message:
165
165
 
166
166
  ```
167
- ⚠ Upstream directive v0.24.0 is available (you are on v0.23.0). Run `task framework:check-updates` for details; follow `skills/deft-directive-sync/SKILL.md` Phase 2 to update.
167
+ ⚠ Upstream directive v0.24.0 is available (you are on v0.23.0). Run `task framework:check-updates` for details; follow `skills/deft-directive-sync/SKILL.md` Phase 0 (npm + `directive update` / `deft update`) and Phase 8 SCM release handoff (`released` | `pr-open` | `blocked:<reason>`) — not submodule Phase 2 alone (#1604).
168
168
  ```
169
169
 
170
170
  The banner is informational only: it never blocks CI, never prompts in non-interactive sessions, and never triggers a second `Continue anyway?` prompt on top of the existing #410 marker-drift gate. Re-notification cadence is per-tag -- once you dismiss `v0.24.0` the banner stays silent for 24 hours, but a fresh `v0.24.1` re-notifies immediately. State is persisted to `xbrief/.deft-remote-probe.json`; per-`run`-invocation dedup prevents the same banner from stacking when chained commands (e.g. `cmd_install -> cmd_project -> cmd_spec`) all hit the gate.
package/Taskfile.yml CHANGED
@@ -954,7 +954,7 @@ tasks:
954
954
  CLI_ARGS: "{{.CLI_ARGS}}"
955
955
 
956
956
  triage:classify:
957
- desc: "Inspect / validate the auto-classification surface (#1129 / D10). -- task triage:classify -- [--list | --validate]"
957
+ desc: "Inspect / validate auto-classification + Tier-1 SCM label mirror (#1129 / #1423). -- task triage:classify -- [--list | --validate | --mirror [--apply]]"
958
958
  cmds:
959
959
  - task: triage-classify:classify
960
960
  vars:
package/UPGRADING.md CHANGED
@@ -187,6 +187,39 @@ the configured mirror.
187
187
 
188
188
  Start a **new agent session** after steps 2–3 so the refreshed AGENTS.md and skills load from a clean context.
189
189
 
190
+ ## SCM release handoff after deposit (#1604)
191
+
192
+ Successful deposit is **not** the same as upgrade released. After `npm i -g @deftai/directive@latest` + `directive update` / `deft update` (+ doctor), the consumer still needs the framework update on the **default branch** (or an explicit PR) before the operator goal is complete.
193
+
194
+ The `deft-directive-sync` skill (and any agent following this upgrade path) MUST finish in **exactly one** terminal state:
195
+
196
+ | Terminal state | Meaning |
197
+ | --- | --- |
198
+ | `released` | Default branch carries the framework update |
199
+ | `pr-open` | Framework-only branch pushed + PR opened (awaiting review/merge) |
200
+ | `blocked:<reason>` | Explicit blocker (dirty worktree, auth, branch protection, human-merge gate, CI, operator declined, …) |
201
+
202
+ **Policy-aware paths:**
203
+
204
+ 1. **Branch-protected / `requireHumanMerge`** — create a framework-only branch, commit deposit files only, push, open a PR. Stop at `pr-open`. Do **not** auto-merge past the human merge gate (#1193).
205
+ 2. **Direct-commit enabled** (`allowDirectCommitsToMaster` / equivalent, and not human-merge gated) — explicit default-branch path with confirmation, then push; end at `released` only when the default branch carries the update.
206
+
207
+ **Rules:**
208
+
209
+ - ⊗ End at a local framework-only commit without naming the next release step (push/PR or confirmed direct commit).
210
+ - ⊗ Claim `released` when the change is only local or only on an open PR.
211
+ - ! Keep upgrade commits/PRs framework-only (do not mix product feature work).
212
+ - ! Missing global CLI → remediate with `npm i -g @deftai/directive@latest` (not GitHub release-asset archaeology).
213
+ - ! Git submodule update remains **legacy / back-compat only**; npm + `directive update` / `deft update` is the primary path.
214
+
215
+ Machine-readable skill exit line (for agents/operators):
216
+
217
+ ```text
218
+ upgrade-handoff: released
219
+ upgrade-handoff: pr-open
220
+ upgrade-handoff: blocked:<reason>
221
+ ```
222
+
190
223
  ## OpenPackage tiered skills (optional, #2462)
191
224
 
192
225
  The npm engine (`npm i -g @deftai/directive`) remains the canonical runtime handler for gates, lifecycle, and `.deft/core/` refresh. **OpenPackage** is an optional cross-harness distribution path for placing tiered consumer skills into Cursor, Codex CLI, and OpenCode native directories — without a Directive-owned skill router.
@@ -919,7 +952,7 @@ The contract is byte-stable by construction:
919
952
  - **Restart required:** No for the probe. Once you actually update the framework (refresh the `./deft` submodule), the standard "start a new agent session" rule from the recorded-vs-current upgrade flow applies.
920
953
  - **Commands:**
921
954
  - `task framework:check-updates` (synchronous probe, exit 1 on BEHIND; pass `-- --force` to bypass the 24h throttle and `-- --json` for machine-parseable output)
922
- - `git submodule update --remote --merge deft && git add deft && git commit -m "chore(deft): bump submodule"` (canonical update path -- mirrors `skills/deft-directive-sync/SKILL.md` Phase 2)
955
+ - Prefer `npm i -g @deftai/directive@latest` + `directive update` / `deft update` (canonical). Legacy submodule: `git submodule update --remote --merge deft && git add deft && git commit -m "chore(deft): bump submodule"` then Phase 8 SCM release handoff (`skills/deft-directive-sync/SKILL.md`) do not stop at local commit only (#1604)
923
956
  - `.deft/core/run upgrade` (after the bump, to record the new framework version in `vbrief/.deft-version` and refresh the AGENTS.md managed section)
924
957
  - `DEFT_NO_NETWORK=1 task <anything>` (CI / air-gapped opt-out: probe short-circuits before any subprocess call)
925
958
 
package/commands.md CHANGED
@@ -55,7 +55,7 @@ When the user types a product slash command, agents MUST route to the correspond
55
55
  These commands are NOT migrated — they operate on shared xBRIEF session abstractions usable across Deft products:
56
56
 
57
57
  - `/deft:continue` — Resume from continue checkpoint ([resilience/continue-here.md](./resilience/continue-here.md))
58
- - `/deft:checkpoint` — Save session state to `./xbrief/continue.xbrief.json`
58
+ - `/deft:checkpoint` — Save session state to `./xbrief/continue.xbrief.json` (same strategy doc: [resilience/continue-here.md](./resilience/continue-here.md); wrappers load that path, not the save-file output)
59
59
 
60
60
  ### Deprecation aliases (prior `/deft:*` product forms)
61
61
 
@@ -242,7 +242,7 @@ Current status: the validation, extractor, provider, registry, generated MAP, an
242
242
  - ⊗ Skip the merge chokepoint because the iteration lane passed.
243
243
  - `task verify:session-ritual` -- validate session-start ritual state.
244
244
  - `task verify:branch` -- enforce default-branch protection.
245
- - `task verify:hooks-installed` -- ensure local git hooks are configured; use `deft verify:hooks-installed --scope=agent` for agent-host hooks.
245
+ - `task verify:hooks-installed` -- ensure local git hooks are configured; use `deft verify:hooks-installed --scope=agent --live` for fail-closed agent-host registration + command functionality.
246
246
  - `task verify:encoding` -- detect mojibake and BOM issues.
247
247
  - `task verify:xbrief-conformance` -- validate xBRIEF conformance surfaces.
248
248
  - `task verify:cache-fresh` -- validate cache freshness where required.
@@ -293,12 +293,14 @@ When the workflow needs an Approach 1 monitor, scope the Cursor leaf `stop-at: p
293
293
 
294
294
  - **Read-only explore (#1185):** Prefer Grok role deposit `default_capability_mode = "read-only"` (see [issue #1185](https://github.com/deftai/directive/issues/1185)). Hooks also deny direct writes when `DEFT_HOOK_READ_ONLY=1` or the host payload signals read-only capability. Implementation and ephemeral spawns remain blocked in read-only posture unless explicitly marked explore.
295
295
 
296
- - Verify registration: `deft verify:hooks-installed --scope=agent` (or `--scope=all` for git + agent hooks).
296
+ - Verify registration only: `deft verify:hooks-installed --scope=agent` (or `--scope=all` for git + agent hooks). Verify fail-closed functional readiness: `deft verify:hooks-installed --scope=agent --live`; `--live` requires explicit `agent` or `all` scope because the default scope remains `git`.
297
+ - **Readiness model (#3100):** reports registration → command functionality → host trust → interception coverage as four separate states. Structural registration fails first; only then does the live check invoke the installed `deft-hook` shim with allow/deny fixtures for enabled Claude, Grok, Cursor, and Codex codecs. Missing/drifted registration, unavailable shim, timeout, empty/invalid required output, or a wrong decision envelope exits non-zero. The probe does not prove host interception. Full contract and latency budget: [contracts/agent-hook-readiness.md](./contracts/agent-hook-readiness.md).
298
+ - **Post-deposit report (#3100):** `directive init` and `deft update` run readiness after writing hook deposits. A red post-check returns non-zero but does not roll back the completed deposit; JSON distinguishes `deposit_completed` from `agent_hook_readiness.ready`.
297
299
  - Repair missing/drifted entries: `deft update`.
298
300
  - **Refresh and opt-out (#2790, #2752):** Upgrade `@deftai/directive`, then run `deft update` to refresh all four deposits to the fast path; do not hand-edit host hook files. Set `plan.policy.hostHooks.<host>` to `false` only when you deliberately need to disable a host's Tier-1 enforcement — it is not the performance fix. When a host is opted out, `deft update` / `directive init` skip creating or re-merging Directive-managed hook entries for that host; if a prior deposit left managed entries in the file, the next update strips only those entries and preserves unrelated settings. Inspect with `deft policy:show --field=hostHooks`. Doctor and `verify:hooks-installed --scope=agent` treat opted-out hosts as healthy — they do not recommend `deft update` to repair them.
299
301
  - **Claude matcher scope:** Once `.claude/settings.json` hooks are loaded, Claude's `PreToolUse` matcher keys on tool names (`Edit`, `Write`, …), not target paths — matched tools can be gated for the whole session, including writes outside the project tree. Opt out of Claude hook deposit when that posture is unwanted.
300
302
  - **Compact re-arm (#2113 / #2992 / #2993):** Cursor `preCompact` and Claude/Grok `PreCompact`/`PostCompact` call `deft-hook --event session.compact` to mark the gated session ritual stale after context compaction/resume (`rearm_needed`). Prefer `deft session:ready` (#2993) as the one-shot recovery path. Multi-step remains valid: `deft session:start --rearm` (preferred when worktree/HEAD allow) or full `deft session:start`, then `deft verify:session-ritual -- --tier=gated`. Codex has no native compact hook — operators must re-run the mutation ritual manually after compaction.
301
- - Codex project hooks are trust-gated by Codex. Directive verifies only that the registrations are structurally current; after an install or changed hook hash, open `/hooks` in Codex and review/approve the project hook commands. Runtime trust cannot be inferred from the file alone.
303
+ - 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.
302
304
  - 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).
303
305
  - The P0 hook slice does not classify shell-mediated *file* writes, richer unified-exec calls, or WebSearch by default. **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 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`.
304
306
  - **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`.
@@ -310,6 +312,17 @@ When the workflow needs an Approach 1 monitor, scope the Cursor leaf `stop-at: p
310
312
 
311
313
  Full always-on contract for the interactive session-start ritual and its gated verifier (#1149 / #1348). Read-only posture (#2176) defers this ceremony until mutation intent — see `.deft/core/commands.md` § Session routing.
312
314
 
315
+ ### Freshness contract: bound vs live generation (#3117)
316
+
317
+ After CLI/deposit upgrade, disk can show the new generation while a long-lived session still executes the pre-upgrade payload it loaded earlier. Disk-only "up to date" is **not** session readiness.
318
+
319
+ - ! Successful `init` / payload `update` stamps a monotonic live generation at `.deft/GENERATION.json` (outside `.deft/core` so replace does not wipe the counter).
320
+ - ! Mutation `session:start` (cold and re-arm) binds that generation into `.deft/session-bind.json` when payload surfaces load.
321
+ - ! Query with `deft freshness:report` / `task freshness:report` / `task session:freshness` (`--json` supported). States: `current` | `stale_soft` | `stale_hard` | `unbound`. Exit `0` only when `current`.
322
+ - ! Rebind without restarting a shared host runtime: re-load surfaces into the session, then `deft freshness:bind` (or re-arm / `session:ready`).
323
+ - ! Mid-mission: park and hand off before a hard refresh; an empty session after refresh is not work complete.
324
+ - Soft vs hard meanings, surfaces, and API: `content/docs/freshness-contract.md`.
325
+
313
326
  ### Session routing (#2176)
314
327
 
315
328
  - ! Default interactive sessions to **read-only posture** until mutation or implementation intent (questions, research, Plan Mode, ticket-shaping). Load AGENTS.md / main.md / USER.md / PROJECT-DEFINITION; confirm alignment with addressing-name; ⊗ do not write `.deft/ritual-state.json`, run install/build side effects, or emit triage welcome, branch-policy, default-branch sync, sync-skill lifecycle checks, or eval/value readback writes unless the operator asks or the task is implementation-ready.
@@ -344,15 +357,16 @@ Cross-link: spawn three postures and deny recoveries live under § Agent-host di
344
357
  ### Mutable ritual (mutation posture)
345
358
 
346
359
  - ! 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 4).
360
+ - ! 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.
347
361
  - ! **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.
348
362
  - ! **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.
349
363
  - ? 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.
350
364
  - ~ `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.
351
365
  - ~ **Process-cost events (#2994):** 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`). 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). See § Process-cost events below.
352
366
  - ~ 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.
353
- - ! 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 `deft doctor` and `deft verify:cache-fresh` entrypoints. Step 0 of the pre-`start_agent` gate stack.
354
- - ! **One-shot recovery (#2993):** 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` + `cache fetch-all --force` when `cache_fresh` is the remaining blocker, then re-verifies. Idempotent fast path when gated inspect is already fresh (no unnecessary fetch-all). Flags: `--json`, `--repo OWNER/NAME`, `--with-network` (forwarded to session:start). Prefer this over juggling the multi-step recovery sequence under hook pressure.
355
- - ? Postpone with `deft session:start -- --defer step=reason` (`alignment`, `branch_policy`, `triage_welcome`, `doctor`, `cache_fresh`).
367
+ - ! 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 `deft verify:cache-fresh` entrypoints. Agent-hook correctness is independent of doctor warnings and throttling. Step 0 of the pre-`start_agent` gate stack.
368
+ - ! **One-shot recovery (#2993 / #3100):** 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` + `cache fetch-all --force` when `cache_fresh` is the remaining blocker, then re-verifies. Even when gated inspect is already fresh, the fast path forces one live `agent_hooks` check so later drift cannot hide behind cached ritual state; it still avoids unnecessary fetch-all. Flags: `--json`, `--repo OWNER/NAME`, `--with-network` (forwarded to session:start). Prefer this over juggling the multi-step recovery sequence under hook pressure.
369
+ - ? Postpone with `deft session:start -- --defer step=reason` (`alignment`, `branch_policy`, `triage_welcome`, `doctor`, `cache_fresh`). `agent_hooks` is non-deferrable.
356
370
  - Headless workers / CI MAY set `DEFT_SESSION_RITUAL_SKIP=1`; verifier exits 0 but warns when bypass hides failure.
357
371
  - ⊗ Self-report ritual complete without fresh `deft session:start` state; ⊗ bypass `deft verify:session-ritual` before implementation dispatch; ⊗ reorder/skip/merge ritual tiers without operator override.
358
372
 
@@ -475,6 +489,7 @@ Directive does not guess your mix. Either you name the next units in order (**or
475
489
  - `task triage:reset -- <issue>` -- append a reset record so a candidate can be reconsidered.
476
490
  - `task triage:bulk-accept|bulk-reject|bulk-defer|bulk-needs-ac` -- apply predictable decisions over filtered cached candidates.
477
491
  - `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.
492
+ - `task triage:classify -- --mirror [--apply] [--repo owner/name] [--json]` -- **Tier-1 deterministic SCM label mirror (#1423 Wave 1).** Runs the existing classify engine over the github-issue cache and mirrors outcomes as labels (`triaged` idempotency marker + optional `plan.policy.triageLabelMirror.actionLabels`). Dry-run by default (prints a digest of planned adds/skips with zero SCM writes); `--apply` writes via the SCM label client / repo-mutation boundary (same surface family as `vbrief:reconcile:labels`). Re-run is a no-op for issues already carrying `triaged`. **Never** calls `triage:accept` and **never** writes `proposed/` xBRIEFs. Waves 2–3 (bootstrap mass-triage, agent Tier-2 comments) are out of scope for this flag.
478
493
 
479
494
  ### Cache Tasks
480
495
 
@@ -0,0 +1,67 @@
1
+ # Contract: Functional agent-hook readiness (#3100)
2
+
3
+ Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
4
+
5
+ ## Purpose
6
+
7
+ Mutation readiness must not report green when an enabled agent-host hook is missing, drifted, unavailable, or non-functional. This gate is deterministic and independent of doctor severity and doctor throttling.
8
+
9
+ The canonical command is:
10
+
11
+ ```bash
12
+ deft verify:hooks-installed --scope=agent --live
13
+ ```
14
+
15
+ Default `verify:hooks-installed` scope remains `git`; callers must explicitly select `agent` or `all` before using `--live`.
16
+
17
+ ## Four distinct states
18
+
19
+ Readiness reports these dimensions separately for each host:
20
+
21
+ 1. **registration** — the enabled managed hook entry exists and matches the deposited contract;
22
+ 2. **command functionality** — allow and deny fixtures pass through the installed `deft-hook` shim and produce the host-specific decision envelope;
23
+ 3. **host trust** — whether the host has authorized the project hook;
24
+ 4. **interception coverage** — whether the host actually invoked the hook for a real tool action.
25
+
26
+ The live probe verifies the first two dimensions. It does not simulate a host tool call, so interception remains `not-directly-verified`. Codex project-hook trust cannot be read by Directive and is reported as `manual-review-required`; operators open `/hooks` and approve the exact project commands. Neither state is described as active or trusted merely because the registration and shim work.
27
+
28
+ ## Gate behavior
29
+
30
+ - ! Structural inspection runs first. A missing or drifted enabled registration fails before any subprocess probe.
31
+ - ! On structural green, the installed `deft-hook` shim is invoked directly for allow and deny fixtures. Resolving and running the full `deft` CLI is not a fallback.
32
+ - ! The host-specific codecs for Claude, Grok, Cursor, and Codex are checked. Missing command, timeout, empty or invalid JSON where a decision is required, and wrong allow/deny envelopes fail closed.
33
+ - ! Exit `0` means all enabled hosts are structurally registered and functionally green (or every host is intentionally disabled). Exit `1` means drift/non-functional output. Exit `2` means the installed shim is unavailable or configuration cannot be evaluated.
34
+ - ! A maintainer source checkout skips this consumer-only gate; missing consumer deposits in the Directive framework repository are not failures.
35
+ - ⊗ Treat Codex `manual-review-required` as a default hard failure. Trust remains a distinct operator-review state in v1.
36
+
37
+ ## Per-host opt-out
38
+
39
+ `plan.policy.hostHooks.<host> = false` is the only opt-out surface. Inspect it with:
40
+
41
+ ```bash
42
+ deft policy:show --field=hostHooks
43
+ ```
44
+
45
+ Only enabled hosts can fail readiness. An opted-out host reports `registration=disabled`, `functionality=disabled`, `trust=disabled`, and `interception=disabled`; it is not probed and repair output must not tell the operator to reinstall that host. When a failed enabled host is unused, recovery copy points to the existing `hostHooks` policy as well as `deft update`.
46
+
47
+ This policy is independent of `.githooks/` and `hostSlashCommands`.
48
+
49
+ ## Mutation-path wiring
50
+
51
+ - `directive init` and `deft update` run and report readiness after depositing hooks. A readiness failure returns non-zero without rolling back the completed deposit; JSON reports `deposit_completed: true` separately from `success` and `agent_hook_readiness.ready`.
52
+ - `deft verify:session-ritual -- --tier=gated` owns a non-deferrable `agent_hooks` step that invokes the canonical live command. It does not route through doctor.
53
+ - `deft session:ready` forces that gated hook check once even when cached gated state looked fresh, so later registration drift cannot be hidden by the fast path.
54
+ - Cold `deft session:start` does not run the live probe. It remains the quick-tier ceremony and does not record an `agent_hooks` success.
55
+
56
+ ## Probe budget
57
+
58
+ Each host fixture has a hard timeout of **1.5 seconds** and each host stops after its first failed fixture. With four enabled hosts and two fixtures each, the absolute timeout ceiling is **12 seconds**; healthy local shims are expected to finish well below that ceiling. The gate does not inherit doctor's 4-hour or 24-hour throttle.
59
+
60
+ ## Implementation anchors
61
+
62
+ - Coordinator: `packages/core/src/verify-env/agent-hook-readiness.ts`
63
+ - Live probe and codecs: `packages/core/src/verify-env/agent-hooks-live-probe.ts`
64
+ - CLI: `packages/cli/src/verify-hooks-installed.ts`
65
+ - Mutation ritual: `packages/core/src/session/verify-session-ritual.ts`
66
+ - One-shot readiness: `packages/core/src/session/session-ready.ts`
67
+ - Post-deposit reporting: `packages/core/src/init-deposit/init-deposit.ts`, `packages/core/src/init-deposit/refresh.ts`
@@ -212,11 +212,11 @@
212
212
  },
213
213
  {
214
214
  "id": "resilience-session-continuity",
215
- "text": "Persist to `./vbrief/continue.vbrief.json` in vBRIEF format",
215
+ "text": "Persist to `./xbrief/continue.xbrief.json` in xBRIEF format",
216
216
  "owner_file": "content/resilience/continue-here.md",
217
217
  "owner_section": "## Continue Checkpoint Contents",
218
218
  "authority": "MUST",
219
- "last_verified": "2026-04-28"
219
+ "last_verified": "2026-08-04"
220
220
  },
221
221
  {
222
222
  "id": "context-engineering-write-strategy",
@@ -0,0 +1,139 @@
1
+ # Freshness contract: bound vs live generation (#3117)
2
+
3
+ Long-lived multi-agent sessions can keep executing the pre-upgrade payload they
4
+ loaded earlier even after `directive update` / deposit apply succeeds and disk
5
+ probes report "up to date." This product **freshness contract** is host-agnostic:
6
+ it does not depend on any single host session-key mechanism.
7
+
8
+ ## Readiness rule
9
+
10
+ Disk-only freshness is **insufficient**. A session is ready only when its
11
+ **bound** generation matches the **live** deposit generation for the surfaces
12
+ it uses.
13
+
14
+ ## Generation token
15
+
16
+ On successful deposit apply (`directive init`) or payload refresh
17
+ (`directive update` when content swaps), Directive stamps a **monotonic** live
18
+ generation under:
19
+
20
+ ```text
21
+ .deft/GENERATION.json
22
+ ```
23
+
24
+ The file is outside `.deft/core/` so a full-tree payload replace does not wipe
25
+ the counter. Fields include `generation` (integer ≥ 1), `contentVersion`,
26
+ `stampedAt`, `stampedBy`, and per-surface fingerprints (`payload`, `version`,
27
+ `templates`, `skills`, `docs`).
28
+
29
+ Already-current update paths ensure the token exists without advancing the
30
+ counter when the content version is unchanged.
31
+
32
+ ## Session bind
33
+
34
+ When a mutation `session:start` (cold or re-arm) loads payload surfaces into
35
+ runtime context, it binds the live generation:
36
+
37
+ ```text
38
+ .deft/session-binds/<safe-session-id>.json # multi-agent isolation (preferred)
39
+ .deft/session-bind.json # default / last-bind convenience
40
+ ```
41
+
42
+ Multi-agent hosts **must** pin session identity so one session cannot certify
43
+ another as current:
44
+
45
+ 1. Prefer `DEFT_SESSION_ID=<id>` in the process environment (printed by
46
+ `session:start`), or
47
+ 2. Pass `--session-id <id>` on every `freshness:report` / `freshness:bind`.
48
+
49
+ Trusted readiness (`state=current`, exit 0) requires a **pinned** identity
50
+ (explicit flag or `DEFT_SESSION_ID`). Bare report without a pin never returns
51
+ `ready=true` even if a ritual-recovered bind matches live — that prevents
52
+ cross-session false current when multiple agents share a worktree.
53
+
54
+ `session:start` binds the ritual `session_id` path and prints the
55
+ `DEFT_SESSION_ID=…` line for the operator or host to adopt.
56
+
57
+ Hosts and operators can rebind without restarting the shared host runtime:
58
+
59
+ ```bash
60
+ # After re-loading payload surfaces into the session:
61
+ deft freshness:bind -- --confirm-payload-loaded
62
+ # multi-agent hosts MUST pin identity:
63
+ deft freshness:bind -- --session-id <host-session-id> --confirm-payload-loaded
64
+ export DEFT_SESSION_ID=<host-session-id>
65
+ deft freshness:report
66
+ # or
67
+ deft freshness:report -- --session-id <host-session-id>
68
+ ```
69
+
70
+ `session:start` attests `payloadLoaded` automatically (payload load ceremony).
71
+ A bare bind without `--confirm-payload-loaded` never yields trusted readiness.
72
+
73
+ API (TypeScript): `bindSessionGeneration(projectRoot, options)` /
74
+ `reportFreshness(projectRoot, { sessionId })` from
75
+ `@deftai/directive-core/freshness`.
76
+
77
+ ## Freshness report
78
+
79
+ ```bash
80
+ deft freshness:report
81
+ task freshness:report
82
+ task session:freshness
83
+ deft freshness:report -- --json
84
+ ```
85
+
86
+ Exit codes:
87
+
88
+ | Code | Meaning |
89
+ |------|---------|
90
+ | 0 | `current` — bound matches live for used surfaces |
91
+ | 1 | `stale_soft` or `unbound` — caution / not yet bound |
92
+ | 2 | `stale_hard` — rebind before trusted work |
93
+
94
+ Report fields: bound generation, live generation, state, differing surfaces
95
+ (hard vs soft), rebind guidance, mid-mission safety note.
96
+
97
+ ## State meanings
98
+
99
+ | State | Meaning | Operator action |
100
+ |-------|---------|-----------------|
101
+ | `current` | Bound matches live | Ready for trusted work |
102
+ | `stale_soft` | Additive / advisory drift (e.g. docs-only) | Safe to continue with caution; rebind when convenient |
103
+ | `stale_hard` | Evidence-untrustworthy drift (payload / version / templates / skills, or generation advance) | **Must rebind** before trusted work |
104
+ | `unbound` | No session bind recorded | Bind after loading surfaces |
105
+
106
+ Hard surfaces: `payload`, `version`, `templates`, `skills`.
107
+ Soft surfaces: `docs` (advisory).
108
+
109
+ ## Rebind without host restart
110
+
111
+ 1. Park in-flight mission work (see mid-mission safety).
112
+ 2. Re-load skill, ritual, template, and command bodies from the live deposit into
113
+ the session context (host-specific load; product does not restart the host).
114
+ 3. Run `deft freshness:bind` (or cold/re-arm `session:start`, which binds
115
+ automatically).
116
+ 4. Confirm with `deft freshness:report` → `current`.
117
+
118
+ Prefer `session:start --rearm` or `session:ready` when ritual state is still
119
+ valid on the same worktree — re-arm also rebinds generation.
120
+
121
+ ## Mid-mission safety
122
+
123
+ - **Park and hand off** before a hard refresh or hard rebind.
124
+ - An empty session after refresh is **not** "work complete." Resume from the
125
+ handoff artifact, not from a blank context.
126
+ - Consumer policy decides *when* to refresh; this product owns generation +
127
+ honesty of bound-vs-live.
128
+
129
+ ## Non-goals
130
+
131
+ - Restarting the whole shared runtime as the freshness mechanism.
132
+ - Auto-resetting sessions on any file mtime change.
133
+ - Bound proof for remote PR claims (see #3120).
134
+
135
+ ## Related
136
+
137
+ - `content/commands.md` § Session-start ritual / freshness pointer
138
+ - Doctor `payload-staleness` (disk/registry currency) — complementary, not a substitute
139
+ - Issue #3117
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deftai/directive-content",
3
- "version": "0.94.0",
3
+ "version": "0.95.0",
4
4
  "description": "Shippable Directive framework content in the consumer .deft/core/ layout (C1 flatten), plus the engine surfaces (.githooks/, Taskfile.yml, tasks/) the deposit wires. Python-free per #2022 Phase 3. Refs #11, #1669, #1967.",
5
5
  "license": "MIT",
6
6
  "type": "module",