@deftai/directive-runtime 0.128.0 → 0.129.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.
Files changed (41) hide show
  1. package/dist/contract-entry.js +2 -0
  2. package/dist/setup-wiring.d.ts +14 -1
  3. package/dist/setup-wiring.js +33 -3
  4. package/dist/setup.d.ts +4 -0
  5. package/dist/setup.js +7 -1
  6. package/dist/verify-ac.js +29 -2
  7. package/package.json +1 -1
  8. package/vendor/directive-core/dist/.tsbuildinfo +1 -1
  9. package/vendor/directive-core/dist/hooks/scope.d.ts +57 -0
  10. package/vendor/directive-core/dist/hooks/scope.d.ts.map +1 -1
  11. package/vendor/directive-core/dist/hooks/scope.js +171 -0
  12. package/vendor/directive-core/dist/hooks/scope.js.map +1 -1
  13. package/vendor/directive-core/dist/packs/pack-render.d.ts +6 -1
  14. package/vendor/directive-core/dist/packs/pack-render.d.ts.map +1 -1
  15. package/vendor/directive-core/dist/packs/pack-render.js +103 -78
  16. package/vendor/directive-core/dist/packs/pack-render.js.map +1 -1
  17. package/vendor/directive-core/dist/packs/packs-root.d.ts +53 -0
  18. package/vendor/directive-core/dist/packs/packs-root.d.ts.map +1 -0
  19. package/vendor/directive-core/dist/packs/packs-root.js +83 -0
  20. package/vendor/directive-core/dist/packs/packs-root.js.map +1 -0
  21. package/vendor/directive-core/dist/packs/packs-slice.d.ts.map +1 -1
  22. package/vendor/directive-core/dist/packs/packs-slice.js +6 -6
  23. package/vendor/directive-core/dist/packs/packs-slice.js.map +1 -1
  24. package/vendor/directive-core/dist/preflight-gh/pre-push.d.ts.map +1 -1
  25. package/vendor/directive-core/dist/preflight-gh/pre-push.js +13 -0
  26. package/vendor/directive-core/dist/preflight-gh/pre-push.js.map +1 -1
  27. package/vendor/directive-core/dist/product-first-done-gate/acceptance-resolver.d.ts +1 -1
  28. package/vendor/directive-core/dist/product-first-done-gate/acceptance-resolver.d.ts.map +1 -1
  29. package/vendor/directive-core/dist/product-first-done-gate/acceptance-resolver.js +1 -1
  30. package/vendor/directive-core/dist/product-first-done-gate/acceptance-resolver.js.map +1 -1
  31. package/vendor/directive-core/dist/product-first-done-gate/index.d.ts +1 -1
  32. package/vendor/directive-core/dist/product-first-done-gate/index.d.ts.map +1 -1
  33. package/vendor/directive-core/dist/product-first-done-gate/index.js +1 -1
  34. package/vendor/directive-core/dist/product-first-done-gate/index.js.map +1 -1
  35. package/vendor/directive-core/dist/release/main.d.ts.map +1 -1
  36. package/vendor/directive-core/dist/release/main.js +3 -2
  37. package/vendor/directive-core/dist/release/main.js.map +1 -1
  38. package/vendor/directive-core/dist/release/version.d.ts +14 -0
  39. package/vendor/directive-core/dist/release/version.d.ts.map +1 -1
  40. package/vendor/directive-core/dist/release/version.js +28 -0
  41. package/vendor/directive-core/dist/release/version.js.map +1 -1
@@ -61,6 +61,8 @@ export async function handleContractEntrypoint(argv) {
61
61
  operation: operation,
62
62
  from,
63
63
  root,
64
+ // Explicit pre-write operator force only (#5837); self-complete never forces.
65
+ forceGitHooks: hasFlag(argv, "--force-githooks"),
64
66
  });
65
67
  process.stdout.write(`${JSON.stringify(result)}\n`);
66
68
  if (result.conflicts.length > 0)
@@ -84,10 +84,23 @@ export declare function ensureHostHooks(projectRoot: string, hostHooksPolicy?: H
84
84
  export declare const PRE_PUSH_BOUND_PRE_PR_MARKER = "deft:pre-pr-bound-push-v1";
85
85
  /** AC8.6 / AC2.5 / F-008 — disclosed when hooks files exist but core.hooksPath cannot activate. */
86
86
  export declare const GIT_HOOKS_INACTIVE_NO_GIT = "Git hooks inactive until git init + eligible repair/self-complete (core.hooksPath not set)";
87
- export declare function ensureGitHooks(projectRoot: string): {
87
+ /**
88
+ * True when `rel` is tracked by git in `projectRoot` (#5837). Any git failure
89
+ * (no repo, no git binary) reads as untracked, which keeps the replace path lawful.
90
+ */
91
+ export declare function isGitTrackedPath(projectRoot: string, rel: string): boolean;
92
+ /** Disclosure for a tracked divergent managed hook kept in place (#5837). */
93
+ export declare function formatTrackedHookPreserved(rel: string): string;
94
+ export interface EnsureGitHooksOptions {
95
+ /** Explicit pre-write operator force: replace tracked divergent managed hooks (#5837). */
96
+ readonly forceTrackedReplace?: boolean;
97
+ }
98
+ export declare function ensureGitHooks(projectRoot: string, options?: EnsureGitHooksOptions): {
88
99
  created: string[];
89
100
  modified: string[];
90
101
  conflicts: string[];
102
+ /** Tracked divergent managed hooks kept in place; a non-failure outcome (#5837). */
103
+ preserved: string[];
91
104
  /** True only when core.hooksPath is relative .githooks (AC9.9). */
92
105
  hooksPathActive: boolean;
93
106
  /** Human disclosure when hooks are not live; null when active. */
@@ -740,10 +740,31 @@ function isOurGitHookBody(rel, body) {
740
740
  const EXECUTABLE_GITHOOKS = new Set([".githooks/pre-commit", ".githooks/pre-push"]);
741
741
  /** AC8.6 / AC2.5 / F-008 — disclosed when hooks files exist but core.hooksPath cannot activate. */
742
742
  export const GIT_HOOKS_INACTIVE_NO_GIT = "Git hooks inactive until git init + eligible repair/self-complete (core.hooksPath not set)";
743
- export function ensureGitHooks(projectRoot) {
743
+ /**
744
+ * True when `rel` is tracked by git in `projectRoot` (#5837). Any git failure
745
+ * (no repo, no git binary) reads as untracked, which keeps the replace path lawful.
746
+ */
747
+ export function isGitTrackedPath(projectRoot, rel) {
748
+ try {
749
+ execFileSync("git", ["-C", projectRoot, "ls-files", "--error-unmatch", "--", rel], {
750
+ stdio: ["ignore", "ignore", "ignore"],
751
+ });
752
+ return true;
753
+ }
754
+ catch {
755
+ return false;
756
+ }
757
+ }
758
+ /** Disclosure for a tracked divergent managed hook kept in place (#5837). */
759
+ export function formatTrackedHookPreserved(rel) {
760
+ return `${rel}: tracked managed hook differs from the template; kept (not a failure). Review and pass --force-githooks to setup to replace it (#5837)`;
761
+ }
762
+ export function ensureGitHooks(projectRoot, options = {}) {
744
763
  const created = [];
745
764
  const modified = [];
746
765
  const conflicts = [];
766
+ const preserved = [];
767
+ const force = options.forceTrackedReplace === true;
747
768
  const files = [
748
769
  { rel: ".githooks/_directive-run.sh", body: GITHOOK_HELPER },
749
770
  { rel: ".githooks/pre-commit", body: PRE_COMMIT },
@@ -756,6 +777,12 @@ export function ensureGitHooks(projectRoot) {
756
777
  conflicts.push(`${file.rel}: existing hook is not Directive-managed; refusing to overwrite (chain or remove manually)`);
757
778
  continue;
758
779
  }
780
+ // Tracked divergent preserve (#5837): never overwrite a committed hook body,
781
+ // even a Directive-managed one, unless the operator forced the replace.
782
+ if (prior !== null && prior !== next && !force && isGitTrackedPath(projectRoot, file.rel)) {
783
+ preserved.push(formatTrackedHookPreserved(file.rel));
784
+ continue;
785
+ }
759
786
  // Refuse-to-downgrade: marker-aware installer will not replace a newer enrolled
760
787
  // pre-push arm with an older body that lacks the monotonic marker (#5804).
761
788
  if (file.rel === ".githooks/pre-push" &&
@@ -802,7 +829,10 @@ export function ensureGitHooks(projectRoot) {
802
829
  catch {
803
830
  stillReferenced = true;
804
831
  }
805
- if (!stillReferenced) {
832
+ if (!stillReferenced && !force && isGitTrackedPath(projectRoot, legacyHelperRel)) {
833
+ preserved.push(formatTrackedHookPreserved(legacyHelperRel));
834
+ }
835
+ else if (!stillReferenced) {
806
836
  try {
807
837
  const rem = containedRemove({ root: projectRoot, target: legacyHelperRel });
808
838
  if (rem.removed)
@@ -847,7 +877,7 @@ export function ensureGitHooks(projectRoot) {
847
877
  inactiveDisclosure = `Git hooks inactive: core.hooksPath is '${current}' (not .githooks)`;
848
878
  }
849
879
  }
850
- return { created, modified, conflicts, hooksPathActive, inactiveDisclosure };
880
+ return { created, modified, conflicts, preserved, hooksPathActive, inactiveDisclosure };
851
881
  }
852
882
  const MINIMAL_TASKFILE = `version: '3'
853
883
 
package/dist/setup.d.ts CHANGED
@@ -11,6 +11,8 @@ export interface SetupResult {
11
11
  readonly modified: string[];
12
12
  readonly removed: string[];
13
13
  readonly conflicts: string[];
14
+ /** Tracked divergent managed hooks kept in place; non-failure, present only when non-empty (#5837). */
15
+ readonly preserved?: string[];
14
16
  readonly message: string;
15
17
  }
16
18
  /**
@@ -22,6 +24,8 @@ export declare function runSetup(options: {
22
24
  readonly operation: SetupOperation;
23
25
  readonly from: string;
24
26
  readonly root: string;
27
+ /** Explicit pre-write operator force to replace tracked divergent managed hooks (#5837). */
28
+ readonly forceGitHooks?: boolean;
25
29
  }): SetupResult;
26
30
  export declare function setupChangeCount(result: SetupResult): number;
27
31
  //# sourceMappingURL=setup.d.ts.map
package/dist/setup.js CHANGED
@@ -223,6 +223,8 @@ function buildOwnershipArtifacts(projectRoot) {
223
223
  */
224
224
  export function runSetup(options) {
225
225
  const { operation, from, root } = options;
226
+ let preserved = [];
227
+ const withPreserved = () => (preserved.length > 0 ? { preserved } : {});
226
228
  const created = [];
227
229
  const modified = [];
228
230
  const removed = [];
@@ -297,7 +299,8 @@ export function runSetup(options) {
297
299
  const hooks = ensureHostHooks(root);
298
300
  created.push(...hooks.created);
299
301
  modified.push(...hooks.modified);
300
- const githooks = ensureGitHooks(root);
302
+ const githooks = ensureGitHooks(root, { forceTrackedReplace: options.forceGitHooks === true });
303
+ preserved = githooks.preserved;
301
304
  created.push(...githooks.created);
302
305
  modified.push(...githooks.modified);
303
306
  conflicts.push(...githooks.conflicts);
@@ -350,6 +353,7 @@ export function runSetup(options) {
350
353
  modified,
351
354
  removed,
352
355
  conflicts,
356
+ ...withPreserved(),
353
357
  message: "setup completed with conflicts",
354
358
  };
355
359
  }
@@ -371,6 +375,7 @@ export function runSetup(options) {
371
375
  modified,
372
376
  removed,
373
377
  conflicts,
378
+ ...withPreserved(),
374
379
  message: `setup ${operation} completed for ${runtimeVersion} (${RUNTIME_PREFIX}); ${disclosure}`,
375
380
  };
376
381
  }
@@ -388,6 +393,7 @@ export function runSetup(options) {
388
393
  modified,
389
394
  removed,
390
395
  conflicts,
396
+ ...withPreserved(),
391
397
  message: `setup ${operation} completed for ${runtimeVersion} (${RUNTIME_PREFIX})`,
392
398
  };
393
399
  }
package/dist/verify-ac.js CHANGED
@@ -12,7 +12,7 @@ import { join, resolve } from "node:path";
12
12
  import { fileURLToPath } from "node:url";
13
13
  import { resolveSessionCompletedVerifyAcTarget } from "../vendor/directive-core/dist/check/index.js";
14
14
  import { formatRejectedLedger, resolveLiteralAcceptanceDetailed, } from "../vendor/directive-core/dist/literal-acceptance/index.js";
15
- import { emitVerifyAcTerminalOutcome, evaluateVerifyAcFromPath, readAdmittedSourceDigest, readAdmittedSourceSentences, readPlanAcceptance, resolveAcceptanceGateProfile, resolveSoftMissingAcTargets, } from "../vendor/directive-core/dist/product-first-done-gate/index.js";
15
+ import { emitVerifyAcTerminalOutcome, evaluateVerifyAcFromPath, readAdmittedSourceDigest, readAdmittedSourceSentences, readBranchBindContext, readPlanAcceptance, resolveAcceptanceGateProfile, resolveSoftMissingAcTargets, } from "../vendor/directive-core/dist/product-first-done-gate/index.js";
16
16
  /** Parse verify:ac CLI args. */
17
17
  export function parseArgs(argv) {
18
18
  const parsed = {
@@ -287,11 +287,38 @@ export function run(argv) {
287
287
  }
288
288
  }
289
289
  else if (args.softMissingXbrief) {
290
+ const bindContext = readBranchBindContext(projectRoot);
290
291
  const selected = resolveSoftMissingAcTargets(projectRoot, {
291
292
  env: process.env,
292
293
  scannedPaths: found.paths,
294
+ branchBind: { ...bindContext, env: process.env },
293
295
  });
294
- if (selected.kind === "one") {
296
+ if (selected.kind === "untied") {
297
+ // #5855 P3: completed-target precedence, then soft-missing (no AC claimed).
298
+ const completed = resolveSessionCompletedVerifyAcTarget({
299
+ projectRoot,
300
+ env: process.env,
301
+ });
302
+ if (completed.kind === "target") {
303
+ paths = [completed.path];
304
+ if (!args.quiet) {
305
+ process.stdout.write(`verify:ac targeting just-completed brief (#3357): ${completed.path}\n`);
306
+ }
307
+ }
308
+ else if (completed.kind === "cannot") {
309
+ process.stderr.write(`${completed.message}\n`);
310
+ emitVerifyAcTerminalOutcome({ projectRoot, env: process.env, outcome: "config-error" });
311
+ return 1;
312
+ }
313
+ else {
314
+ if (!args.quiet) {
315
+ process.stdout.write(`${selected.message}\n`);
316
+ }
317
+ emitVerifyAcTerminalOutcome({ projectRoot, env: process.env, outcome: "soft-missing" });
318
+ return 0;
319
+ }
320
+ }
321
+ else if (selected.kind === "one") {
295
322
  paths = [selected.path];
296
323
  if (!args.quiet) {
297
324
  process.stdout.write(`verify:ac soft-missing multi-active (#4285): selected ${selected.path}\n`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deftai/directive-runtime",
3
- "version": "0.128.0",
3
+ "version": "0.129.0",
4
4
  "description": "Directive runtime — pinned product commands, hooks, content, and engine.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://deftai.github.io/directive/",