@deftai/directive-content 0.67.0 → 0.68.1

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,14 +1,47 @@
1
- # Shared deft CLI resolver for .githooks/* (#2067).
1
+ # Shared deft CLI resolver for .githooks/* (#2067, #2248).
2
2
  # REPO_ROOT must be set before sourcing.
3
+ #
4
+ # Resolution order:
5
+ # 1. DEFT_HOOKS_PREFER_GLOBAL=1 forces the global `deft` (escape hatch, #2248).
6
+ # 2. Framework-source (monorepo) checkout: prefer the freshly-built LOCAL CLI
7
+ # (packages/cli/dist/bin.js) over a possibly-stale global `deft`, so a
8
+ # newly-added-and-wired verb is not unknown to the global and does not
9
+ # block commits/pushes (#2248). Detected via the built local CLI existing
10
+ # under $REPO_ROOT together with a monorepo sentinel (pnpm-workspace.yaml).
11
+ # 3. Consumer install (vendored .deft/core, no local build): resolve the
12
+ # global `deft` exactly as before -- consumers have no local CLI to prefer.
13
+ # 4. Local build present without the monorepo sentinel: fall back to it.
14
+ # 5. Nothing resolvable: fail with an install hint.
3
15
 
4
16
  run_deft() {
17
+ _deft_local="$REPO_ROOT/packages/cli/dist/bin.js"
18
+
19
+ # (1) Escape hatch: force the global even in a monorepo.
20
+ if [ "${DEFT_HOOKS_PREFER_GLOBAL:-}" = "1" ] && command -v deft >/dev/null 2>&1; then
21
+ deft "$@"
22
+ return $?
23
+ fi
24
+
25
+ # (2) Framework-source checkout: the local build is authoritative for verbs.
26
+ if [ -f "$_deft_local" ] && [ -f "$REPO_ROOT/pnpm-workspace.yaml" ]; then
27
+ node "$_deft_local" "$@"
28
+ return $?
29
+ fi
30
+
31
+ # (3) Consumer install: resolve the global `deft` exactly as today.
5
32
  if command -v deft >/dev/null 2>&1; then
6
33
  deft "$@"
7
- elif [ -f "$REPO_ROOT/packages/cli/dist/bin.js" ]; then
8
- node "$REPO_ROOT/packages/cli/dist/bin.js" "$@"
9
- else
10
- echo "deft hooks: 'deft' not found on PATH and no local CLI at packages/cli/dist/bin.js." >&2
11
- echo " Install: npm i -g @deftai/directive" >&2
12
- exit 1
34
+ return $?
35
+ fi
36
+
37
+ # (4) Local build present without the monorepo sentinel.
38
+ if [ -f "$_deft_local" ]; then
39
+ node "$_deft_local" "$@"
40
+ return $?
13
41
  fi
42
+
43
+ # (5) Nothing resolvable.
44
+ echo "deft hooks: 'deft' not found on PATH and no local CLI at packages/cli/dist/bin.js." >&2
45
+ echo " Install: npm i -g @deftai/directive" >&2
46
+ exit 1
14
47
  }
@@ -17,6 +17,8 @@ run_deft verify:branch --project-root "$REPO_ROOT" || exit $?
17
17
 
18
18
  run_deft verify:encoding --staged --project-root "$REPO_ROOT" || exit $?
19
19
 
20
+ run_deft verify:forward-coverage --staged --project-root "$REPO_ROOT" || exit $?
21
+
20
22
  if [ -d "$REPO_ROOT/xbrief" ] || [ -d "$REPO_ROOT/vbrief" ]; then
21
23
  run_deft verify:vbrief-conformance --staged --project-root "$REPO_ROOT" || exit $?
22
24
  fi
package/Taskfile.yml CHANGED
@@ -353,6 +353,7 @@ tasks:
353
353
  - verify:bridge-drift
354
354
  - verify:branch
355
355
  - verify:encoding
356
+ - verify:forward-coverage
356
357
  - verify:vbrief-conformance
357
358
  - verify:destructive-gh-verbs
358
359
  - verify:scm-boundary
@@ -460,12 +461,14 @@ tasks:
460
461
  cmds:
461
462
  - task: install:uninstall
462
463
  # User-facing upgrade entrypoint (#1061). Aliases the install:upgrade
463
- # wrapper that delegates to the native deft-ts install-upgrade handler. Cited by the doctor's
464
- # failure prose and docs/install-manifest.md as the canonical
465
- # post-drift repair entrypoint for the AGENTS.md / manifest /
466
- # .deft-version triple.
464
+ # wrapper. As of #2064 the native deft-ts install-upgrade handler is a thin
465
+ # redirect onto `directive update` -- the single canonical upgrade verb that
466
+ # file-swaps the vendored .deft/core payload, rewrites the install manifest,
467
+ # and regenerates .deft-version. Prefer `deft update` directly; this alias is
468
+ # retained for compatibility. Cited by the doctor's failure prose and
469
+ # docs/install-manifest.md as the post-drift repair entrypoint.
467
470
  upgrade:
468
- desc: "Upgrade deft framework -- refresh AGENTS.md + write install manifest + regenerate .deft-version (alias for install:upgrade, #1061)"
471
+ desc: "Upgrade deft framework -- redirects to `deft update` (the canonical verb: refresh payload + AGENTS.md + install manifest + .deft-version; alias for install:upgrade, #1061/#2064)"
469
472
  cmds:
470
473
  - task: install:upgrade
471
474
 
package/UPGRADING.md CHANGED
@@ -30,6 +30,8 @@ From v0.55.1 onwards `@deftai/directive` is published on npm. The canonical cons
30
30
 
31
31
  This re-copies the vendored `.deft/core/` payload and refreshes project-root `.githooks/` (#2049).
32
32
 
33
+ > **`deft update` is the single canonical upgrade verb (#2064).** The older `deft install-upgrade` (and its `task upgrade` maintainer alias) now print a one-line notice and delegate to this exact `deft update` path — they no longer have their own semantics. Previously `install-upgrade` only rewrote the marker/manifest without swapping the payload, so on a stale deposit it reported a false "Project already at X. Nothing to do." Use `deft update`; there is nothing `install-upgrade` does that `deft update` does not.
34
+
33
35
  3. **Stamp npm provenance (one-time, idempotent):**
34
36
 
35
37
  ```bash
@@ -368,6 +370,8 @@ The transition is one-way -- v0.28 has no shim back to the bare-only marker. To
368
370
  <!-- 1061: AGENTS.md drift repair via task upgrade BEGIN -->
369
371
  ## From drifted AGENTS.md -> current install (`task upgrade` repair path, #1061)
370
372
 
373
+ > **Consolidation note (#2064):** `deft install-upgrade` and its `task upgrade` maintainer alias now delegate to the single canonical `deft update` path (see [Canonical upgrade — npm](#canonical-upgrade--npm-v0551)). The legacy `.deft/VERSION` retirement described below (backed up as `.deft/VERSION.premigrate`) is folded into `deft update`, so the drift-repair steps here still apply verbatim — the doctor now names `deft update` as the fix.
374
+
371
375
  - **Applies when:** `task framework:doctor` reports drift on any of the four checks (`quick-start-resolves`, `skill-paths-resolve`, `manifest-agreement`, `install-path-consistency`). Common causes: a canonical-reinstall over a pre-v0.27 AGENTS.md (the #1060 recurrence pattern), a marker-version mismatch where AGENTS.md still carries the v1 / v2 managed-section sentinel after a framework bump, or an install-path-consistency mismatch detected via the new `install_root` manifest field that #1062 added to `<install>/VERSION` (the doctor reads the manifest's `install_root` first, then falls back to the AGENTS.md install-root parse, and FAILs when the resolved directory does not exist on disk).
372
376
  - **Safe to auto-run:** Yes. `task upgrade` is the canonical user-facing entrypoint added in #1061; it wraps `run upgrade` and is idempotent on re-run (a second invocation against a current manifest + AGENTS.md is a no-op). The wrapper: (1) re-pulls the framework version marker by writing / refreshing `.deft-version`; (2) re-writes the canonical install manifest at `<install>/VERSION` (`ref` / `sha` / `tag` / `install_root` / `fetched_at` / `fetched_by`); (3) refreshes AGENTS.md to the current marker version (v3 sentinel with sha / refreshed / session attributes) via `cmd_agents_refresh`. Pre-v0.27 AGENTS.md files (no managed-section markers, or v1 markers) are migrated in place: content above and below the bracketed block is preserved verbatim, only the framework-owned managed section is rewritten.
373
377
  - **Restart required:** Recommended. The agent's current session may still hold stale AGENTS.md / skill references from the pre-upgrade marker. After `task upgrade` completes, start a new agent session so the refreshed prose loads from a clean context.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deftai/directive-content",
3
- "version": "0.67.0",
3
+ "version": "0.68.1",
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
  "type": "module",
6
6
  "files": [
@@ -548,6 +548,23 @@
548
548
  ],
549
549
  "source": "Issue #696. Observed 2026-04-27: a returning session emitted the alignment confirmation, ran `Test-Path` on USER.md (-> True), declared all config present, and addressed the user by a name injected via a Warp Drive notebook instead of the name in USER.md. USER.md was never read; its `Personal (always wins)` precedence rule was never applied because that rule lives inside the file the agent skipped.",
550
550
  "body": "**Source:** Issue #696. Observed 2026-04-27: a returning session emitted the alignment confirmation, ran `Test-Path` on USER.md (-> True), declared all config present, and addressed the user by a name injected via a Warp Drive notebook instead of the name in USER.md. USER.md was never read; its `Personal (always wins)` precedence rule was never applied because that rule lives inside the file the agent skipped.\n\n**Key insight:** A presence / existence check on USER.md is NOT a content read. An alignment confirmation that can be emitted without reading USER.md leaves a substitution gap: when external context (Warp Drive notebooks, MCP server outputs, prompt-injected preferences) defines the same fields as USER.md, the agent silently adopts the external value. External context sits OUTSIDE deft's precedence hierarchy -- USER.md `Personal (always wins)` must win, but only a real content read can apply that rule.\n\n**Rule:** The alignment confirmation MUST include data drawn from USER.md content -- specifically the addressing-name -- so the read is unfakeable (`Deft Directive active -- AGENTS.md loaded. Addressing you as: {Name}.`). Returning Sessions is promoted from unmarked prose to an enforced `!`/`\u2297` rule with an ordered read list (main.md -> USER.md -> PROJECT-DEFINITION) and an inline external-context precedence rule. A `Test-Path` substitution for a content read is an explicit anti-pattern.\n\n**Canonical encoding (strongest-applicable layer):** the rule body lives in `AGENTS.md` + `templates/agents-entry.md` (`## Returning Sessions` + `### Deft Alignment Confirmation`), propagated to the consumer managed-section via `task agents:refresh` (#1309). Deterministic shape-coverage: `tests/content/test_agents_md.py` (must-marker, Test-Path anti-pattern, name-echo, external-context precedence wording). The behavioral eval that actually catches the substitution failure class (conflicting USER.md vs external-context names) is deferred to its own issue (Fix D); the greet-skill structural cleanup is Fix E.\n\n**Cross-references:** `AGENTS.md` / `templates/agents-entry.md` `## Returning Sessions` + `### Deft Alignment Confirmation` (rule body); `tests/content/test_agents_md.py` (shape coverage); #163 (CLI gate parity, complementary); #258 (Warp Drive inventory, documentation half of the same root cause); #78 (adjacent bootstrap-update offer)."
551
+ },
552
+ {
553
+ "id": "prefiling-master-diff-check-2026-07",
554
+ "title": "Pre-filing master-diff check before proposing to add a file (2026-07)",
555
+ "date": "2026-07",
556
+ "issue_refs": [
557
+ "#1102",
558
+ "#1099",
559
+ "#1100",
560
+ "#1070"
561
+ ],
562
+ "tags": [
563
+ "scm",
564
+ "skills"
565
+ ],
566
+ "source": "Issue #1102. On 2026-05-12 a refinement session (PR #1098) filed #1099 proposing to add .github/dependabot.yml without checking master -- the file already existed (landed via #1070 / v0.29.1). #1099 closed as a stale duplicate the same day; #1100 re-filed as the additive-delta scope.",
567
+ "body": "**Source:** Issue #1102. On 2026-05-12 a refinement session (PR #1098) filed #1099 proposing to add `.github/dependabot.yml` without checking master -- the file already existed (landed via #1070 / v0.29.1). #1099 closed as a stale duplicate the same day; #1100 was re-filed as the additive-delta scope.\n\n**Key insight:** A one-second `git ls-tree origin/master -- <path>` (or `gh api repos/{owner}/{repo}/contents/{path}` without a clone) existence check before filing an add-a-file issue prevents this whole close-and-refile class. If the path already exists, the issue must be scoped to the DELTA vs the on-master state, not the original 'deposit this file' framing.\n\n**Canonical encoding (strongest-applicable layer):** the `!` MUST rule + `\u2297` anti-pattern live in the canonical issue-filing skill `skills/deft-directive-gh-slice/SKILL.md` (Step 5 + Anti-Patterns), cross-referenced from `skills/deft-directive-refinement/SKILL.md` Phase 1. Deterministic shape-coverage: `packages/core/src/content-contracts/skills/gh_slice_prefiling_master_diff.test.ts`.\n\n**Cross-references:** #1070 (`.github/dependabot.yml` originally landed), #1099 (stale-duplicate filing, closed), #1100 (corrected additive-scope refile), PR #1098 (refinement session that surfaced the pattern)."
551
568
  }
552
569
  ]
553
570
  }