@deftai/directive-core 0.104.0 → 0.106.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 (287) hide show
  1. package/dist/authz/classify.js +1108 -67
  2. package/dist/check/cached-orchestrator.d.ts +1 -1
  3. package/dist/check/cached-orchestrator.js +2 -2
  4. package/dist/check/named-cause.d.ts +1 -1
  5. package/dist/check/named-cause.js +34 -4
  6. package/dist/codebase/default-extractor.d.ts +5 -0
  7. package/dist/codebase/default-extractor.js +7 -15
  8. package/dist/deposit/copy-tree.js +60 -0
  9. package/dist/deposit/python-free.js +26 -18
  10. package/dist/doctor/checks.d.ts +8 -0
  11. package/dist/doctor/checks.js +37 -25
  12. package/dist/doctor/doctor-state.d.ts +4 -0
  13. package/dist/doctor/doctor-state.js +7 -1
  14. package/dist/doctor/main.js +9 -19
  15. package/dist/doctor/types.d.ts +9 -0
  16. package/dist/forward-coverage/diff-coverage.d.ts +39 -0
  17. package/dist/forward-coverage/diff-coverage.js +112 -0
  18. package/dist/forward-coverage/diff-lines.d.ts +19 -0
  19. package/dist/forward-coverage/diff-lines.js +173 -0
  20. package/dist/forward-coverage/evaluate.d.ts +24 -9
  21. package/dist/forward-coverage/evaluate.js +125 -19
  22. package/dist/fs/contained-write.d.ts +115 -1
  23. package/dist/fs/contained-write.js +241 -5
  24. package/dist/fs/mutation-ledger.d.ts +54 -0
  25. package/dist/fs/mutation-ledger.js +133 -0
  26. package/dist/fs/non-product-dirs.d.ts +79 -0
  27. package/dist/fs/non-product-dirs.js +96 -0
  28. package/dist/hooks/dispatcher.d.ts +3 -1
  29. package/dist/hooks/dispatcher.js +14 -0
  30. package/dist/index.d.ts +1 -0
  31. package/dist/index.js +2 -0
  32. package/dist/init-deposit/agent-hooks.d.ts +1 -1
  33. package/dist/init-deposit/agent-hooks.js +18 -16
  34. package/dist/init-deposit/core-guard-pin-content.d.ts +7 -0
  35. package/dist/init-deposit/core-guard-pin-content.js +393 -0
  36. package/dist/init-deposit/gitignore.js +9 -0
  37. package/dist/init-deposit/hygiene.d.ts +47 -11
  38. package/dist/init-deposit/hygiene.js +172 -37
  39. package/dist/init-deposit/legacy-detect.js +6 -2
  40. package/dist/init-deposit/refresh.d.ts +21 -1
  41. package/dist/init-deposit/refresh.js +106 -9
  42. package/dist/init-deposit/scaffold.js +28 -279
  43. package/dist/init-deposit/slash-deposit.js +13 -7
  44. package/dist/init-deposit/xbrief-projections.d.ts +8 -1
  45. package/dist/init-deposit/xbrief-projections.js +24 -11
  46. package/dist/intake/clause-derivation.d.ts +47 -1
  47. package/dist/intake/clause-derivation.js +238 -9
  48. package/dist/intake/issue-ingest.d.ts +3 -1
  49. package/dist/intake/issue-ingest.js +35 -6
  50. package/dist/lifecycle/completed-tracked-on-delivery.d.ts +5 -0
  51. package/dist/lifecycle/completed-tracked-on-delivery.js +85 -18
  52. package/dist/lifecycle-visible/evaluate.d.ts +98 -0
  53. package/dist/lifecycle-visible/evaluate.js +710 -0
  54. package/dist/lifecycle-visible/index.d.ts +2 -0
  55. package/dist/lifecycle-visible/index.js +2 -0
  56. package/dist/literal-acceptance/capture.d.ts +10 -0
  57. package/dist/literal-acceptance/capture.js +226 -77
  58. package/dist/literal-acceptance/evaluate.d.ts +29 -4
  59. package/dist/literal-acceptance/evaluate.js +70 -2
  60. package/dist/literal-acceptance/index.d.ts +3 -3
  61. package/dist/literal-acceptance/index.js +3 -3
  62. package/dist/literal-acceptance/safety.d.ts +41 -0
  63. package/dist/literal-acceptance/safety.js +126 -2
  64. package/dist/literal-acceptance/types.d.ts +8 -0
  65. package/dist/orchestration/judgment-policy.d.ts +13 -0
  66. package/dist/orchestration/judgment-policy.js +15 -0
  67. package/dist/orchestration/probe-session.js +13 -8
  68. package/dist/orchestration/verify-judgment-gates.d.ts +4 -0
  69. package/dist/orchestration/verify-judgment-gates.js +43 -11
  70. package/dist/orphan-active/evaluate.d.ts +7 -1
  71. package/dist/orphan-active/evaluate.js +102 -23
  72. package/dist/platform/platform-capabilities.js +2 -3
  73. package/dist/policy/base-branch.d.ts +37 -0
  74. package/dist/policy/base-branch.js +114 -0
  75. package/dist/policy/branch-sync.d.ts +80 -0
  76. package/dist/policy/branch-sync.js +211 -0
  77. package/dist/policy/ceremony-dial-escalation.js +1 -0
  78. package/dist/policy/ceremony-dial.js +11 -21
  79. package/dist/policy/delivery-branch.d.ts +5 -3
  80. package/dist/policy/delivery-branch.js +7 -3
  81. package/dist/policy/file-size-thresholds.d.ts +24 -0
  82. package/dist/policy/file-size-thresholds.js +23 -0
  83. package/dist/policy/forge-outage-retry.d.ts +47 -0
  84. package/dist/policy/forge-outage-retry.js +157 -0
  85. package/dist/policy/host-hooks.d.ts +20 -0
  86. package/dist/policy/host-hooks.js +121 -2
  87. package/dist/policy/index.d.ts +7 -0
  88. package/dist/policy/index.js +66 -7
  89. package/dist/policy/org-force-on-migration.js +2 -1
  90. package/dist/policy/plan-extensions.d.ts +1 -1
  91. package/dist/policy/plan-extensions.js +2 -0
  92. package/dist/policy/product-signal.js +6 -7
  93. package/dist/policy/project-invariants.d.ts +50 -0
  94. package/dist/policy/project-invariants.js +205 -0
  95. package/dist/policy/require-human-merge.js +8 -6
  96. package/dist/policy/resolve.d.ts +7 -2
  97. package/dist/policy/resolve.js +25 -8
  98. package/dist/policy/sync-default.d.ts +129 -0
  99. package/dist/policy/sync-default.js +452 -0
  100. package/dist/policy/sync-max-files.d.ts +93 -0
  101. package/dist/policy/sync-max-files.js +192 -0
  102. package/dist/policy/value-feedback.js +7 -8
  103. package/dist/pr-monitor/absent-required.d.ts +11 -0
  104. package/dist/pr-monitor/absent-required.js +61 -0
  105. package/dist/pr-monitor/constants.d.ts +7 -0
  106. package/dist/pr-monitor/constants.js +7 -0
  107. package/dist/pr-monitor/index.d.ts +2 -1
  108. package/dist/pr-monitor/index.js +2 -1
  109. package/dist/pr-monitor/main.js +4 -0
  110. package/dist/pr-monitor/monitor.js +24 -1
  111. package/dist/pr-wait-mergeable/classify.js +6 -0
  112. package/dist/preflight/evaluate.d.ts +4 -0
  113. package/dist/preflight/evaluate.js +35 -1
  114. package/dist/preflight/index.d.ts +4 -0
  115. package/dist/preflight/index.js +2 -0
  116. package/dist/preflight/intended-placement.d.ts +62 -0
  117. package/dist/preflight/intended-placement.js +275 -0
  118. package/dist/preflight/project-invariants-gate.d.ts +29 -0
  119. package/dist/preflight/project-invariants-gate.js +82 -0
  120. package/dist/preflight-cache/evaluate.d.ts +12 -0
  121. package/dist/preflight-cache/evaluate.js +15 -1
  122. package/dist/preflight-cache/index.d.ts +1 -1
  123. package/dist/preflight-cache/index.js +1 -1
  124. package/dist/product-first-done-gate/acceptance-resolver.d.ts +128 -0
  125. package/dist/product-first-done-gate/acceptance-resolver.js +144 -0
  126. package/dist/product-first-done-gate/acceptance.d.ts +7 -4
  127. package/dist/product-first-done-gate/acceptance.js +79 -8
  128. package/dist/product-first-done-gate/empty-resolution.d.ts +4 -1
  129. package/dist/product-first-done-gate/empty-resolution.js +12 -1
  130. package/dist/product-first-done-gate/evaluate.d.ts +16 -0
  131. package/dist/product-first-done-gate/evaluate.js +298 -34
  132. package/dist/product-first-done-gate/index.d.ts +2 -0
  133. package/dist/product-first-done-gate/index.js +1 -0
  134. package/dist/release/build-dist.d.ts +101 -0
  135. package/dist/release/build-dist.js +428 -46
  136. package/dist/release/closed-verb-gate.d.ts +12 -0
  137. package/dist/release/closed-verb-gate.js +51 -0
  138. package/dist/release/index.d.ts +1 -0
  139. package/dist/release/index.js +1 -0
  140. package/dist/release/pipeline.js +7 -0
  141. package/dist/release/types.d.ts +12 -0
  142. package/dist/render/constants.d.ts +2 -1
  143. package/dist/render/constants.js +2 -1
  144. package/dist/render/framework-commands.js +4 -0
  145. package/dist/render/spec-validate.js +23 -12
  146. package/dist/run-summary/emit.d.ts +16 -10
  147. package/dist/run-summary/emit.js +26 -15
  148. package/dist/run-summary/index.d.ts +3 -2
  149. package/dist/run-summary/index.js +2 -1
  150. package/dist/run-summary/session-id.d.ts +21 -0
  151. package/dist/run-summary/session-id.js +92 -0
  152. package/dist/run-summary/types.d.ts +33 -4
  153. package/dist/run-summary/types.js +1 -0
  154. package/dist/scope/acceptance-evidence.d.ts +19 -7
  155. package/dist/scope/acceptance-evidence.js +38 -11
  156. package/dist/scope/delivery-evidence.d.ts +3 -3
  157. package/dist/scope/delivery-evidence.js +22 -27
  158. package/dist/scope/index.d.ts +1 -0
  159. package/dist/scope/index.js +1 -0
  160. package/dist/scope/main.js +15 -5
  161. package/dist/scope/parent-lineage.js +7 -6
  162. package/dist/scope/project-invariant-coverage.d.ts +54 -0
  163. package/dist/scope/project-invariant-coverage.js +322 -0
  164. package/dist/scope/promote-from-issue.js +5 -5
  165. package/dist/scope/transition.js +1 -1
  166. package/dist/scope-provenance/compare-intent.d.ts +27 -0
  167. package/dist/scope-provenance/compare-intent.js +233 -0
  168. package/dist/scope-provenance/digest.d.ts +18 -1
  169. package/dist/scope-provenance/digest.js +16 -11
  170. package/dist/scope-provenance/evaluate.d.ts +5 -1
  171. package/dist/scope-provenance/evaluate.js +67 -7
  172. package/dist/scope-provenance/extract-intent.d.ts +43 -0
  173. package/dist/scope-provenance/extract-intent.js +262 -0
  174. package/dist/scope-provenance/index.d.ts +7 -1
  175. package/dist/scope-provenance/index.js +7 -1
  176. package/dist/scope-provenance/intent-digest.d.ts +12 -0
  177. package/dist/scope-provenance/intent-digest.js +33 -0
  178. package/dist/scope-provenance/intent-evaluate.d.ts +43 -0
  179. package/dist/scope-provenance/intent-evaluate.js +149 -0
  180. package/dist/scope-provenance/json-tokenizer.d.ts +19 -0
  181. package/dist/scope-provenance/json-tokenizer.js +225 -0
  182. package/dist/scope-provenance/known-machine.d.ts +38 -0
  183. package/dist/scope-provenance/known-machine.js +157 -0
  184. package/dist/scope-provenance/mint-artifacts.d.ts +102 -0
  185. package/dist/scope-provenance/mint-artifacts.js +425 -0
  186. package/dist/session/ac-pass-banking.d.ts +9 -36
  187. package/dist/session/ac-pass-banking.js +33 -79
  188. package/dist/session/ac-pass-reuse.d.ts +53 -0
  189. package/dist/session/ac-pass-reuse.js +95 -0
  190. package/dist/session/git.js +19 -4
  191. package/dist/session/index.d.ts +4 -0
  192. package/dist/session/index.js +4 -0
  193. package/dist/session/occupancy-stress-worker.d.ts +7 -0
  194. package/dist/session/occupancy-stress-worker.js +36 -0
  195. package/dist/session/occupancy.d.ts +97 -0
  196. package/dist/session/occupancy.js +422 -0
  197. package/dist/session/openclaw-soft-rebind-deposit.js +6 -6
  198. package/dist/session/process-cost.d.ts +32 -10
  199. package/dist/session/process-cost.js +189 -1
  200. package/dist/session/product-state-hash.d.ts +26 -0
  201. package/dist/session/product-state-hash.js +700 -0
  202. package/dist/session/ritual-entrypoint.js +16 -1
  203. package/dist/session/session-ready.d.ts +2 -0
  204. package/dist/session/session-ready.js +52 -30
  205. package/dist/session/session-start.d.ts +13 -0
  206. package/dist/session/session-start.js +103 -9
  207. package/dist/session/verify-ac-session-cache.d.ts +42 -0
  208. package/dist/session/verify-ac-session-cache.js +126 -0
  209. package/dist/session/verify-session-ritual.d.ts +28 -0
  210. package/dist/session/verify-session-ritual.js +97 -5
  211. package/dist/slash/openclaw-deposit.js +13 -9
  212. package/dist/slice/constants.d.ts +2 -2
  213. package/dist/slice/constants.js +2 -2
  214. package/dist/slice/existing.js +9 -3
  215. package/dist/slice/lock.d.ts +16 -1
  216. package/dist/slice/lock.js +137 -11
  217. package/dist/story-ready/evaluate.d.ts +2 -0
  218. package/dist/story-ready/evaluate.js +13 -0
  219. package/dist/swarm/complete-cohort.d.ts +3 -0
  220. package/dist/swarm/complete-cohort.js +59 -11
  221. package/dist/swarm/finalize-cohort-cli.d.ts +7 -2
  222. package/dist/swarm/finalize-cohort-cli.js +165 -35
  223. package/dist/swarm/finalize-cohort.d.ts +1 -0
  224. package/dist/swarm/finalize-cohort.js +47 -4
  225. package/dist/swarm/launch.d.ts +22 -0
  226. package/dist/swarm/launch.js +155 -0
  227. package/dist/swarm/routing-set-cli.d.ts +11 -1
  228. package/dist/swarm/routing-set-cli.js +15 -3
  229. package/dist/swarm/routing-verify.d.ts +13 -1
  230. package/dist/swarm/routing-verify.js +60 -21
  231. package/dist/swarm/routing.d.ts +14 -0
  232. package/dist/swarm/routing.js +53 -3
  233. package/dist/telemetry-coverage/fake-trial.js +10 -0
  234. package/dist/telemetry-coverage/kinds.js +2 -0
  235. package/dist/triage/actions/index.js +4 -1
  236. package/dist/triage/bootstrap/index.js +6 -6
  237. package/dist/triage/help/registry-data.d.ts +1 -1
  238. package/dist/triage/help/registry-data.js +1 -1
  239. package/dist/triage/welcome/writers.d.ts +1 -1
  240. package/dist/triage/welcome/writers.js +10 -5
  241. package/dist/ts-check-lane/index.d.ts +3 -0
  242. package/dist/ts-check-lane/index.js +2 -0
  243. package/dist/ts-check-lane/progress-reporter.d.ts +17 -0
  244. package/dist/ts-check-lane/progress-reporter.js +38 -0
  245. package/dist/ts-check-lane/progress.d.ts +32 -0
  246. package/dist/ts-check-lane/progress.js +57 -0
  247. package/dist/ts-check-lane/run-lane.d.ts +3 -1
  248. package/dist/ts-check-lane/run-lane.js +8 -6
  249. package/dist/validate-content/validate-links.d.ts +8 -0
  250. package/dist/validate-content/validate-links.js +9 -15
  251. package/dist/value/feedback-file.js +12 -2
  252. package/dist/value/readback.d.ts +4 -1
  253. package/dist/value/readback.js +51 -12
  254. package/dist/vbrief-build/index.d.ts +1 -0
  255. package/dist/vbrief-build/index.js +1 -0
  256. package/dist/vbrief-build/project-invariants-io.d.ts +16 -0
  257. package/dist/vbrief-build/project-invariants-io.js +41 -0
  258. package/dist/vbrief-reconcile/graph.js +18 -1
  259. package/dist/vbrief-reconcile/index.d.ts +1 -1
  260. package/dist/vbrief-reconcile/index.js +1 -1
  261. package/dist/vbrief-reconcile/types.d.ts +13 -0
  262. package/dist/vbrief-reconcile/umbrellas.d.ts +14 -0
  263. package/dist/vbrief-reconcile/umbrellas.js +261 -26
  264. package/dist/vbrief-validate/index.d.ts +1 -1
  265. package/dist/vbrief-validate/index.js +1 -1
  266. package/dist/vbrief-validate/plan-hooks.d.ts +4 -0
  267. package/dist/vbrief-validate/plan-hooks.js +68 -0
  268. package/dist/vbrief-validate/schema.d.ts +4 -0
  269. package/dist/vbrief-validate/schema.js +1 -1
  270. package/dist/verify-ac/evaluate.d.ts +7 -1
  271. package/dist/verify-ac/evaluate.js +34 -26
  272. package/dist/verify-ac/flag.d.ts +4 -0
  273. package/dist/verify-ac/flag.js +16 -0
  274. package/dist/verify-ac/index.d.ts +2 -2
  275. package/dist/verify-ac/index.js +2 -2
  276. package/dist/verify-env/agent-hook-readiness.d.ts +2 -2
  277. package/dist/verify-env/agent-hook-readiness.js +12 -8
  278. package/dist/verify-env/agent-hooks-live-probe.d.ts +5 -1
  279. package/dist/verify-env/agent-hooks-live-probe.js +26 -5
  280. package/dist/verify-env/agent-hooks.js +3 -4
  281. package/dist/verify-source/contained-writes.js +2 -0
  282. package/dist/verify-source/verify-stubs.d.ts +15 -1
  283. package/dist/verify-source/verify-stubs.js +20 -16
  284. package/dist/vitest-runner/win32-coverage-tmp-setup.d.ts +5 -6
  285. package/dist/vitest-runner/win32-coverage-tmp-setup.js +5 -6
  286. package/dist/xbrief-migrate/migrate-project.js +2 -5
  287. package/package.json +7 -3
@@ -9,20 +9,128 @@
9
9
  */
10
10
  import { existsSync, readFileSync } from "node:fs";
11
11
  import { basename, isAbsolute, relative, resolve } from "node:path";
12
- import { emitAcceptanceStampFromPlan } from "../intake/clause-derivation.js";
13
- import { evaluateLiteralAcceptanceFromPlan, runLiteralAcceptanceCommands, } from "../literal-acceptance/index.js";
12
+ import { emitAcceptanceStampFromPlan, MISSING_AMBIGUITY_ATTESTATION_CAUSE, stampedAmbiguityAttestationError, } from "../intake/clause-derivation.js";
13
+ import { appendLiteralAcceptanceAdvisory, evaluateLiteralAcceptanceFromPlan, isNoopRefusalReason, runLiteralAcceptanceCommands, stripLiteralAcceptanceAdvisory, } from "../literal-acceptance/index.js";
14
14
  import { ENV_RUN_SUMMARY_PATH, RunSummaryEmitter, } from "../run-summary/index.js";
15
15
  import { maybeBankOnAcPass } from "../session/ac-pass-banking.js";
16
+ import { resolveAcReuse, resolveScopeIdForAcReuse, snapshotFromReuseFields, } from "../session/ac-pass-reuse.js";
17
+ import { gitHead } from "../session/git.js";
18
+ import { hashProductState } from "../session/product-state-hash.js";
19
+ import { resolveVerifyAcSessionId, writeVerifyAcSessionCache, } from "../session/verify-ac-session-cache.js";
16
20
  import { formatClauseWalkMessage, walkAcceptanceClauses, } from "../verify-ac/clauses.js";
17
21
  import { emitVerifyAcAttempts, evaluateProductOracleIntegrity, mergeOracleVerdict, } from "../verify-ac/evaluate.js";
18
22
  import { readPlanAcceptance, validatePlanAcceptance } from "./acceptance.js";
19
- import { formatSoftEmptyMessage, isEmptyAcResolution, projectHasSuiteFloor, } from "./empty-resolution.js";
23
+ import { clauseWalkBlocks, formatAcceptanceVerdict, resolveAcceptanceVerdict, } from "./acceptance-resolver.js";
24
+ import { formatSoftEmptyMessage, formatTranscriptEmptyMessage, isEmptyAcResolution, projectHasSuiteFloor, } from "./empty-resolution.js";
20
25
  function asRecord(value) {
21
26
  if (typeof value === "object" && value !== null && !Array.isArray(value)) {
22
27
  return value;
23
28
  }
24
29
  return null;
25
30
  }
31
+ function tryReuseVerifyAc(plan, acceptance, options, projectRoot) {
32
+ const mode = options.reuseMode ?? "auto";
33
+ if (mode === "never")
34
+ return null;
35
+ const reuse = resolveAcReuse({
36
+ projectRoot,
37
+ plan,
38
+ scopeId: options.bankScopeId,
39
+ sessionId: options.sessionId,
40
+ env: options.env,
41
+ productPaths: options.productPaths,
42
+ allowCache: mode === "auto",
43
+ allowBank: true,
44
+ });
45
+ if (reuse.kind === "miss")
46
+ return null;
47
+ if (reuse.kind === "cache") {
48
+ const snap = reuse.cache.snapshot;
49
+ const cachedAcceptance = readPlanAcceptance({ acceptance: snap.acceptance });
50
+ return {
51
+ ok: snap.ok,
52
+ code: snap.code,
53
+ message: options.quiet
54
+ ? ""
55
+ : snap.message.includes("served_from=")
56
+ ? snap.message
57
+ : `${snap.message} served_from=cache`,
58
+ commands: snap.commands,
59
+ runs: snap.runs,
60
+ rejected: snap.rejected,
61
+ sourceRung: acceptance.source_rung,
62
+ noneStated: acceptance.none_stated,
63
+ acceptance: cachedAcceptance.commands.length > 0 ? cachedAcceptance : acceptance,
64
+ resolution: "verified-pass",
65
+ resolvedCommandCount: snap.resolvedCommandCount,
66
+ servedFrom: "cache",
67
+ };
68
+ }
69
+ const commandCount = acceptance.commands.length;
70
+ if (commandCount === 0)
71
+ return null;
72
+ return {
73
+ ok: true,
74
+ code: 0,
75
+ message: options.quiet
76
+ ? ""
77
+ : `verify:ac passed (#3284) served_from=bank [rung=${acceptance.source_rung}]`,
78
+ commands: acceptance.commands.map((c) => ({
79
+ command: c.command,
80
+ cwd: c.cwd ?? null,
81
+ expectedStdout: c.expectedStdout ?? null,
82
+ expectedExitCode: c.expectedExitCode ?? 0,
83
+ source: "explicit",
84
+ sourceSpan: "plan.acceptance.commands",
85
+ })),
86
+ runs: [],
87
+ sourceRung: acceptance.source_rung,
88
+ noneStated: acceptance.none_stated,
89
+ acceptance,
90
+ resolution: "verified-pass",
91
+ resolvedCommandCount: commandCount,
92
+ servedFrom: "bank",
93
+ };
94
+ }
95
+ function persistVerifyAcSessionCache(result, options, projectRoot, plan) {
96
+ if (!result.ok || result.resolution !== "verified-pass")
97
+ return;
98
+ const sessionId = resolveVerifyAcSessionId(options.env, options.sessionId);
99
+ const resolvedScope = resolveScopeIdForAcReuse(plan, options.bankScopeId);
100
+ if (sessionId === null || resolvedScope === null)
101
+ return;
102
+ const hashed = hashProductState({
103
+ projectRoot,
104
+ plan,
105
+ productPaths: options.productPaths,
106
+ });
107
+ if (!hashed.complete)
108
+ return;
109
+ try {
110
+ writeVerifyAcSessionCache({
111
+ projectRoot,
112
+ sessionId,
113
+ scopeId: resolvedScope,
114
+ productStateHash: hashed.digest,
115
+ snapshot: snapshotFromReuseFields({
116
+ ok: result.ok,
117
+ code: result.code === 2 ? 2 : result.code === 1 ? 1 : 0,
118
+ message: result.message,
119
+ commands: result.commands,
120
+ runs: result.runs,
121
+ rejected: result.rejected,
122
+ sourceRung: result.sourceRung,
123
+ noneStated: result.noneStated,
124
+ acceptance: result.acceptance,
125
+ resolution: result.resolution,
126
+ resolvedCommandCount: result.resolvedCommandCount,
127
+ }),
128
+ });
129
+ }
130
+ catch {
131
+ // fail-open: missing cache must not fail a green run
132
+ }
133
+ }
26
134
  /**
27
135
  * Evaluate product AC from an in-memory plan.
28
136
  */
@@ -31,16 +139,38 @@ export function evaluateVerifyAcFromPlan(plan, options = {}) {
31
139
  const optionsWithScope = {
32
140
  ...options,
33
141
  oracleScopeKey: options.oracleScopeKey?.trim() || planId || null,
142
+ bankScopeId: options.bankScopeId?.trim() || planId || options.bankScopeId,
34
143
  observedAcceptance: options.observedAcceptance !== undefined ? options.observedAcceptance : plan.acceptance,
35
144
  };
36
145
  const acceptance = readPlanAcceptance(plan);
37
146
  const schemaErrors = validatePlanAcceptance(plan.acceptance ?? acceptance);
38
147
  // Only hard-fail schema when an explicit plan.acceptance object exists.
39
148
  if (plan.acceptance !== undefined && schemaErrors.length > 0) {
149
+ const noop = schemaErrors.some((error) => isNoopRefusalReason(error));
150
+ return applyOracle({
151
+ ok: false,
152
+ code: noop ? 1 : 2,
153
+ message: noop
154
+ ? `verify:ac rejected-noop (#3396): ${schemaErrors.join("; ")}`
155
+ : `verify:ac config error (#3284): ${schemaErrors.join("; ")}`,
156
+ commands: [],
157
+ runs: [],
158
+ sourceRung: acceptance.source_rung,
159
+ noneStated: acceptance.none_stated,
160
+ acceptance,
161
+ resolution: noop ? "rejected-noop" : "config",
162
+ resolvedCommandCount: 0,
163
+ }, optionsWithScope, plan);
164
+ }
165
+ const projectRoot = resolve(optionsWithScope.projectRoot ?? process.cwd());
166
+ const attestationError = stampedAmbiguityAttestationError(optionsWithScope.observedAcceptance !== undefined
167
+ ? optionsWithScope.observedAcceptance
168
+ : plan.acceptance);
169
+ if (attestationError !== null) {
40
170
  return applyOracle({
41
171
  ok: false,
42
172
  code: 2,
43
- message: `verify:ac config error (#3284): ${schemaErrors.join("; ")}`,
173
+ message: optionsWithScope.quiet === true ? "" : attestationError.message,
44
174
  commands: [],
45
175
  runs: [],
46
176
  sourceRung: acceptance.source_rung,
@@ -48,9 +178,13 @@ export function evaluateVerifyAcFromPlan(plan, options = {}) {
48
178
  acceptance,
49
179
  resolution: "config",
50
180
  resolvedCommandCount: 0,
51
- }, optionsWithScope);
181
+ cause: attestationError.cause ?? MISSING_AMBIGUITY_ATTESTATION_CAUSE,
182
+ }, optionsWithScope, plan);
183
+ }
184
+ const reused = tryReuseVerifyAc(plan, acceptance, optionsWithScope, projectRoot);
185
+ if (reused !== null) {
186
+ return applyOracle(reused, optionsWithScope, plan);
52
187
  }
53
- const projectRoot = resolve(optionsWithScope.projectRoot ?? process.cwd());
54
188
  // Prefer shared literal-acceptance path so safety / promotion rules stay one place.
55
189
  // Empty plan.acceptance.commands still consults the #3267 rejected ledger
56
190
  // (Greptile P1: rejected stated AC must never soft-pass).
@@ -66,12 +200,12 @@ export function evaluateVerifyAcFromPlan(plan, options = {}) {
66
200
  (optionsWithScope.checkIntegrated === true ? false : undefined),
67
201
  quiet: optionsWithScope.quiet,
68
202
  });
69
- // When literal path had nothing executable but plan.acceptance has derived commands,
70
- // run them directly with source=explicit semantics.
71
- if (base.ok &&
72
- base.runs.length === 0 &&
73
- acceptance.commands.length > 0 &&
74
- (acceptance.source_rung === "derived" || acceptance.source_rung === "project_floor")) {
203
+ // When the literal ledger produced no runs, execute non-empty plan.acceptance.commands
204
+ // as source=explicit. The documented key is plan.acceptance.commands (#3284 / #3449);
205
+ // the #3267 ledger is a parallel store and can be empty while stated commands exist.
206
+ // Stated was previously excluded, so rung=stated + empty ledger printed "nothing to run".
207
+ // Do not override a blocking rejected ledger or a config error.
208
+ if (shouldRunPlanAcceptanceDirectly(base, acceptance)) {
75
209
  const runner = optionsWithScope.runner;
76
210
  const direct = runLiteralAcceptanceCommands(acceptance.commands.map((c) => ({
77
211
  command: c.command,
@@ -85,7 +219,17 @@ export function evaluateVerifyAcFromPlan(plan, options = {}) {
85
219
  runner,
86
220
  allowTaskStatement: optionsWithScope.allowTaskStatement,
87
221
  });
88
- return applyOracle(annotate(direct, acceptance, optionsWithScope.quiet), optionsWithScope);
222
+ // Carry the #3484 demotion forward: the direct path replaces `base`, and the
223
+ // advisory ledger must stay visible (reported, never blocking) (#3497).
224
+ const advisory = base.advisoryRejected ?? [];
225
+ const directWithAdvisory = {
226
+ ...direct,
227
+ advisoryRejected: advisory,
228
+ message: optionsWithScope.quiet === true
229
+ ? direct.message
230
+ : appendLiteralAcceptanceAdvisory(direct.message, advisory),
231
+ };
232
+ return applyOracle(annotate(directWithAdvisory, acceptance, optionsWithScope.quiet), optionsWithScope, plan);
89
233
  }
90
234
  // Check composition: mid-story unpromoted capture-only may soft-pass so the
91
235
  // framework graph is not deadlocked before agents promote peers.
@@ -94,7 +238,7 @@ export function evaluateVerifyAcFromPlan(plan, options = {}) {
94
238
  if (optionsWithScope.checkIntegrated === true && !base.ok && base.runs.length === 0) {
95
239
  const hasRejected = (base.rejected?.length ?? 0) > 0;
96
240
  if (hasRejected) {
97
- return applyOracle(annotate(base, acceptance, optionsWithScope.quiet), optionsWithScope);
241
+ return applyOracle(annotate(base, acceptance, optionsWithScope.quiet), optionsWithScope, plan);
98
242
  }
99
243
  const unpromoted = /capture-only|task_statement|no matching agent-promoted/i.test(base.message) ||
100
244
  (base.commands.length > 0 && base.commands.every((c) => c.source === "task_statement"));
@@ -122,10 +266,21 @@ export function evaluateVerifyAcFromPlan(plan, options = {}) {
122
266
  rejectedCount: base.rejected?.length ?? 0,
123
267
  }),
124
268
  resolvedCommandCount: base.commands.length,
125
- }, optionsWithScope);
269
+ }, optionsWithScope, plan);
126
270
  }
127
271
  }
128
- return applyOracle(annotate(base, acceptance, optionsWithScope.quiet), optionsWithScope);
272
+ return applyOracle(annotate(base, acceptance, optionsWithScope.quiet), optionsWithScope, plan);
273
+ }
274
+ function shouldRunPlanAcceptanceDirectly(base, acceptance) {
275
+ if (acceptance.commands.length === 0)
276
+ return false;
277
+ if (base.runs.length > 0)
278
+ return false;
279
+ if (base.code === 2)
280
+ return false;
281
+ if ((base.rejected?.length ?? 0) > 0)
282
+ return false;
283
+ return true;
129
284
  }
130
285
  function classifyResolution(input) {
131
286
  if (input.resolution !== undefined) {
@@ -158,6 +313,17 @@ function applyEmptyFloorPolicy(result, options) {
158
313
  }
159
314
  const projectRoot = resolve(options.projectRoot ?? process.cwd());
160
315
  const suiteFloor = options.hasSuiteFloor ?? projectHasSuiteFloor(projectRoot);
316
+ const skippedPrompts = result.transcriptPromptSkipped ?? 0;
317
+ if (suiteFloor && skippedPrompts > 0) {
318
+ return {
319
+ ...result,
320
+ ok: false,
321
+ code: 1,
322
+ message: options.quiet === true ? "" : formatTranscriptEmptyMessage(result.acceptance),
323
+ resolution: "fail",
324
+ resolvedCommandCount: 0,
325
+ };
326
+ }
161
327
  if (suiteFloor) {
162
328
  return {
163
329
  ...result,
@@ -185,6 +351,8 @@ function acceptanceOutcomeOf(result) {
185
351
  return "fail";
186
352
  if (result.resolution === "config")
187
353
  return "config-error";
354
+ if (result.resolution === "rejected-noop")
355
+ return "rejected-noop";
188
356
  return "soft-missing";
189
357
  }
190
358
  function emitAcceptanceObservedStamp(options, projectRoot) {
@@ -208,9 +376,9 @@ function emitAcceptanceOutcome(result, options, projectRoot) {
208
376
  try {
209
377
  const emitter = new RunSummaryEmitter({
210
378
  projectRoot,
211
- sessionId: (typeof options.env.DEFT_SESSION_ID === "string" && options.env.DEFT_SESSION_ID.trim()) ||
212
- "verify-ac",
379
+ sessionId: options.sessionId,
213
380
  env: options.env,
381
+ component: "verify-ac",
214
382
  });
215
383
  emitter.emitAcceptance({
216
384
  resolved_command_count: result.resolvedCommandCount,
@@ -222,6 +390,9 @@ function emitAcceptanceOutcome(result, options, projectRoot) {
222
390
  id: row.id,
223
391
  outcome: row.outcome,
224
392
  })),
393
+ served_from: result.servedFrom ?? "executed",
394
+ ...(result.cause !== undefined ? { cause: result.cause } : {}),
395
+ miss_reason: (result.servedFrom ?? "executed") === "executed" ? result.missReason : undefined,
225
396
  });
226
397
  }
227
398
  catch {
@@ -239,8 +410,14 @@ function emitAcceptanceTelemetry(result, options, projectRoot) {
239
410
  */
240
411
  export function emitVerifyAcTerminalOutcome(input) {
241
412
  emitAcceptanceOutcome({
242
- ok: input.outcome !== "config-error" && input.outcome !== "fail",
243
- code: input.outcome === "config-error" ? 2 : input.outcome === "fail" ? 1 : 0,
413
+ ok: input.outcome !== "config-error" &&
414
+ input.outcome !== "fail" &&
415
+ input.outcome !== "rejected-noop",
416
+ code: input.outcome === "config-error"
417
+ ? 2
418
+ : input.outcome === "fail" || input.outcome === "rejected-noop"
419
+ ? 1
420
+ : 0,
244
421
  message: "",
245
422
  commands: [],
246
423
  runs: [],
@@ -257,11 +434,13 @@ export function emitVerifyAcTerminalOutcome(input) {
257
434
  ? "skipped"
258
435
  : input.outcome === "fail"
259
436
  ? "fail"
260
- : input.outcome === "soft_empty"
261
- ? "soft_empty"
262
- : input.outcome === "verified-pass"
263
- ? "verified-pass"
264
- : "empty-pass",
437
+ : input.outcome === "rejected-noop"
438
+ ? "rejected-noop"
439
+ : input.outcome === "soft_empty"
440
+ ? "soft_empty"
441
+ : input.outcome === "verified-pass"
442
+ ? "verified-pass"
443
+ : "empty-pass",
265
444
  resolvedCommandCount: 0,
266
445
  }, { projectRoot: input.projectRoot, env: input.env }, resolve(input.projectRoot));
267
446
  }
@@ -273,7 +452,16 @@ function applyClauseWalk(result, options) {
273
452
  const projectRoot = resolve(options.projectRoot ?? process.cwd());
274
453
  const report = walkAcceptanceClauses(clauses, projectRoot);
275
454
  const message = options.quiet ? result.message : formatClauseWalkMessage(report, result.message);
276
- const ok = result.ok && report.ok;
455
+ // #3497: a clause the static walk cannot decide is evidence of nothing. It blocks
456
+ // only when nothing else verified the product; a green executable acceptance run
457
+ // already is the product-first oracle. Failed clauses still block unconditionally.
458
+ const blocked = clauseWalkBlocks({
459
+ failed: report.failed.length,
460
+ verified: report.verified.length,
461
+ walked: report.clauses.length,
462
+ hasGreenExecutableRun: result.ok && result.runs.length > 0 && result.runs.every((run) => run.ok),
463
+ });
464
+ const ok = result.ok && !blocked;
277
465
  return {
278
466
  ...result,
279
467
  ok,
@@ -288,9 +476,49 @@ function applyClauseWalk(result, options) {
288
476
  clauseWalked: true,
289
477
  };
290
478
  }
291
- function applyOracle(result, options) {
479
+ function applyRejectedNoop(result) {
480
+ if (result.resolution === "rejected-noop") {
481
+ return result;
482
+ }
483
+ const rejected = result.rejected ?? [];
484
+ const fromLedger = rejected.some((row) => isNoopRefusalReason(row.reason));
485
+ const fromRuns = result.runs.some((row) => !row.ok && isNoopRefusalReason(row.detail.replace(/^refused:\s*/i, "")));
486
+ // #3484 / #3497: the advisory block quotes refusal reasons that were deliberately
487
+ // demoted because the plan states structured acceptance commands. Sniffing the
488
+ // rendered message resurrected them as a blocking no-op verdict — verify:ac
489
+ // refused while its own output said "do NOT block". Read the blocking ledgers,
490
+ // and inspect only the non-advisory part of the message.
491
+ const fromMessage = isNoopRefusalReason(stripLiteralAcceptanceAdvisory(result.message));
492
+ if (!fromLedger && !fromRuns && !fromMessage) {
493
+ return result;
494
+ }
495
+ return {
496
+ ...result,
497
+ ok: false,
498
+ code: result.code === 2 ? 2 : 1,
499
+ resolution: "rejected-noop",
500
+ };
501
+ }
502
+ /**
503
+ * Make the rendered message agree with the verdict (#3497).
504
+ *
505
+ * `annotate` stamps "verify:ac passed" from the sub-gate result, but later stages
506
+ * (clause walk, no-op ledger, oracle integrity) can still flip `ok`. The old output
507
+ * left the stale "passed" lead in place, so scope:complete printed four passing lines
508
+ * and then refused. Re-label the lead and name the deciding predicate.
509
+ */
510
+ function labelVerdict(result) {
511
+ const verdict = resolveAcceptanceVerdict(result);
512
+ if (verdict.ok) {
513
+ return result.message;
514
+ }
515
+ const relabelled = result.message.replace(/verify:ac passed \(#3284\)/g, "verify:ac FAILED (#3284)");
516
+ const line = formatAcceptanceVerdict(verdict);
517
+ return relabelled.length > 0 ? `${relabelled}\n${line}` : line;
518
+ }
519
+ function applyOracle(result, options, plan = {}) {
292
520
  const projectRoot = resolve(options.projectRoot ?? process.cwd());
293
- const walked = applyClauseWalk(result, options);
521
+ const walked = applyClauseWalk(applyRejectedNoop(result), options);
294
522
  const gated = walked.clauseWalked === true ? walked : applyEmptyFloorPolicy(walked, options);
295
523
  // Emit/read disk only when the caller supplied env (CLI passes process.env).
296
524
  // Tests stay isolated unless they opt in with env or runSummaryText.
@@ -310,14 +538,40 @@ function applyOracle(result, options) {
310
538
  env: options.env,
311
539
  });
312
540
  next = mergeOracleVerdict(gated, verdict);
313
- if (!verdict.ok && next.resolution !== "soft_empty" && next.resolution !== "config") {
541
+ if (!verdict.ok &&
542
+ next.resolution !== "soft_empty" &&
543
+ next.resolution !== "config" &&
544
+ next.resolution !== "rejected-noop") {
314
545
  next = { ...next, resolution: "fail" };
315
546
  }
316
547
  }
548
+ const servedFrom = next.servedFrom ?? "executed";
549
+ let missReason = next.missReason;
550
+ if (servedFrom === "executed" && (missReason === undefined || missReason.length === 0)) {
551
+ const reuse = resolveAcReuse({
552
+ projectRoot,
553
+ plan,
554
+ scopeId: options.bankScopeId,
555
+ sessionId: options.sessionId,
556
+ env: options.env,
557
+ productPaths: options.productPaths,
558
+ allowCache: (options.reuseMode ?? "auto") === "auto",
559
+ allowBank: true,
560
+ });
561
+ if (reuse.kind === "miss")
562
+ missReason = reuse.reason;
563
+ }
564
+ const stamped = {
565
+ ...next,
566
+ message: options.quiet === true ? next.message : labelVerdict(next),
567
+ servedFrom,
568
+ missReason: servedFrom === "executed" ? missReason : undefined,
569
+ };
570
+ persistVerifyAcSessionCache(stamped, options, projectRoot, plan);
317
571
  if (options.skipAcceptanceEmit !== true) {
318
- emitAcceptanceTelemetry(next, options, projectRoot);
572
+ emitAcceptanceTelemetry(stamped, options, projectRoot);
319
573
  }
320
- return next;
574
+ return stamped;
321
575
  }
322
576
  function annotate(result, acceptance, quiet) {
323
577
  const prefix = result.ok
@@ -353,6 +607,7 @@ function annotate(result, acceptance, quiet) {
353
607
  rejectedCount: result.rejected?.length ?? 0,
354
608
  }),
355
609
  resolvedCommandCount: result.runs.length > 0 ? result.runs.length : commandCount,
610
+ servedFrom: "executed",
356
611
  };
357
612
  }
358
613
  /**
@@ -417,14 +672,14 @@ export function resolveOracleScopeKey(plan, xbriefPath, projectRoot) {
417
672
  return rel;
418
673
  }
419
674
  /**
420
- * After executable AC pass, FINALIZE the banking checkpoint (#3285).
421
- * Soft/advisory passes with zero runs do not bank. Fail-open on ledger errors.
675
+ * After verified-pass, FINALIZE the banking checkpoint (#3285 / #3558).
676
+ * Soft/advisory empty-pass still skips. Ledger I/O failures fail closed.
422
677
  */
423
678
  function maybeAttachAcPassBank(result, plan, xbriefPath, options) {
424
679
  if (options.bankOnPass === false) {
425
680
  return result;
426
681
  }
427
- if (!result.ok || result.runs.length === 0) {
682
+ if (!result.ok || result.resolution !== "verified-pass") {
428
683
  return result;
429
684
  }
430
685
  const projectRoot = resolve(options.projectRoot ?? process.cwd());
@@ -435,11 +690,20 @@ function maybeAttachAcPassBank(result, plan, xbriefPath, options) {
435
690
  .replace(/\.xbrief\.json$/i, "")
436
691
  .replace(/\.vbrief\.json$/i, "");
437
692
  try {
693
+ const hashed = hashProductState({
694
+ projectRoot,
695
+ plan,
696
+ productPaths: options.productPaths,
697
+ });
438
698
  const banked = maybeBankOnAcPass({
439
699
  projectRoot,
440
700
  scopeId,
441
701
  executableRuns: result.runs.length,
702
+ verifiedPass: true,
442
703
  quiet: options.quiet,
704
+ productStateHash: hashed.complete ? hashed.digest : null,
705
+ environ: options.env,
706
+ headSha: gitHead(projectRoot).head,
443
707
  });
444
708
  if (options.quiet || banked.notes.length === 0) {
445
709
  return result;
@@ -4,7 +4,9 @@
4
4
  * acceptance.commands schema, verify:ac evaluation, check-mode composition
5
5
  * (AC-first, hygiene advisory under pressure, rapid=AC-only).
6
6
  */
7
+ export type { AcServedFrom } from "../session/verify-ac-session-cache.js";
7
8
  export { attachPlanAcceptance, buildAcceptanceFromIntakeCapture, readPlanAcceptance, stampAcceptanceFromLiteralCapture, validatePlanAcceptance, } from "./acceptance.js";
9
+ export { type AcceptanceGateProfileOptions, type AcceptancePredicate, type AcceptanceReaderProfile, type AcceptanceReading, type AcceptanceVerdict, clauseWalkBlocks, formatAcceptanceVerdict, resolveAcceptanceGateProfile, resolveAcceptanceVerdict, resolvedAcceptanceCommandCount, } from "./acceptance-resolver.js";
8
10
  export { applyProductFirstGateMode, isHygieneGate, isProductAcGate, type ProductFirstCheckModeResolution, type ResolveProductFirstCheckModeInput, resolveProductFirstCheckMode, } from "./check-mode.js";
9
11
  export { EMPTY_AC_CAUSE, EMPTY_AC_OUTCOME, EMPTY_AC_REMEDY, formatSoftEmptyMessage, isEmptyAcResolution, isSoftEmptyAcText, projectHasSuiteFloor, type VerifyAcResolution, } from "./empty-resolution.js";
10
12
  export { type EvaluateVerifyAcOptions, emitVerifyAcTerminalOutcome, evaluateVerifyAcFromPath, evaluateVerifyAcFromPlan, isVerifyAcRequiredAtCeremonyDepth, resolveOracleScopeKey, type VerifyAcResult, } from "./evaluate.js";
@@ -5,6 +5,7 @@
5
5
  * (AC-first, hygiene advisory under pressure, rapid=AC-only).
6
6
  */
7
7
  export { attachPlanAcceptance, buildAcceptanceFromIntakeCapture, readPlanAcceptance, stampAcceptanceFromLiteralCapture, validatePlanAcceptance, } from "./acceptance.js";
8
+ export { clauseWalkBlocks, formatAcceptanceVerdict, resolveAcceptanceGateProfile, resolveAcceptanceVerdict, resolvedAcceptanceCommandCount, } from "./acceptance-resolver.js";
8
9
  export { applyProductFirstGateMode, isHygieneGate, isProductAcGate, resolveProductFirstCheckMode, } from "./check-mode.js";
9
10
  export { EMPTY_AC_CAUSE, EMPTY_AC_OUTCOME, EMPTY_AC_REMEDY, formatSoftEmptyMessage, isEmptyAcResolution, isSoftEmptyAcText, projectHasSuiteFloor, } from "./empty-resolution.js";
10
11
  export { emitVerifyAcTerminalOutcome, evaluateVerifyAcFromPath, evaluateVerifyAcFromPlan, isVerifyAcRequiredAtCeremonyDepth, resolveOracleScopeKey, } from "./evaluate.js";
@@ -1,7 +1,104 @@
1
+ import { lstatSync } from "node:fs";
2
+ /**
3
+ * Shared "not product source" core (#3487) plus the coverage artifacts only the
4
+ * release archive names. Scratch and agent worktrees are never shippable
5
+ * framework content (#2953). The archive set is git-tracked files (#3490); this
6
+ * denylist is defence in depth, including for a tracked path under a core name.
7
+ *
8
+ * Callers may still widen this per run via `extraExcludes` / `--exclude-extra`.
9
+ */
1
10
  export declare const DEFAULT_EXCLUDES: Set<string>;
2
11
  export declare const DEFAULT_EXCLUDED_PATH_PREFIXES: readonly ["history/archive", "vbrief/completed", "vbrief/cancelled"];
12
+ /**
13
+ * Generated outputs that may be packed even when untracked. Empty by default:
14
+ * the release archive is a source distribution, so extra outputs must be named
15
+ * explicitly (#3490).
16
+ */
17
+ export declare const DEFAULT_GENERATED_ALLOWLIST: readonly string[];
3
18
  export declare const ARCHIVE_ROOT = "deft";
4
19
  export declare const CONTENT_PREFIX = "content/";
20
+ /** Raised when the resolved archive set contains an untracked surprise (#3490). */
21
+ export declare class UntrackedArchiveEntryError extends Error {
22
+ readonly paths: readonly string[];
23
+ constructor(paths: readonly string[]);
24
+ }
25
+ export type ArchiveSourceEntry = {
26
+ absPath: string | Buffer;
27
+ archiveRel: string;
28
+ archiveRelBytes: Buffer;
29
+ };
30
+ /** Private-use mark so archiver's string `name` can carry raw member bytes. */
31
+ export declare const ARCHIVE_BINARY_NAME_MARK = "\uF000";
32
+ export declare function flattenContentPrefixBytes(relBytes: Buffer): Buffer;
33
+ export declare function isValidUtf8Buffer(buf: Buffer): boolean;
34
+ export declare function archiveMemberBytes(archiveRelBytes: Buffer): Buffer;
35
+ /** Archiver `file()`/`append` name: UTF-8 text, or marked latin1 of raw bytes. */
36
+ export declare function archiverEntryName(memberBytes: Buffer): string;
37
+ /** Original `ls-files -z` segment bytes plus the display/skip string. */
38
+ export type GitLsFilesPath = {
39
+ readonly relPosix: string;
40
+ readonly bytes: Buffer;
41
+ };
42
+ export type ArchiveFsLookup = {
43
+ realpathSync: (path: string | Buffer, options?: {
44
+ encoding?: BufferEncoding | "buffer" | null;
45
+ }) => string | Buffer;
46
+ lstatSync: (path: string | Buffer) => ReturnType<typeof lstatSync>;
47
+ };
48
+ /** `-z` stdout is a NUL-separated byte stream; never UTF-8-decode it whole. */
49
+ export declare const GIT_LS_FILES_Z_ENCODING: null;
50
+ export type GitLsFilesZSpawn = (command: string, args: readonly string[], options: {
51
+ encoding: null;
52
+ timeout?: number;
53
+ maxBuffer?: number;
54
+ stdio?: readonly ["ignore", "pipe", "pipe"];
55
+ }) => {
56
+ status: number | null;
57
+ stdout?: Buffer | string | null;
58
+ stderr?: Buffer | string | null;
59
+ error?: Error | null;
60
+ signal?: NodeJS.Signals | null;
61
+ };
62
+ /** Decode one `ls-files -z` segment; keep non-UTF-8 bytes as latin1. */
63
+ export declare function decodeGitLsFilesPath(segment: Buffer): string;
64
+ /** Split a raw `git ls-files -z` Buffer on 0x00, keeping original path bytes. */
65
+ export declare function splitGitLsFilesZRecords(stdout: Buffer): GitLsFilesPath[];
66
+ /** Split a raw `git ls-files -z` Buffer on 0x00, then decode each path. */
67
+ export declare function splitGitLsFilesZ(stdout: Buffer): string[];
68
+ /**
69
+ * Return `git ls-files -z` paths with original bytes. Fail closed when git
70
+ * cannot enumerate tracked files -- a walk would pack host-local untracked
71
+ * state (#3490).
72
+ */
73
+ export declare function listGitTrackedPathRecords(root: string, spawn?: GitLsFilesZSpawn): GitLsFilesPath[];
74
+ /** Return `git ls-files -z` paths in POSIX form. */
75
+ export declare function listGitTrackedFiles(root: string, spawn?: GitLsFilesZSpawn): string[];
76
+ /**
77
+ * Fail closed when any resolved archive path is untracked and not on the
78
+ * generated-output allowlist (#3490).
79
+ */
80
+ export declare function assertArchiveEntriesTrackedOrGenerated(root: string, rels: readonly string[], generatedAllowlist?: readonly string[], spawn?: GitLsFilesZSpawn): void;
81
+ export type ResolveArchiveEntriesOptions = {
82
+ readonly extraExcludes?: readonly string[];
83
+ readonly excludedPrefixes?: readonly string[];
84
+ readonly generatedAllowlist?: readonly string[];
85
+ readonly spawn?: GitLsFilesZSpawn;
86
+ readonly fs?: ArchiveFsLookup;
87
+ };
88
+ /** Join canonical root bytes with original git path bytes; convert POSIX `/` to OS sep. */
89
+ export declare function joinRootAndRelBytes(rootBytes: Buffer, relBytes: Buffer): Buffer;
90
+ /**
91
+ * String path when the `-z` segment is valid UTF-8; otherwise a Buffer that
92
+ * keeps the original filename bytes for fs lookup (#3490 residual).
93
+ */
94
+ export declare function fsLookupPath(root: string, relPosix: string, bytes: Buffer, rootBytes?: Buffer): string | Buffer | null;
95
+ /** Resolve a POSIX rel path under root, or null if it escapes (#3490 review). */
96
+ export declare function containedAbsPath(root: string, relPosix: string): string | null;
97
+ /**
98
+ * Derive the archive file set from git-tracked paths plus an explicit
99
+ * generated-output allowlist. The basename denylist remains defence in depth.
100
+ */
101
+ export declare function resolveArchiveEntries(root: string, options?: ResolveArchiveEntriesOptions): ArchiveSourceEntry[];
5
102
  export declare function iterSourceFiles(root: string, excludes?: ReadonlySet<string>, excludedPrefixes?: readonly string[]): Array<{
6
103
  absPath: string;
7
104
  archiveRel: string;
@@ -16,8 +113,12 @@ export type BuildProgress = {
16
113
  };
17
114
  export type BuildArchiveOptions = {
18
115
  readonly extraExcludes?: readonly string[];
116
+ /** Untracked generated outputs that may be packed (#3490). */
117
+ readonly generatedAllowlist?: readonly string[];
19
118
  /** Progress sink; default silent so unit tests stay quiet (#2953). */
20
119
  readonly onProgress?: (p: BuildProgress) => void;
120
+ readonly spawn?: GitLsFilesZSpawn;
121
+ readonly fs?: ArchiveFsLookup;
21
122
  };
22
123
  /**
23
124
  * Emit human-readable stage progress for long release packaging runs (#2953).