@deftai/directive-core 0.100.0 → 0.102.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 (120) hide show
  1. package/dist/authz/classify.js +193 -27
  2. package/dist/authz/decompose-apply.d.ts +14 -0
  3. package/dist/authz/decompose-apply.js +93 -18
  4. package/dist/check/cached-orchestrator.d.ts +30 -5
  5. package/dist/check/cached-orchestrator.js +297 -10
  6. package/dist/check/cli-native-gates.d.ts +43 -0
  7. package/dist/check/cli-native-gates.js +84 -0
  8. package/dist/check/gate-lists.d.ts +10 -4
  9. package/dist/check/gate-lists.js +19 -5
  10. package/dist/check/index.d.ts +4 -2
  11. package/dist/check/index.js +3 -1
  12. package/dist/check/named-cause.d.ts +45 -0
  13. package/dist/check/named-cause.js +131 -0
  14. package/dist/check/orchestrator.js +6 -1
  15. package/dist/doctor/checks.d.ts +5 -6
  16. package/dist/doctor/checks.js +13 -56
  17. package/dist/doctor/help.d.ts +5 -0
  18. package/dist/doctor/help.js +31 -0
  19. package/dist/doctor/index.d.ts +2 -0
  20. package/dist/doctor/index.js +2 -0
  21. package/dist/doctor/main.js +58 -0
  22. package/dist/doctor/session-coda.d.ts +82 -0
  23. package/dist/doctor/session-coda.js +151 -0
  24. package/dist/doctor/types.d.ts +16 -0
  25. package/dist/eval/later-graduation.d.ts +39 -0
  26. package/dist/eval/later-graduation.js +91 -0
  27. package/dist/eval/report.d.ts +6 -0
  28. package/dist/eval/report.js +27 -8
  29. package/dist/index.d.ts +3 -0
  30. package/dist/index.js +3 -0
  31. package/dist/init-deposit/gitignore.js +2 -0
  32. package/dist/intake/issue-ingest.js +49 -0
  33. package/dist/policy/ac-pass-banking.d.ts +58 -0
  34. package/dist/policy/ac-pass-banking.js +150 -0
  35. package/dist/policy/ceremony-dial-escalation.d.ts +52 -0
  36. package/dist/policy/ceremony-dial-escalation.js +92 -0
  37. package/dist/policy/ceremony-dial.d.ts +32 -1
  38. package/dist/policy/ceremony-dial.js +128 -1
  39. package/dist/policy/check-resume.d.ts +9 -38
  40. package/dist/policy/check-resume.js +18 -156
  41. package/dist/policy/coverage-debt.d.ts +18 -37
  42. package/dist/policy/coverage-debt.js +38 -147
  43. package/dist/policy/index.d.ts +2 -1
  44. package/dist/policy/index.js +16 -2
  45. package/dist/preflight-cache/evaluate.d.ts +3 -0
  46. package/dist/preflight-cache/evaluate.js +3 -0
  47. package/dist/product-first-done-gate/acceptance.d.ts +25 -0
  48. package/dist/product-first-done-gate/acceptance.js +269 -0
  49. package/dist/product-first-done-gate/check-mode.d.ts +45 -0
  50. package/dist/product-first-done-gate/check-mode.js +148 -0
  51. package/dist/product-first-done-gate/empty-resolution.d.ts +26 -0
  52. package/dist/product-first-done-gate/empty-resolution.js +38 -0
  53. package/dist/product-first-done-gate/evaluate.d.ts +76 -0
  54. package/dist/product-first-done-gate/evaluate.js +411 -0
  55. package/dist/product-first-done-gate/index.d.ts +12 -0
  56. package/dist/product-first-done-gate/index.js +12 -0
  57. package/dist/product-first-done-gate/types.d.ts +67 -0
  58. package/dist/product-first-done-gate/types.js +54 -0
  59. package/dist/run-summary/emit.d.ts +66 -0
  60. package/dist/run-summary/emit.js +217 -0
  61. package/dist/run-summary/index.d.ts +5 -0
  62. package/dist/run-summary/index.js +5 -0
  63. package/dist/run-summary/path.d.ts +25 -0
  64. package/dist/run-summary/path.js +78 -0
  65. package/dist/run-summary/share.d.ts +25 -0
  66. package/dist/run-summary/share.js +106 -0
  67. package/dist/run-summary/types.d.ts +134 -0
  68. package/dist/run-summary/types.js +28 -0
  69. package/dist/scope/acceptance-activate-gate.d.ts +23 -0
  70. package/dist/scope/acceptance-activate-gate.js +70 -0
  71. package/dist/scope/acceptance-evidence.d.ts +34 -0
  72. package/dist/scope/acceptance-evidence.js +84 -10
  73. package/dist/scope/decompose.d.ts +5 -0
  74. package/dist/scope/decompose.js +11 -2
  75. package/dist/scope/index.d.ts +1 -0
  76. package/dist/scope/index.js +1 -0
  77. package/dist/scope/transition.js +5 -0
  78. package/dist/session/ac-pass-banking.d.ts +221 -0
  79. package/dist/session/ac-pass-banking.js +761 -0
  80. package/dist/session/deposit-sha.d.ts +49 -0
  81. package/dist/session/deposit-sha.js +121 -0
  82. package/dist/session/effort-budget.d.ts +6 -0
  83. package/dist/session/effort-budget.js +21 -3
  84. package/dist/session/index.d.ts +5 -1
  85. package/dist/session/index.js +5 -1
  86. package/dist/session/orientation-compression.d.ts +127 -0
  87. package/dist/session/orientation-compression.js +435 -0
  88. package/dist/session/orientation-state.d.ts +29 -0
  89. package/dist/session/orientation-state.js +85 -0
  90. package/dist/session/session-start.d.ts +31 -0
  91. package/dist/session/session-start.js +219 -22
  92. package/dist/session/toolchain-preflight.d.ts +79 -0
  93. package/dist/session/toolchain-preflight.js +211 -0
  94. package/dist/triage/bootstrap/gitignore.d.ts +1 -1
  95. package/dist/triage/bootstrap/gitignore.js +8 -2
  96. package/dist/triage/bootstrap/index.js +15 -3
  97. package/dist/triage/classify/index.d.ts +1 -0
  98. package/dist/triage/classify/index.js +2 -0
  99. package/dist/triage/classify/label-mirror.js +16 -0
  100. package/dist/triage/classify/mirror-discovery-tip.d.ts +95 -0
  101. package/dist/triage/classify/mirror-discovery-tip.js +234 -0
  102. package/dist/triage/reconcile/reconcile.js +28 -6
  103. package/dist/triage/summary/index.js +12 -4
  104. package/dist/triage/welcome/default-mode.js +16 -0
  105. package/dist/ts-check-lane/run-lane.js +21 -4
  106. package/dist/vbrief-validate/conformance.js +7 -0
  107. package/dist/verify-ac/clauses.d.ts +51 -0
  108. package/dist/verify-ac/clauses.js +490 -0
  109. package/dist/verify-ac/evaluate.d.ts +55 -0
  110. package/dist/verify-ac/evaluate.js +145 -0
  111. package/dist/verify-ac/flag.d.ts +35 -0
  112. package/dist/verify-ac/flag.js +104 -0
  113. package/dist/verify-ac/index.d.ts +10 -0
  114. package/dist/verify-ac/index.js +10 -0
  115. package/dist/vitest-runner/coverage-debt-teardown.js +16 -4
  116. package/package.json +15 -3
  117. package/dist/policy/coverage-check-resume-presets.d.ts +0 -46
  118. package/dist/policy/coverage-check-resume-presets.js +0 -228
  119. package/dist/session/coverage-check-resume-nudge.d.ts +0 -34
  120. package/dist/session/coverage-check-resume-nudge.js +0 -66
@@ -0,0 +1,76 @@
1
+ /**
2
+ * evaluate verify:ac — product-first acceptance gate (#3284).
3
+ *
4
+ * Runs plan.acceptance.commands (or #3267 literal ledger) via the shared
5
+ * literal-acceptance runner. Records source_rung in the result message.
6
+ * Project floor with empty commands is a soft pass only when a suite floor
7
+ * exists (suite gates own the floor inside full `task check`). With no suite
8
+ * floor, empty resolution is soft_empty — not a green run (#3334).
9
+ */
10
+ import { type EvaluateLiteralAcceptanceOptions, type LiteralAcceptanceGateResult } from "../literal-acceptance/index.js";
11
+ import { type ClauseWalkResult } from "../verify-ac/clauses.js";
12
+ import { type VerifyAcResolution } from "./empty-resolution.js";
13
+ import type { AcSourceRung, PlanAcceptance } from "./types.js";
14
+ export interface VerifyAcResult extends LiteralAcceptanceGateResult {
15
+ readonly sourceRung: AcSourceRung;
16
+ readonly noneStated: boolean;
17
+ readonly acceptance: PlanAcceptance;
18
+ readonly resolution: VerifyAcResolution;
19
+ readonly resolvedCommandCount: number;
20
+ readonly clauseOutcomes?: readonly ClauseWalkResult[];
21
+ readonly clauseWalked?: boolean;
22
+ }
23
+ export interface EvaluateVerifyAcOptions extends EvaluateLiteralAcceptanceOptions {
24
+ /**
25
+ * When true, missing xBRIEF / no active scope is exit 0 (check composition).
26
+ * Default false for standalone done-gate use.
27
+ */
28
+ readonly softMissingXbrief?: boolean;
29
+ /**
30
+ * Check-graph mode (#3284): used by `task check` via `--soft-missing-xbrief`.
31
+ * - Unpromoted capture-only (task_statement) commands do not fail the graph
32
+ * (promotion remains a done-gate / scope:complete concern via verify:ac standalone).
33
+ * - Executable command failures still fail closed (product-first).
34
+ * - Safety-rejected ledger still fails closed.
35
+ */
36
+ readonly checkIntegrated?: boolean;
37
+ /** Allow task_statement sources to execute (tests / explicit promote). */
38
+ readonly allowTaskStatement?: boolean;
39
+ /**
40
+ * When false, skip AC-pass banking after executable pass (#3285).
41
+ * Default true — first green executable AC banks a finalize checkpoint.
42
+ */
43
+ readonly bankOnPass?: boolean;
44
+ /** Optional scope id override for the bank ledger (default plan.id / path). */
45
+ readonly bankScopeId?: string | null;
46
+ /**
47
+ * Injected run-summary JSONL for product-oracle integrity (#3322).
48
+ * Undefined → read DEFT_RUN_SUMMARY_PATH / default dest; null → skip disk.
49
+ */
50
+ readonly runSummaryText?: string | null;
51
+ /** When false, skip #3322 oracle integrity. Default true. */
52
+ readonly applyOracleIntegrity?: boolean;
53
+ /** Env seam for run-summary dest resolution (#3322 / #3334). */
54
+ readonly env?: NodeJS.ProcessEnv;
55
+ /**
56
+ * Inject suite-floor detection (tests). Default: framework source has a
57
+ * suite floor; consumer projects do not (#3334).
58
+ */
59
+ readonly hasSuiteFloor?: boolean;
60
+ /**
61
+ * When true, skip the acceptance run-summary emit so the path helper can
62
+ * emit after the #3285 bank checkpoint.
63
+ */
64
+ readonly skipAcceptanceEmit?: boolean;
65
+ }
66
+ /**
67
+ * Evaluate product AC from an in-memory plan.
68
+ */
69
+ export declare function evaluateVerifyAcFromPlan(plan: Record<string, unknown>, options?: EvaluateVerifyAcOptions): VerifyAcResult;
70
+ /**
71
+ * Evaluate from xBRIEF path.
72
+ */
73
+ export declare function evaluateVerifyAcFromPath(xbriefPath: string, options?: EvaluateVerifyAcOptions): VerifyAcResult;
74
+ /** Pure: product AC is required at every ceremony depth (#3284 / #3267 / #3156). */
75
+ export declare function isVerifyAcRequiredAtCeremonyDepth(_depth: string | null | undefined): boolean;
76
+ //# sourceMappingURL=evaluate.d.ts.map
@@ -0,0 +1,411 @@
1
+ /**
2
+ * evaluate verify:ac — product-first acceptance gate (#3284).
3
+ *
4
+ * Runs plan.acceptance.commands (or #3267 literal ledger) via the shared
5
+ * literal-acceptance runner. Records source_rung in the result message.
6
+ * Project floor with empty commands is a soft pass only when a suite floor
7
+ * exists (suite gates own the floor inside full `task check`). With no suite
8
+ * floor, empty resolution is soft_empty — not a green run (#3334).
9
+ */
10
+ import { existsSync, readFileSync } from "node:fs";
11
+ import { basename, resolve } from "node:path";
12
+ import { evaluateLiteralAcceptanceFromPlan, runLiteralAcceptanceCommands, } from "../literal-acceptance/index.js";
13
+ import { ENV_RUN_SUMMARY_PATH, RunSummaryEmitter, } from "../run-summary/index.js";
14
+ import { maybeBankOnAcPass } from "../session/ac-pass-banking.js";
15
+ import { formatClauseWalkMessage, walkAcceptanceClauses, } from "../verify-ac/clauses.js";
16
+ import { emitVerifyAcAttempts, evaluateProductOracleIntegrity, mergeOracleVerdict, } from "../verify-ac/evaluate.js";
17
+ import { readPlanAcceptance, validatePlanAcceptance } from "./acceptance.js";
18
+ import { formatSoftEmptyMessage, isEmptyAcResolution, projectHasSuiteFloor, } from "./empty-resolution.js";
19
+ function asRecord(value) {
20
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
21
+ return value;
22
+ }
23
+ return null;
24
+ }
25
+ /**
26
+ * Evaluate product AC from an in-memory plan.
27
+ */
28
+ export function evaluateVerifyAcFromPlan(plan, options = {}) {
29
+ const acceptance = readPlanAcceptance(plan);
30
+ const schemaErrors = validatePlanAcceptance(plan.acceptance ?? acceptance);
31
+ // Only hard-fail schema when an explicit plan.acceptance object exists.
32
+ if (plan.acceptance !== undefined && schemaErrors.length > 0) {
33
+ return applyOracle({
34
+ ok: false,
35
+ code: 2,
36
+ message: `verify:ac config error (#3284): ${schemaErrors.join("; ")}`,
37
+ commands: [],
38
+ runs: [],
39
+ sourceRung: acceptance.source_rung,
40
+ noneStated: acceptance.none_stated,
41
+ acceptance,
42
+ resolution: "config",
43
+ resolvedCommandCount: 0,
44
+ }, options);
45
+ }
46
+ const projectRoot = resolve(options.projectRoot ?? process.cwd());
47
+ // Prefer shared literal-acceptance path so safety / promotion rules stay one place.
48
+ // Empty plan.acceptance.commands still consults the #3267 rejected ledger
49
+ // (Greptile P1: rejected stated AC must never soft-pass).
50
+ // For derived/floor commands already on plan.acceptance, inject as explicit metadata
51
+ // if the literal ledger is empty of executables.
52
+ const base = evaluateLiteralAcceptanceFromPlan(plan, {
53
+ projectRoot,
54
+ runner: options.runner,
55
+ // Check composition uses the stamped ledger only. Re-scanning issue prose
56
+ // during `task check` re-captures backtick `verify:ac` lines as rejected
57
+ // and deadlocks the graph (#3323 / #3284 check-integrated).
58
+ captureFromNarratives: options.captureFromNarratives ?? (options.checkIntegrated === true ? false : undefined),
59
+ quiet: options.quiet,
60
+ });
61
+ // When literal path had nothing executable but plan.acceptance has derived commands,
62
+ // run them directly with source=explicit semantics.
63
+ if (base.ok &&
64
+ base.runs.length === 0 &&
65
+ acceptance.commands.length > 0 &&
66
+ (acceptance.source_rung === "derived" || acceptance.source_rung === "project_floor")) {
67
+ const runner = options.runner;
68
+ const direct = runLiteralAcceptanceCommands(acceptance.commands.map((c) => ({
69
+ command: c.command,
70
+ cwd: c.cwd ?? null,
71
+ expectedStdout: c.expectedStdout ?? null,
72
+ expectedExitCode: c.expectedExitCode ?? 0,
73
+ source: "explicit",
74
+ sourceSpan: "plan.acceptance.commands",
75
+ })), { projectRoot, runner, allowTaskStatement: options.allowTaskStatement });
76
+ return applyOracle(annotate(direct, acceptance, options.quiet), options);
77
+ }
78
+ // Check composition: mid-story unpromoted capture-only may soft-pass so the
79
+ // framework graph is not deadlocked before agents promote peers.
80
+ // Greptile P1 #3284: safety-rejected stated commands NEVER soft-pass — they
81
+ // block product verification until a safe alternative is promoted.
82
+ if (options.checkIntegrated === true && !base.ok && base.runs.length === 0) {
83
+ const hasRejected = (base.rejected?.length ?? 0) > 0;
84
+ if (hasRejected) {
85
+ return applyOracle(annotate(base, acceptance, options.quiet), options);
86
+ }
87
+ const unpromoted = /capture-only|task_statement|no matching agent-promoted/i.test(base.message) ||
88
+ (base.commands.length > 0 && base.commands.every((c) => c.source === "task_statement"));
89
+ if (unpromoted || base.commands.length === 0) {
90
+ return applyOracle({
91
+ ok: true,
92
+ code: 0,
93
+ message: options.quiet
94
+ ? ""
95
+ : `verify:ac advisory (#3284 check-integrated): no executable AC peers yet ` +
96
+ `(capture-only / empty). Done-gate standalone verify:ac still requires promotion. ` +
97
+ `[rung=${acceptance.source_rung}]\n` +
98
+ base.message,
99
+ commands: base.commands,
100
+ runs: [],
101
+ rejected: base.rejected,
102
+ sourceRung: acceptance.source_rung,
103
+ noneStated: acceptance.none_stated,
104
+ acceptance,
105
+ resolution: classifyResolution({
106
+ ok: true,
107
+ code: 0,
108
+ runsLength: 0,
109
+ commandCount: base.commands.length,
110
+ rejectedCount: base.rejected?.length ?? 0,
111
+ }),
112
+ resolvedCommandCount: base.commands.length,
113
+ }, options);
114
+ }
115
+ }
116
+ return applyOracle(annotate(base, acceptance, options.quiet), options);
117
+ }
118
+ function classifyResolution(input) {
119
+ if (input.resolution !== undefined) {
120
+ return input.resolution;
121
+ }
122
+ if (input.code === 2) {
123
+ return "config";
124
+ }
125
+ if (!input.ok) {
126
+ return "fail";
127
+ }
128
+ if (input.runsLength > 0) {
129
+ return "verified-pass";
130
+ }
131
+ if (isEmptyAcResolution(input)) {
132
+ return "empty-pass";
133
+ }
134
+ return "empty-pass";
135
+ }
136
+ function applyEmptyFloorPolicy(result, options) {
137
+ if (!isEmptyAcResolution({
138
+ ok: result.ok,
139
+ code: result.code,
140
+ runsLength: result.runs.length,
141
+ commandCount: Math.max(result.commands.length, result.acceptance.commands.length),
142
+ rejectedCount: result.rejected?.length ?? 0,
143
+ resolution: result.resolution,
144
+ })) {
145
+ return result;
146
+ }
147
+ const projectRoot = resolve(options.projectRoot ?? process.cwd());
148
+ const suiteFloor = options.hasSuiteFloor ?? projectHasSuiteFloor(projectRoot);
149
+ if (suiteFloor) {
150
+ return {
151
+ ...result,
152
+ resolution: "empty-pass",
153
+ resolvedCommandCount: 0,
154
+ };
155
+ }
156
+ return {
157
+ ...result,
158
+ ok: false,
159
+ code: 1,
160
+ message: formatSoftEmptyMessage(result.acceptance),
161
+ resolution: "soft_empty",
162
+ resolvedCommandCount: 0,
163
+ };
164
+ }
165
+ function acceptanceOutcomeOf(result) {
166
+ if (result.resolution === "verified-pass")
167
+ return "verified-pass";
168
+ if (result.resolution === "empty-pass")
169
+ return "empty-pass";
170
+ if (result.resolution === "soft_empty")
171
+ return "soft_empty";
172
+ if (result.resolution === "fail")
173
+ return "fail";
174
+ return null;
175
+ }
176
+ function emitAcceptanceOutcome(result, options, projectRoot) {
177
+ if (options.env === undefined) {
178
+ return;
179
+ }
180
+ const dest = options.env[ENV_RUN_SUMMARY_PATH];
181
+ if (dest === undefined || dest.trim().length === 0) {
182
+ return;
183
+ }
184
+ const outcome = acceptanceOutcomeOf(result);
185
+ if (outcome === null) {
186
+ return;
187
+ }
188
+ try {
189
+ const emitter = new RunSummaryEmitter({
190
+ projectRoot,
191
+ sessionId: (typeof options.env.DEFT_SESSION_ID === "string" && options.env.DEFT_SESSION_ID.trim()) ||
192
+ "verify-ac",
193
+ env: options.env,
194
+ });
195
+ emitter.emitAcceptance({
196
+ resolved_command_count: result.resolvedCommandCount,
197
+ outcome,
198
+ source_rung: result.sourceRung,
199
+ none_stated: result.noneStated,
200
+ clause_count: result.clauseOutcomes?.length,
201
+ clause_outcomes: result.clauseOutcomes?.map((row) => ({
202
+ id: row.id,
203
+ outcome: row.outcome,
204
+ })),
205
+ });
206
+ }
207
+ catch {
208
+ // fail-open
209
+ }
210
+ }
211
+ function applyClauseWalk(result, options) {
212
+ const clauses = result.acceptance.clauses ?? [];
213
+ if (clauses.length === 0 || result.resolution === "config" || result.resolution === "skipped") {
214
+ return result;
215
+ }
216
+ const projectRoot = resolve(options.projectRoot ?? process.cwd());
217
+ const report = walkAcceptanceClauses(clauses, projectRoot);
218
+ const message = options.quiet ? result.message : formatClauseWalkMessage(report, result.message);
219
+ const ok = result.ok && report.ok;
220
+ return {
221
+ ...result,
222
+ ok,
223
+ code: ok ? result.code : result.code === 2 ? 2 : 1,
224
+ message,
225
+ resolution: ok
226
+ ? result.resolution === "empty-pass"
227
+ ? "verified-pass"
228
+ : result.resolution
229
+ : "fail",
230
+ clauseOutcomes: report.clauses,
231
+ clauseWalked: true,
232
+ };
233
+ }
234
+ function applyOracle(result, options) {
235
+ const projectRoot = resolve(options.projectRoot ?? process.cwd());
236
+ const walked = applyClauseWalk(result, options);
237
+ const gated = walked.clauseWalked === true ? walked : applyEmptyFloorPolicy(walked, options);
238
+ // Emit/read disk only when the caller supplied env (CLI passes process.env).
239
+ // Tests stay isolated unless they opt in with env or runSummaryText.
240
+ if (options.env !== undefined) {
241
+ emitVerifyAcAttempts({
242
+ projectRoot,
243
+ runs: gated.runs,
244
+ env: options.env,
245
+ });
246
+ }
247
+ let next = gated;
248
+ if (options.applyOracleIntegrity !== false) {
249
+ const verdict = evaluateProductOracleIntegrity({
250
+ projectRoot,
251
+ runSummaryText: options.runSummaryText,
252
+ env: options.env,
253
+ });
254
+ next = mergeOracleVerdict(gated, verdict);
255
+ if (!verdict.ok && next.resolution !== "soft_empty" && next.resolution !== "config") {
256
+ next = { ...next, resolution: "fail" };
257
+ }
258
+ }
259
+ if (options.skipAcceptanceEmit !== true) {
260
+ emitAcceptanceOutcome(next, options, projectRoot);
261
+ }
262
+ return next;
263
+ }
264
+ function annotate(result, acceptance, quiet) {
265
+ const prefix = result.ok
266
+ ? `verify:ac passed (#3284) [rung=${acceptance.source_rung}]`
267
+ : `verify:ac FAILED (#3284) [rung=${acceptance.source_rung}]`;
268
+ let message = result.message;
269
+ if (!quiet) {
270
+ if (message.includes("#3267")) {
271
+ message = message.replace(/#3267/g, "#3284/#3267");
272
+ }
273
+ if (!message.startsWith("verify:ac")) {
274
+ message = `${prefix}\n${message}`;
275
+ }
276
+ else if (!message.includes(`rung=${acceptance.source_rung}`)) {
277
+ message = `${message} [rung=${acceptance.source_rung}]`;
278
+ }
279
+ }
280
+ else if (result.ok) {
281
+ message = "";
282
+ }
283
+ const commandCount = Math.max(result.commands.length, acceptance.commands.length);
284
+ return {
285
+ ...result,
286
+ message,
287
+ sourceRung: acceptance.source_rung,
288
+ noneStated: acceptance.none_stated,
289
+ acceptance,
290
+ resolution: classifyResolution({
291
+ ok: result.ok,
292
+ code: result.code,
293
+ runsLength: result.runs.length,
294
+ commandCount,
295
+ rejectedCount: result.rejected?.length ?? 0,
296
+ }),
297
+ resolvedCommandCount: result.runs.length > 0 ? result.runs.length : commandCount,
298
+ };
299
+ }
300
+ /**
301
+ * Evaluate from xBRIEF path.
302
+ */
303
+ export function evaluateVerifyAcFromPath(xbriefPath, options = {}) {
304
+ const abs = resolve(xbriefPath);
305
+ if (!existsSync(abs)) {
306
+ if (options.softMissingXbrief) {
307
+ return applyOracle(softSkip(`xBRIEF not found: ${abs}`, options.quiet), options);
308
+ }
309
+ return applyOracle(configResult(`verify:ac: xBRIEF not found: ${abs}`), options);
310
+ }
311
+ let parsed;
312
+ try {
313
+ parsed = JSON.parse(readFileSync(abs, "utf8"));
314
+ }
315
+ catch (err) {
316
+ const msg = err instanceof Error ? err.message : String(err);
317
+ return applyOracle(configResult(`verify:ac: unreadable xBRIEF (${msg}): ${abs}`), options);
318
+ }
319
+ const data = asRecord(parsed);
320
+ if (data === null) {
321
+ return applyOracle(configResult(`verify:ac: xBRIEF top-level is not an object: ${abs}`), options);
322
+ }
323
+ const plan = asRecord(data.plan);
324
+ if (plan === null) {
325
+ return applyOracle(configResult(`verify:ac: xBRIEF missing plan object: ${abs}`), options);
326
+ }
327
+ const result = evaluateVerifyAcFromPlan(plan, { ...options, skipAcceptanceEmit: true });
328
+ const banked = maybeAttachAcPassBank(result, plan, abs, options);
329
+ emitAcceptanceOutcome(banked, options, resolve(options.projectRoot ?? process.cwd()));
330
+ return banked;
331
+ }
332
+ /**
333
+ * After executable AC pass, FINALIZE the banking checkpoint (#3285).
334
+ * Soft/advisory passes with zero runs do not bank. Fail-open on ledger errors.
335
+ */
336
+ function maybeAttachAcPassBank(result, plan, xbriefPath, options) {
337
+ if (options.bankOnPass === false) {
338
+ return result;
339
+ }
340
+ if (!result.ok || result.runs.length === 0) {
341
+ return result;
342
+ }
343
+ const projectRoot = resolve(options.projectRoot ?? process.cwd());
344
+ const planId = typeof plan.id === "string" && plan.id.trim() ? plan.id.trim() : null;
345
+ const scopeId = options.bankScopeId?.trim() ||
346
+ planId ||
347
+ basename(xbriefPath)
348
+ .replace(/\.xbrief\.json$/i, "")
349
+ .replace(/\.vbrief\.json$/i, "");
350
+ try {
351
+ const banked = maybeBankOnAcPass({
352
+ projectRoot,
353
+ scopeId,
354
+ executableRuns: result.runs.length,
355
+ quiet: options.quiet,
356
+ });
357
+ if (options.quiet || banked.notes.length === 0) {
358
+ return result;
359
+ }
360
+ const extra = banked.notes.join("\n");
361
+ return {
362
+ ...result,
363
+ message: result.message ? `${result.message}\n${extra}` : extra,
364
+ };
365
+ }
366
+ catch (err) {
367
+ // Checkpoint is mandatory after executable AC green (#3285 Greptile residual).
368
+ const msg = err instanceof Error ? err.message : String(err);
369
+ return {
370
+ ...result,
371
+ ok: false,
372
+ code: 1,
373
+ resolution: "fail",
374
+ message: `verify:ac bank checkpoint failed (#3285): ${msg}` +
375
+ (result.message ? `\n${result.message}` : ""),
376
+ };
377
+ }
378
+ }
379
+ function configResult(message) {
380
+ return {
381
+ ok: false,
382
+ code: 2,
383
+ message,
384
+ commands: [],
385
+ runs: [],
386
+ sourceRung: "project_floor",
387
+ noneStated: true,
388
+ acceptance: { commands: [], none_stated: true, source_rung: "project_floor" },
389
+ resolution: "config",
390
+ resolvedCommandCount: 0,
391
+ };
392
+ }
393
+ function softSkip(detail, quiet) {
394
+ return {
395
+ ok: true,
396
+ code: 0,
397
+ message: quiet ? "" : `verify:ac skipped (#3284 soft-missing): ${detail}`,
398
+ commands: [],
399
+ runs: [],
400
+ sourceRung: "project_floor",
401
+ noneStated: true,
402
+ acceptance: { commands: [], none_stated: true, source_rung: "project_floor" },
403
+ resolution: "skipped",
404
+ resolvedCommandCount: 0,
405
+ };
406
+ }
407
+ /** Pure: product AC is required at every ceremony depth (#3284 / #3267 / #3156). */
408
+ export function isVerifyAcRequiredAtCeremonyDepth(_depth) {
409
+ return true;
410
+ }
411
+ //# sourceMappingURL=evaluate.js.map
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Product-first done-gate (#3284).
3
+ *
4
+ * acceptance.commands schema, verify:ac evaluation, check-mode composition
5
+ * (AC-first, hygiene advisory under pressure, rapid=AC-only).
6
+ */
7
+ export { attachPlanAcceptance, buildAcceptanceFromIntakeCapture, readPlanAcceptance, stampAcceptanceFromLiteralCapture, validatePlanAcceptance, } from "./acceptance.js";
8
+ export { applyProductFirstGateMode, isHygieneGate, isProductAcGate, type ProductFirstCheckModeResolution, type ResolveProductFirstCheckModeInput, resolveProductFirstCheckMode, } from "./check-mode.js";
9
+ export { EMPTY_AC_CAUSE, EMPTY_AC_OUTCOME, EMPTY_AC_REMEDY, formatSoftEmptyMessage, isEmptyAcResolution, isSoftEmptyAcText, projectHasSuiteFloor, type VerifyAcResolution, } from "./empty-resolution.js";
10
+ export { type EvaluateVerifyAcOptions, evaluateVerifyAcFromPath, evaluateVerifyAcFromPlan, isVerifyAcRequiredAtCeremonyDepth, type VerifyAcResult, } from "./evaluate.js";
11
+ export { type AcceptanceCommand, type AcSourceRung, ENV_CHECK_AC_ONLY, ENV_CHECK_MODE, ENV_HYGIENE_ADVISORY, HYGIENE_GATE_ID_PREFIXES, PLAN_ACCEPTANCE_KEY, type PlanAcceptance, PRODUCT_AC_GATE_ID, type ProductFirstCheckMode, } from "./types.js";
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Product-first done-gate (#3284).
3
+ *
4
+ * acceptance.commands schema, verify:ac evaluation, check-mode composition
5
+ * (AC-first, hygiene advisory under pressure, rapid=AC-only).
6
+ */
7
+ export { attachPlanAcceptance, buildAcceptanceFromIntakeCapture, readPlanAcceptance, stampAcceptanceFromLiteralCapture, validatePlanAcceptance, } from "./acceptance.js";
8
+ export { applyProductFirstGateMode, isHygieneGate, isProductAcGate, resolveProductFirstCheckMode, } from "./check-mode.js";
9
+ export { EMPTY_AC_CAUSE, EMPTY_AC_OUTCOME, EMPTY_AC_REMEDY, formatSoftEmptyMessage, isEmptyAcResolution, isSoftEmptyAcText, projectHasSuiteFloor, } from "./empty-resolution.js";
10
+ export { evaluateVerifyAcFromPath, evaluateVerifyAcFromPlan, isVerifyAcRequiredAtCeremonyDepth, } from "./evaluate.js";
11
+ export { ENV_CHECK_AC_ONLY, ENV_CHECK_MODE, ENV_HYGIENE_ADVISORY, HYGIENE_GATE_ID_PREFIXES, PLAN_ACCEPTANCE_KEY, PRODUCT_AC_GATE_ID, } from "./types.js";
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,67 @@
1
+ import type { AcceptanceClause } from "../verify-ac/clauses.js";
2
+ /**
3
+ * Product-first done-gate (#3284): stated acceptance criteria run FIRST and are
4
+ * never skippable; hygiene gates run second and may degrade under pressure.
5
+ *
6
+ * Architecture for #3267 (literal acceptance-command mechanism). Composes
7
+ * #3214 ceremony dial (rapid = AC-only) and #3266 bank-the-pass.
8
+ */
9
+ /** Three-rung AC-source ladder (probe lock on #3284). */
10
+ export type AcSourceRung = "stated" | "derived" | "project_floor";
11
+ /**
12
+ * One executable acceptance command (verbatim when source_rung=stated).
13
+ * Mirrors literal-acceptance command shape for interoperability.
14
+ */
15
+ export interface AcceptanceCommand {
16
+ readonly command: string;
17
+ readonly cwd?: string | null;
18
+ readonly expectedStdout?: string | null;
19
+ readonly expectedExitCode?: number;
20
+ }
21
+ /**
22
+ * Canonical plan.acceptance block (#3284).
23
+ *
24
+ * - Empty `commands` is allowed only when `none_stated: true` (absence is a decision).
25
+ * - `none_stated: true` never means "no AC" — it means AC is derived/floor and flagged.
26
+ * - `source_rung` records which ladder rung was locked at intake / promote.
27
+ */
28
+ export interface PlanAcceptance {
29
+ readonly commands: readonly AcceptanceCommand[];
30
+ /** Explicit marker when the task statement stated no shell commands. */
31
+ readonly none_stated: boolean;
32
+ readonly source_rung: AcSourceRung;
33
+ /** Why derived/floor was chosen (required for derived when recorded). */
34
+ readonly derived_reason?: string | null;
35
+ /** Rung-2 independently testable clauses (#3323). Parallel to commands[]. */
36
+ readonly clauses?: readonly AcceptanceClause[];
37
+ }
38
+ /** How `task check` composes product vs hygiene gates under pressure (#3284). */
39
+ export type ProductFirstCheckMode =
40
+ /** Full graph: AC first (fail-fast), then hygiene (hard), then suite. */
41
+ "full"
42
+ /**
43
+ * Budget pressure / degraded env: AC still mandatory; hygiene runs but is
44
+ * advisory (non-zero does not fail check). Suite still runs after AC when present.
45
+ */
46
+ | "pressure"
47
+ /**
48
+ * Ceremony dial rapid/minimal positive content: only AC verification
49
+ * (no hygiene, no suite) before declaring done via check.
50
+ */
51
+ | "rapid";
52
+ /** Canonical product AC gate id used in check gate lists. */
53
+ export declare const PRODUCT_AC_GATE_ID: "verify:ac";
54
+ /** plan.acceptance object key on the plan root. */
55
+ export declare const PLAN_ACCEPTANCE_KEY: "acceptance";
56
+ /** Env override for check mode (full|pressure|rapid|degraded→pressure). */
57
+ export declare const ENV_CHECK_MODE = "DEFT_CHECK_MODE";
58
+ /** Explicit hygiene-advisory flag (truthy → pressure mode floor). */
59
+ export declare const ENV_HYGIENE_ADVISORY = "DEFT_HYGIENE_ADVISORY";
60
+ /** Explicit rapid AC-only flag (truthy → rapid mode). */
61
+ export declare const ENV_CHECK_AC_ONLY = "DEFT_CHECK_AC_ONLY";
62
+ /**
63
+ * Hygiene gate ids (framework + consumer). Failures may become advisory under
64
+ * pressure; AC never does. Suite gates are separate (#3188).
65
+ */
66
+ export declare const HYGIENE_GATE_ID_PREFIXES: readonly string[];
67
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,54 @@
1
+ /** Canonical product AC gate id used in check gate lists. */
2
+ export const PRODUCT_AC_GATE_ID = "verify:ac";
3
+ /** plan.acceptance object key on the plan root. */
4
+ export const PLAN_ACCEPTANCE_KEY = "acceptance";
5
+ /** Env override for check mode (full|pressure|rapid|degraded→pressure). */
6
+ export const ENV_CHECK_MODE = "DEFT_CHECK_MODE";
7
+ /** Explicit hygiene-advisory flag (truthy → pressure mode floor). */
8
+ export const ENV_HYGIENE_ADVISORY = "DEFT_HYGIENE_ADVISORY";
9
+ /** Explicit rapid AC-only flag (truthy → rapid mode). */
10
+ export const ENV_CHECK_AC_ONLY = "DEFT_CHECK_AC_ONLY";
11
+ /**
12
+ * Hygiene gate ids (framework + consumer). Failures may become advisory under
13
+ * pressure; AC never does. Suite gates are separate (#3188).
14
+ */
15
+ export const HYGIENE_GATE_ID_PREFIXES = [
16
+ "verify:branch",
17
+ "verify:encoding",
18
+ "verify:cache-fresh",
19
+ "verify:orphan-active",
20
+ "verify:license-sync",
21
+ "verify:contract-drift",
22
+ "toolchain:check",
23
+ "toolchain:check-consumer",
24
+ "verify:stubs",
25
+ "verify:links",
26
+ "verify:rule-ownership",
27
+ "verify:biome-config",
28
+ "verify:content-manifest",
29
+ "verify:skill-external-fetch-gate",
30
+ "verify:cursor-tier1",
31
+ "verify:openclaw-tier1",
32
+ "verify:go-freeze",
33
+ "verify:bridge-drift",
34
+ "verify:forward-coverage",
35
+ "verify:test-boundary",
36
+ "verify:scope-provenance",
37
+ "verify:consumer-check-contract",
38
+ "verify:vbrief-conformance",
39
+ "verify:destructive-gh-verbs",
40
+ "verify:scm-boundary",
41
+ "verify:xbrief-drift",
42
+ "verify:no-task-runtime",
43
+ "verify:pack-drift",
44
+ "verify:wip-cap",
45
+ "verify:agents-md-budget",
46
+ "verify:eval-health-relocation",
47
+ "verify:eval-triggers-relocation",
48
+ "vbrief:validate",
49
+ "codebase:validate-structure",
50
+ "verify:codebase-map-fresh",
51
+ "verify-strategy-output",
52
+ "doctor",
53
+ ];
54
+ //# sourceMappingURL=types.js.map