@deftai/directive-core 0.104.0 → 0.105.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.
- package/dist/authz/classify.js +526 -42
- package/dist/check/cached-orchestrator.d.ts +1 -1
- package/dist/check/cached-orchestrator.js +2 -2
- package/dist/check/named-cause.d.ts +1 -1
- package/dist/check/named-cause.js +33 -3
- package/dist/codebase/default-extractor.d.ts +5 -0
- package/dist/codebase/default-extractor.js +7 -15
- package/dist/deposit/copy-tree.js +60 -0
- package/dist/deposit/python-free.js +26 -18
- package/dist/doctor/checks.d.ts +8 -0
- package/dist/doctor/checks.js +37 -25
- package/dist/doctor/doctor-state.d.ts +4 -0
- package/dist/doctor/doctor-state.js +7 -1
- package/dist/doctor/main.js +9 -19
- package/dist/doctor/types.d.ts +9 -0
- package/dist/fs/contained-write.d.ts +115 -1
- package/dist/fs/contained-write.js +241 -5
- package/dist/fs/mutation-ledger.d.ts +54 -0
- package/dist/fs/mutation-ledger.js +133 -0
- package/dist/fs/non-product-dirs.d.ts +79 -0
- package/dist/fs/non-product-dirs.js +96 -0
- package/dist/hooks/dispatcher.d.ts +3 -1
- package/dist/hooks/dispatcher.js +14 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/init-deposit/agent-hooks.js +17 -15
- package/dist/init-deposit/core-guard-pin-content.d.ts +7 -0
- package/dist/init-deposit/core-guard-pin-content.js +393 -0
- package/dist/init-deposit/gitignore.js +9 -0
- package/dist/init-deposit/hygiene.d.ts +47 -11
- package/dist/init-deposit/hygiene.js +172 -37
- package/dist/init-deposit/legacy-detect.js +6 -2
- package/dist/init-deposit/refresh.d.ts +21 -1
- package/dist/init-deposit/refresh.js +106 -9
- package/dist/init-deposit/scaffold.js +28 -279
- package/dist/init-deposit/slash-deposit.js +13 -7
- package/dist/init-deposit/xbrief-projections.d.ts +8 -1
- package/dist/init-deposit/xbrief-projections.js +24 -11
- package/dist/intake/clause-derivation.d.ts +38 -1
- package/dist/intake/clause-derivation.js +211 -9
- package/dist/intake/issue-ingest.d.ts +3 -1
- package/dist/intake/issue-ingest.js +35 -6
- package/dist/lifecycle/completed-tracked-on-delivery.d.ts +5 -0
- package/dist/lifecycle/completed-tracked-on-delivery.js +85 -18
- package/dist/literal-acceptance/capture.d.ts +10 -0
- package/dist/literal-acceptance/capture.js +224 -75
- package/dist/literal-acceptance/evaluate.d.ts +29 -4
- package/dist/literal-acceptance/evaluate.js +70 -2
- package/dist/literal-acceptance/index.d.ts +3 -3
- package/dist/literal-acceptance/index.js +3 -3
- package/dist/literal-acceptance/safety.d.ts +41 -0
- package/dist/literal-acceptance/safety.js +126 -2
- package/dist/literal-acceptance/types.d.ts +8 -0
- package/dist/orphan-active/evaluate.d.ts +7 -1
- package/dist/orphan-active/evaluate.js +102 -23
- package/dist/platform/platform-capabilities.js +2 -3
- package/dist/policy/base-branch.d.ts +37 -0
- package/dist/policy/base-branch.js +114 -0
- package/dist/policy/branch-sync.d.ts +80 -0
- package/dist/policy/branch-sync.js +211 -0
- package/dist/policy/ceremony-dial-escalation.js +1 -0
- package/dist/policy/ceremony-dial.js +4 -14
- package/dist/policy/delivery-branch.d.ts +5 -3
- package/dist/policy/delivery-branch.js +7 -3
- package/dist/policy/file-size-thresholds.d.ts +24 -0
- package/dist/policy/file-size-thresholds.js +23 -0
- package/dist/policy/forge-outage-retry.d.ts +47 -0
- package/dist/policy/forge-outage-retry.js +157 -0
- package/dist/policy/index.d.ts +7 -0
- package/dist/policy/index.js +66 -7
- package/dist/policy/project-invariants.d.ts +50 -0
- package/dist/policy/project-invariants.js +205 -0
- package/dist/policy/sync-default.d.ts +129 -0
- package/dist/policy/sync-default.js +452 -0
- package/dist/policy/sync-max-files.d.ts +93 -0
- package/dist/policy/sync-max-files.js +192 -0
- package/dist/pr-monitor/absent-required.d.ts +11 -0
- package/dist/pr-monitor/absent-required.js +61 -0
- package/dist/pr-monitor/constants.d.ts +7 -0
- package/dist/pr-monitor/constants.js +7 -0
- package/dist/pr-monitor/index.d.ts +2 -1
- package/dist/pr-monitor/index.js +2 -1
- package/dist/pr-monitor/main.js +4 -0
- package/dist/pr-monitor/monitor.js +24 -1
- package/dist/pr-wait-mergeable/classify.js +6 -0
- package/dist/preflight/evaluate.d.ts +4 -0
- package/dist/preflight/evaluate.js +35 -1
- package/dist/preflight/index.d.ts +4 -0
- package/dist/preflight/index.js +2 -0
- package/dist/preflight/intended-placement.d.ts +62 -0
- package/dist/preflight/intended-placement.js +275 -0
- package/dist/preflight/project-invariants-gate.d.ts +29 -0
- package/dist/preflight/project-invariants-gate.js +82 -0
- package/dist/product-first-done-gate/acceptance-resolver.d.ts +128 -0
- package/dist/product-first-done-gate/acceptance-resolver.js +144 -0
- package/dist/product-first-done-gate/acceptance.d.ts +7 -4
- package/dist/product-first-done-gate/acceptance.js +79 -8
- package/dist/product-first-done-gate/empty-resolution.d.ts +4 -1
- package/dist/product-first-done-gate/empty-resolution.js +12 -1
- package/dist/product-first-done-gate/evaluate.d.ts +12 -0
- package/dist/product-first-done-gate/evaluate.js +254 -31
- package/dist/product-first-done-gate/index.d.ts +2 -0
- package/dist/product-first-done-gate/index.js +1 -0
- package/dist/release/build-dist.d.ts +101 -0
- package/dist/release/build-dist.js +428 -46
- package/dist/run-summary/emit.d.ts +16 -10
- package/dist/run-summary/emit.js +26 -15
- package/dist/run-summary/index.d.ts +3 -2
- package/dist/run-summary/index.js +2 -1
- package/dist/run-summary/session-id.d.ts +21 -0
- package/dist/run-summary/session-id.js +92 -0
- package/dist/run-summary/types.d.ts +29 -4
- package/dist/run-summary/types.js +1 -0
- package/dist/scope/acceptance-evidence.d.ts +19 -7
- package/dist/scope/acceptance-evidence.js +38 -11
- package/dist/scope/delivery-evidence.d.ts +3 -3
- package/dist/scope/delivery-evidence.js +22 -27
- package/dist/scope/index.d.ts +1 -0
- package/dist/scope/index.js +1 -0
- package/dist/scope/parent-lineage.js +7 -6
- package/dist/scope/project-invariant-coverage.d.ts +54 -0
- package/dist/scope/project-invariant-coverage.js +322 -0
- package/dist/scope/transition.js +1 -1
- package/dist/scope-provenance/compare-intent.d.ts +27 -0
- package/dist/scope-provenance/compare-intent.js +233 -0
- package/dist/scope-provenance/digest.d.ts +18 -1
- package/dist/scope-provenance/digest.js +16 -11
- package/dist/scope-provenance/evaluate.d.ts +5 -1
- package/dist/scope-provenance/evaluate.js +64 -4
- package/dist/scope-provenance/extract-intent.d.ts +43 -0
- package/dist/scope-provenance/extract-intent.js +262 -0
- package/dist/scope-provenance/index.d.ts +7 -1
- package/dist/scope-provenance/index.js +7 -1
- package/dist/scope-provenance/intent-digest.d.ts +12 -0
- package/dist/scope-provenance/intent-digest.js +33 -0
- package/dist/scope-provenance/intent-evaluate.d.ts +43 -0
- package/dist/scope-provenance/intent-evaluate.js +149 -0
- package/dist/scope-provenance/json-tokenizer.d.ts +19 -0
- package/dist/scope-provenance/json-tokenizer.js +225 -0
- package/dist/scope-provenance/known-machine.d.ts +38 -0
- package/dist/scope-provenance/known-machine.js +157 -0
- package/dist/scope-provenance/mint-artifacts.d.ts +102 -0
- package/dist/scope-provenance/mint-artifacts.js +425 -0
- package/dist/session/ac-pass-banking.d.ts +4 -36
- package/dist/session/ac-pass-banking.js +30 -77
- package/dist/session/ac-pass-reuse.d.ts +53 -0
- package/dist/session/ac-pass-reuse.js +95 -0
- package/dist/session/git.js +19 -4
- package/dist/session/index.d.ts +4 -0
- package/dist/session/index.js +4 -0
- package/dist/session/occupancy-stress-worker.d.ts +7 -0
- package/dist/session/occupancy-stress-worker.js +36 -0
- package/dist/session/occupancy.d.ts +97 -0
- package/dist/session/occupancy.js +422 -0
- package/dist/session/openclaw-soft-rebind-deposit.js +6 -6
- package/dist/session/product-state-hash.d.ts +26 -0
- package/dist/session/product-state-hash.js +683 -0
- package/dist/session/session-ready.d.ts +2 -0
- package/dist/session/session-ready.js +52 -30
- package/dist/session/session-start.d.ts +7 -0
- package/dist/session/session-start.js +71 -7
- package/dist/session/verify-ac-session-cache.d.ts +42 -0
- package/dist/session/verify-ac-session-cache.js +126 -0
- package/dist/session/verify-session-ritual.d.ts +5 -0
- package/dist/session/verify-session-ritual.js +9 -0
- package/dist/slash/openclaw-deposit.js +13 -9
- package/dist/slice/constants.d.ts +2 -2
- package/dist/slice/constants.js +2 -2
- package/dist/slice/existing.js +9 -3
- package/dist/slice/lock.d.ts +16 -1
- package/dist/slice/lock.js +137 -11
- package/dist/story-ready/evaluate.d.ts +2 -0
- package/dist/story-ready/evaluate.js +13 -0
- package/dist/swarm/complete-cohort.d.ts +3 -0
- package/dist/swarm/complete-cohort.js +59 -11
- package/dist/swarm/finalize-cohort.js +33 -2
- package/dist/swarm/launch.d.ts +22 -0
- package/dist/swarm/launch.js +155 -0
- package/dist/swarm/routing-set-cli.d.ts +11 -1
- package/dist/swarm/routing-set-cli.js +13 -3
- package/dist/swarm/routing-verify.d.ts +12 -0
- package/dist/swarm/routing-verify.js +59 -20
- package/dist/swarm/routing.d.ts +14 -0
- package/dist/swarm/routing.js +53 -3
- package/dist/telemetry-coverage/fake-trial.js +10 -0
- package/dist/telemetry-coverage/kinds.js +2 -0
- package/dist/triage/actions/index.js +4 -1
- package/dist/ts-check-lane/index.d.ts +3 -0
- package/dist/ts-check-lane/index.js +2 -0
- package/dist/ts-check-lane/progress-reporter.d.ts +17 -0
- package/dist/ts-check-lane/progress-reporter.js +38 -0
- package/dist/ts-check-lane/progress.d.ts +32 -0
- package/dist/ts-check-lane/progress.js +57 -0
- package/dist/ts-check-lane/run-lane.d.ts +3 -1
- package/dist/ts-check-lane/run-lane.js +8 -6
- package/dist/validate-content/validate-links.d.ts +8 -0
- package/dist/validate-content/validate-links.js +9 -15
- package/dist/value/feedback-file.js +12 -2
- package/dist/vbrief-build/index.d.ts +1 -0
- package/dist/vbrief-build/index.js +1 -0
- package/dist/vbrief-build/project-invariants-io.d.ts +16 -0
- package/dist/vbrief-build/project-invariants-io.js +41 -0
- package/dist/vbrief-reconcile/graph.js +18 -1
- package/dist/vbrief-reconcile/index.d.ts +1 -1
- package/dist/vbrief-reconcile/index.js +1 -1
- package/dist/vbrief-reconcile/types.d.ts +13 -0
- package/dist/vbrief-reconcile/umbrellas.d.ts +14 -0
- package/dist/vbrief-reconcile/umbrellas.js +261 -26
- package/dist/vbrief-validate/index.d.ts +1 -1
- package/dist/vbrief-validate/index.js +1 -1
- package/dist/vbrief-validate/plan-hooks.d.ts +4 -0
- package/dist/vbrief-validate/plan-hooks.js +68 -0
- package/dist/verify-ac/evaluate.d.ts +7 -1
- package/dist/verify-ac/evaluate.js +34 -26
- package/dist/verify-ac/flag.d.ts +4 -0
- package/dist/verify-ac/flag.js +16 -0
- package/dist/verify-ac/index.d.ts +2 -2
- package/dist/verify-ac/index.js +2 -2
- package/dist/verify-source/contained-writes.js +2 -0
- package/dist/verify-source/verify-stubs.d.ts +15 -1
- package/dist/verify-source/verify-stubs.js +20 -16
- package/dist/vitest-runner/win32-coverage-tmp-setup.d.ts +5 -6
- package/dist/vitest-runner/win32-coverage-tmp-setup.js +5 -6
- package/dist/xbrief-migrate/migrate-project.js +2 -5
- package/package.json +3 -3
package/dist/run-summary/emit.js
CHANGED
|
@@ -12,6 +12,7 @@ import { readCorePackageVersion } from "../engine-version.js";
|
|
|
12
12
|
import { ContainedWriteError, ContainedWriteErrorCode, containedWrite, } from "../fs/contained-write.js";
|
|
13
13
|
import { assertWriteTargetSafe } from "../fs/projection-containment.js";
|
|
14
14
|
import { resolveRunSummaryDestination } from "./path.js";
|
|
15
|
+
import { resolveRunSummarySessionId } from "./session-id.js";
|
|
15
16
|
import { ENV_TOTAL_TOOL_TURNS, RUN_SUMMARY_SCHEMA_VERSION, RUN_SUMMARY_STDOUT_PREFIX, RUN_SUMMARY_WRITE_WARNING, } from "./types.js";
|
|
16
17
|
function sortKeysDeep(value) {
|
|
17
18
|
if (Array.isArray(value)) {
|
|
@@ -250,6 +251,7 @@ export class RunSummaryEmitter {
|
|
|
250
251
|
warned = false;
|
|
251
252
|
projectRoot;
|
|
252
253
|
sessionId;
|
|
254
|
+
component;
|
|
253
255
|
frameworkVersion;
|
|
254
256
|
now;
|
|
255
257
|
destination;
|
|
@@ -258,7 +260,12 @@ export class RunSummaryEmitter {
|
|
|
258
260
|
writeStderr;
|
|
259
261
|
constructor(options) {
|
|
260
262
|
this.projectRoot = options.projectRoot;
|
|
261
|
-
this.sessionId =
|
|
263
|
+
this.sessionId = resolveRunSummarySessionId({
|
|
264
|
+
projectRoot: options.projectRoot,
|
|
265
|
+
explicit: options.sessionId,
|
|
266
|
+
env: options.env,
|
|
267
|
+
});
|
|
268
|
+
this.component = options.component?.trim() || undefined;
|
|
262
269
|
this.frameworkVersion = options.frameworkVersion ?? readCorePackageVersion();
|
|
263
270
|
this.now = options.now ?? (() => new Date());
|
|
264
271
|
this.env = options.env ?? process.env;
|
|
@@ -285,6 +292,7 @@ export class RunSummaryEmitter {
|
|
|
285
292
|
ts: this.now().toISOString(),
|
|
286
293
|
event,
|
|
287
294
|
payload,
|
|
295
|
+
...(this.component !== undefined ? { component: this.component } : {}),
|
|
288
296
|
...(denominator !== undefined ? { total_tool_turns: denominator } : {}),
|
|
289
297
|
};
|
|
290
298
|
}
|
|
@@ -352,6 +360,9 @@ export class RunSummaryEmitter {
|
|
|
352
360
|
emitAcceptanceStamp(payload) {
|
|
353
361
|
return this.emit("acceptance_stamp", payload);
|
|
354
362
|
}
|
|
363
|
+
emitAcPassBank(payload) {
|
|
364
|
+
return this.emit("ac_pass_bank", payload);
|
|
365
|
+
}
|
|
355
366
|
/** Emit the harness-supplied denominator when DEFT_TOTAL_TOOL_TURNS is set. */
|
|
356
367
|
emitKnownToolTurnDenominator() {
|
|
357
368
|
const n = readEnvToolTurnDenominator(this.env);
|
|
@@ -361,14 +372,16 @@ export class RunSummaryEmitter {
|
|
|
361
372
|
return this.emitToolTurnDenominator({ total_tool_turns: n });
|
|
362
373
|
}
|
|
363
374
|
/**
|
|
364
|
-
*
|
|
375
|
+
* Emit a session denominator only when a host/harness value is known (#3399).
|
|
365
376
|
* `emitKnownToolTurnDenominator` stays silent unless DEFT_TOTAL_TOOL_TURNS is
|
|
366
|
-
* set; this caller records
|
|
377
|
+
* set; this caller also records DEFT_MAX_TURNS / host maxTurns.
|
|
367
378
|
*/
|
|
368
379
|
emitSessionToolTurnDenominator(hostMaxTurns) {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
380
|
+
const resolved = resolveSessionToolTurnDenominator(this.env, hostMaxTurns);
|
|
381
|
+
if (resolved === undefined) {
|
|
382
|
+
return { emitted: false, destination: this.destination, line: null, warning: false };
|
|
383
|
+
}
|
|
384
|
+
return this.emitToolTurnDenominator(resolved);
|
|
372
385
|
}
|
|
373
386
|
}
|
|
374
387
|
function readPayloadToolTurnDenominator(payload) {
|
|
@@ -384,8 +397,6 @@ export function readEnvToolTurnDenominator(env) {
|
|
|
384
397
|
}
|
|
385
398
|
/** Canonical host planned-turn budget recorded at session:start (#3356). */
|
|
386
399
|
export const ENV_MAX_TURNS_DENOMINATOR = "DEFT_MAX_TURNS";
|
|
387
|
-
/** session:start is one CLI invocation when no host/harness count is known (#3356). */
|
|
388
|
-
export const SESSION_START_CLI_INVOCATION_DENOMINATOR = 1;
|
|
389
400
|
function isPositiveIntegerDenominator(value) {
|
|
390
401
|
return (typeof value === "number" && Number.isInteger(value) && Number.isFinite(value) && value > 0);
|
|
391
402
|
}
|
|
@@ -408,26 +419,26 @@ function readPositiveIntegerEnv(env, key) {
|
|
|
408
419
|
return isPositiveIntegerDenominator(n) ? n : undefined;
|
|
409
420
|
}
|
|
410
421
|
/**
|
|
411
|
-
* Resolve the session tool/turn denominator (#
|
|
422
|
+
* Resolve the session tool/turn denominator (#3399).
|
|
412
423
|
*
|
|
413
424
|
* Prefer harness actuals (`DEFT_TOTAL_TOOL_TURNS`), then a host planned-turn
|
|
414
|
-
* budget (`DEFT_MAX_TURNS` or `hostMaxTurns`
|
|
415
|
-
*
|
|
425
|
+
* budget (`DEFT_MAX_TURNS` or `hostMaxTurns`). Unset → undefined (no event).
|
|
426
|
+
* Share is unevaluable without a host/harness value.
|
|
416
427
|
*/
|
|
417
428
|
export function resolveSessionToolTurnDenominator(env, hostMaxTurns) {
|
|
418
429
|
const known = readEnvToolTurnDenominator(env);
|
|
419
430
|
if (known !== undefined) {
|
|
420
|
-
return known;
|
|
431
|
+
return { total_tool_turns: known, denominator_source: "harness_actual" };
|
|
421
432
|
}
|
|
422
433
|
const planned = readPositiveIntegerEnv(env, ENV_MAX_TURNS_DENOMINATOR);
|
|
423
434
|
if (planned !== undefined) {
|
|
424
|
-
return planned;
|
|
435
|
+
return { total_tool_turns: planned, denominator_source: "host_planned" };
|
|
425
436
|
}
|
|
426
437
|
const host = coercePositiveHostDenominator(hostMaxTurns);
|
|
427
438
|
if (host !== undefined) {
|
|
428
|
-
return host;
|
|
439
|
+
return { total_tool_turns: host, denominator_source: "host_planned" };
|
|
429
440
|
}
|
|
430
|
-
return
|
|
441
|
+
return undefined;
|
|
431
442
|
}
|
|
432
443
|
/**
|
|
433
444
|
* One-shot helper for call sites that do not hold an emitter (e.g. dial escalate).
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export { type EmitRunSummaryResult, ENV_MAX_TURNS_DENOMINATOR, emitRunSummaryEvent, RunSummaryEmitter, type RunSummaryEmitterOptions, resolveSessionToolTurnDenominator,
|
|
1
|
+
export { type EmitRunSummaryResult, ENV_MAX_TURNS_DENOMINATOR, emitRunSummaryEvent, type ResolvedSessionToolTurnDenominator, RunSummaryEmitter, type RunSummaryEmitterOptions, resolveSessionToolTurnDenominator, } from "./emit.js";
|
|
2
2
|
export { gitignoreCoversRunSummary, type ResolveRunSummaryDestinationOptions, resolveRunSummaryDestination, } from "./path.js";
|
|
3
|
+
export { type ResolveRunSummarySessionIdInput, resolveRunSummarySessionId, } from "./session-id.js";
|
|
3
4
|
export { computeRitualGateShare, parseRunSummaryJsonl, type RitualGateShare, readToolTurnDenominator, } from "./share.js";
|
|
4
|
-
export { type AcceptanceClauseOutcomeRow, type AcceptanceRunSummaryOutcome, type AcceptanceRunSummaryPayload, type AcceptanceStampRunSummaryPayload, type CheckGateOutcome, type CheckInvocationRunSummaryPayload, DEFAULT_RUN_SUMMARY_BASENAME, type DialEscalationEvaluationOutcome, type DialEscalationEvaluationRunSummaryPayload, type DialTransitionRunSummaryPayload, ENV_RUN_SUMMARY_PATH, ENV_TOTAL_TOOL_TURNS, RUN_SUMMARY_EVENT_KINDS, RUN_SUMMARY_SCHEMA_VERSION, RUN_SUMMARY_STDOUT_PREFIX, RUN_SUMMARY_WRITE_WARNING, type RunSummaryBaseFields, type RunSummaryDestination, type RunSummaryEventKind, type RunSummaryLine, type RunSummaryPayload, type SessionStartRunSummaryPayload, type ToolTurnDenominatorRunSummaryPayload, type VerificationOutcome, type VerificationRunSummaryPayload, } from "./types.js";
|
|
5
|
+
export { type AcceptanceClauseOutcomeRow, type AcceptanceRunSummaryOutcome, type AcceptanceRunSummaryPayload, type AcceptanceStampRunSummaryPayload, type AcPassBankRunSummaryPayload, type CheckGateOutcome, type CheckInvocationRunSummaryPayload, DEFAULT_RUN_SUMMARY_BASENAME, type DialEscalationEvaluationOutcome, type DialEscalationEvaluationRunSummaryPayload, type DialTransitionRunSummaryPayload, ENV_RUN_SUMMARY_PATH, ENV_TOTAL_TOOL_TURNS, RUN_SUMMARY_EVENT_KINDS, RUN_SUMMARY_SCHEMA_VERSION, RUN_SUMMARY_STDOUT_PREFIX, RUN_SUMMARY_WRITE_WARNING, type RunSummaryBaseFields, type RunSummaryDestination, type RunSummaryEventKind, type RunSummaryLine, type RunSummaryPayload, type SessionStartRunSummaryPayload, type ToolTurnDenominatorRunSummaryPayload, type ToolTurnDenominatorSource, type VerificationOutcome, type VerificationRunSummaryPayload, } from "./types.js";
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export { ENV_MAX_TURNS_DENOMINATOR, emitRunSummaryEvent, RunSummaryEmitter, resolveSessionToolTurnDenominator,
|
|
1
|
+
export { ENV_MAX_TURNS_DENOMINATOR, emitRunSummaryEvent, RunSummaryEmitter, resolveSessionToolTurnDenominator, } from "./emit.js";
|
|
2
2
|
export { gitignoreCoversRunSummary, resolveRunSummaryDestination, } from "./path.js";
|
|
3
|
+
export { resolveRunSummarySessionId, } from "./session-id.js";
|
|
3
4
|
export { computeRitualGateShare, parseRunSummaryJsonl, readToolTurnDenominator, } from "./share.js";
|
|
4
5
|
export { DEFAULT_RUN_SUMMARY_BASENAME, ENV_RUN_SUMMARY_PATH, ENV_TOTAL_TOOL_TURNS, RUN_SUMMARY_EVENT_KINDS, RUN_SUMMARY_SCHEMA_VERSION, RUN_SUMMARY_STDOUT_PREFIX, RUN_SUMMARY_WRITE_WARNING, } from "./types.js";
|
|
5
6
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared workspace session identity for run-summary emitters (#3399).
|
|
3
|
+
*
|
|
4
|
+
* Ritual-state holds the workspace session id written by session:start.
|
|
5
|
+
* #3350 persisted seq by counting JSONL lines; it is not the identity store.
|
|
6
|
+
*/
|
|
7
|
+
export interface ResolveRunSummarySessionIdInput {
|
|
8
|
+
readonly projectRoot: string;
|
|
9
|
+
readonly explicit?: string | null;
|
|
10
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
11
|
+
readonly mint?: () => string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Resolve one workspace session id for a run-summary line.
|
|
15
|
+
*
|
|
16
|
+
* Order: explicit option → DEFT_SESSION_ID → ritual-state session_id →
|
|
17
|
+
* last session_id already in the destination JSONL → mint only when no
|
|
18
|
+
* workspace session exists yet.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveRunSummarySessionId(input: ResolveRunSummarySessionIdInput): string;
|
|
21
|
+
//# sourceMappingURL=session-id.d.ts.map
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared workspace session identity for run-summary emitters (#3399).
|
|
3
|
+
*
|
|
4
|
+
* Ritual-state holds the workspace session id written by session:start.
|
|
5
|
+
* #3350 persisted seq by counting JSONL lines; it is not the identity store.
|
|
6
|
+
*/
|
|
7
|
+
import { randomUUID } from "node:crypto";
|
|
8
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
9
|
+
import { resolve } from "node:path";
|
|
10
|
+
import { readRitualState } from "../session/ritual-sentinel.js";
|
|
11
|
+
import { resolveRunSummaryDestination } from "./path.js";
|
|
12
|
+
import { parseRunSummaryJsonl } from "./share.js";
|
|
13
|
+
const mintedByProjectRoot = new Map();
|
|
14
|
+
function trimNonEmpty(value) {
|
|
15
|
+
if (typeof value !== "string") {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
const trimmed = value.trim();
|
|
19
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
20
|
+
}
|
|
21
|
+
function lastSessionIdFromJsonl(path) {
|
|
22
|
+
try {
|
|
23
|
+
if (!existsSync(path)) {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
const lines = parseRunSummaryJsonl(readFileSync(path, "utf8"));
|
|
27
|
+
for (let i = lines.length - 1; i >= 0; i -= 1) {
|
|
28
|
+
const id = trimNonEmpty(lines[i]?.session_id);
|
|
29
|
+
if (id !== undefined) {
|
|
30
|
+
return id;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function ritualSessionId(projectRoot) {
|
|
40
|
+
try {
|
|
41
|
+
const [state] = readRitualState(projectRoot);
|
|
42
|
+
return trimNonEmpty(state?.sessionId);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Resolve one workspace session id for a run-summary line.
|
|
50
|
+
*
|
|
51
|
+
* Order: explicit option → DEFT_SESSION_ID → ritual-state session_id →
|
|
52
|
+
* last session_id already in the destination JSONL → mint only when no
|
|
53
|
+
* workspace session exists yet.
|
|
54
|
+
*/
|
|
55
|
+
export function resolveRunSummarySessionId(input) {
|
|
56
|
+
const explicit = trimNonEmpty(input.explicit);
|
|
57
|
+
if (explicit !== undefined) {
|
|
58
|
+
return explicit;
|
|
59
|
+
}
|
|
60
|
+
const env = input.env ?? process.env;
|
|
61
|
+
const fromEnv = trimNonEmpty(env.DEFT_SESSION_ID);
|
|
62
|
+
if (fromEnv !== undefined) {
|
|
63
|
+
return fromEnv;
|
|
64
|
+
}
|
|
65
|
+
const fromRitual = ritualSessionId(input.projectRoot);
|
|
66
|
+
if (fromRitual !== undefined) {
|
|
67
|
+
return fromRitual;
|
|
68
|
+
}
|
|
69
|
+
const dest = resolveRunSummaryDestination(input.projectRoot, { env });
|
|
70
|
+
if (dest.kind === "file") {
|
|
71
|
+
const fromJsonl = lastSessionIdFromJsonl(dest.path);
|
|
72
|
+
if (fromJsonl !== undefined) {
|
|
73
|
+
return fromJsonl;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const rootKey = resolve(input.projectRoot);
|
|
77
|
+
if (input.mint !== undefined) {
|
|
78
|
+
const minted = trimNonEmpty(input.mint());
|
|
79
|
+
if (minted !== undefined) {
|
|
80
|
+
mintedByProjectRoot.set(rootKey, minted);
|
|
81
|
+
return minted;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const cached = mintedByProjectRoot.get(rootKey);
|
|
85
|
+
if (cached !== undefined) {
|
|
86
|
+
return cached;
|
|
87
|
+
}
|
|
88
|
+
const minted = randomUUID();
|
|
89
|
+
mintedByProjectRoot.set(rootKey, minted);
|
|
90
|
+
return minted;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=session-id.js.map
|
|
@@ -15,7 +15,7 @@ export declare const DEFAULT_RUN_SUMMARY_BASENAME = ".deft-run-summary.json";
|
|
|
15
15
|
export declare const RUN_SUMMARY_STDOUT_PREFIX = "DEFT-TLM:";
|
|
16
16
|
/** One warning when an explicitly requested write fails. */
|
|
17
17
|
export declare const RUN_SUMMARY_WRITE_WARNING = "[deft run-summary] failed to write DEFT_RUN_SUMMARY_PATH telemetry (fail-open; exit codes unchanged)";
|
|
18
|
-
export declare const RUN_SUMMARY_EVENT_KINDS: readonly ["session_start", "dial_transition", "dial_escalation_evaluation", "check_invocation", "tool_turn_denominator", "verification", "acceptance", "acceptance_stamp"];
|
|
18
|
+
export declare const RUN_SUMMARY_EVENT_KINDS: readonly ["session_start", "dial_transition", "dial_escalation_evaluation", "check_invocation", "tool_turn_denominator", "verification", "acceptance", "acceptance_stamp", "ac_pass_bank"];
|
|
19
19
|
export type RunSummaryEventKind = (typeof RUN_SUMMARY_EVENT_KINDS)[number];
|
|
20
20
|
export interface RunSummaryBaseFields {
|
|
21
21
|
readonly schema_version: typeof RUN_SUMMARY_SCHEMA_VERSION;
|
|
@@ -32,6 +32,11 @@ export interface RunSummaryBaseFields {
|
|
|
32
32
|
readonly seq: number;
|
|
33
33
|
readonly ts: string;
|
|
34
34
|
readonly event: RunSummaryEventKind;
|
|
35
|
+
/**
|
|
36
|
+
* Optional emitter label (verify-ac, clause-derivation, …). Not a closed
|
|
37
|
+
* union — new callers add a string without a schema bump (#3399).
|
|
38
|
+
*/
|
|
39
|
+
readonly component?: string;
|
|
35
40
|
/**
|
|
36
41
|
* Session total tool/turn count (#3320). Present so ritual+gate share is
|
|
37
42
|
* computable from the summary alone. Absence means the #3286 trigger is unevaluable.
|
|
@@ -88,14 +93,32 @@ export interface CheckInvocationRunSummaryPayload {
|
|
|
88
93
|
readonly none_stated?: boolean;
|
|
89
94
|
readonly clause_outcomes?: readonly AcceptanceClauseOutcomeRow[];
|
|
90
95
|
}
|
|
91
|
-
/**
|
|
96
|
+
/** How a tool_turn_denominator value was obtained (#3399). */
|
|
97
|
+
export type ToolTurnDenominatorSource = "harness_actual" | "host_planned";
|
|
98
|
+
/** Total tool/turn count for the session (#3320 / #3399). */
|
|
92
99
|
export interface ToolTurnDenominatorRunSummaryPayload {
|
|
93
100
|
readonly total_tool_turns: number;
|
|
101
|
+
readonly denominator_source?: ToolTurnDenominatorSource;
|
|
102
|
+
}
|
|
103
|
+
/** Bank checkpoint JSONL payload. Disk ledger stays camelCase (#3387). */
|
|
104
|
+
export interface AcPassBankRunSummaryPayload {
|
|
105
|
+
readonly scope_id: string;
|
|
106
|
+
readonly banked_at: string;
|
|
107
|
+
readonly next_action?: string;
|
|
108
|
+
readonly had_surplus?: boolean;
|
|
109
|
+
readonly surplus_threshold?: number;
|
|
110
|
+
readonly remaining_fraction?: number | null;
|
|
111
|
+
readonly remaining_turns?: number | null;
|
|
112
|
+
readonly remaining_budget?: number | null;
|
|
113
|
+
readonly max_turns?: number | null;
|
|
114
|
+
readonly max_budget?: number | null;
|
|
115
|
+
readonly head_sha?: string | null;
|
|
116
|
+
readonly path?: string;
|
|
94
117
|
}
|
|
95
118
|
/** Product-oracle attempt (#3322). Same emitter as #3319 / #3320. */
|
|
96
119
|
export type VerificationOutcome = "pass" | "fail";
|
|
97
120
|
/** verify:ac resolution telemetry (#3334 / #3355). Distinct from verification pass/fail. */
|
|
98
|
-
export type AcceptanceRunSummaryOutcome = "verified-pass" | "empty-pass" | "soft_empty" | "fail" | "config-error" | "soft-missing";
|
|
121
|
+
export type AcceptanceRunSummaryOutcome = "verified-pass" | "empty-pass" | "soft_empty" | "fail" | "config-error" | "soft-missing" | "rejected-noop";
|
|
99
122
|
export interface AcceptanceRunSummaryPayload {
|
|
100
123
|
readonly resolved_command_count: number;
|
|
101
124
|
readonly outcome: AcceptanceRunSummaryOutcome;
|
|
@@ -103,6 +126,8 @@ export interface AcceptanceRunSummaryPayload {
|
|
|
103
126
|
readonly none_stated?: boolean;
|
|
104
127
|
readonly clause_count?: number;
|
|
105
128
|
readonly clause_outcomes?: readonly AcceptanceClauseOutcomeRow[];
|
|
129
|
+
/** bank | cache | executed — how verify:ac obtained this result (#3387). */
|
|
130
|
+
readonly served_from?: "bank" | "cache" | "executed";
|
|
106
131
|
}
|
|
107
132
|
/** Intake-time stamp: which rung locked, whether commands were stated, counts (#3323). */
|
|
108
133
|
export interface AcceptanceStampRunSummaryPayload {
|
|
@@ -122,7 +147,7 @@ export interface VerificationRunSummaryPayload {
|
|
|
122
147
|
*/
|
|
123
148
|
readonly independent_rederivation?: boolean;
|
|
124
149
|
}
|
|
125
|
-
export type RunSummaryPayload = SessionStartRunSummaryPayload | DialTransitionRunSummaryPayload | DialEscalationEvaluationRunSummaryPayload | CheckInvocationRunSummaryPayload | ToolTurnDenominatorRunSummaryPayload | VerificationRunSummaryPayload | AcceptanceRunSummaryPayload | AcceptanceStampRunSummaryPayload;
|
|
150
|
+
export type RunSummaryPayload = SessionStartRunSummaryPayload | DialTransitionRunSummaryPayload | DialEscalationEvaluationRunSummaryPayload | CheckInvocationRunSummaryPayload | ToolTurnDenominatorRunSummaryPayload | VerificationRunSummaryPayload | AcceptanceRunSummaryPayload | AcceptanceStampRunSummaryPayload | AcPassBankRunSummaryPayload;
|
|
126
151
|
export type RunSummaryLine = RunSummaryBaseFields & {
|
|
127
152
|
readonly payload: RunSummaryPayload;
|
|
128
153
|
};
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* ITEM_CORE is not expanded with bare keys; verify:vbrief-conformance rejects them.
|
|
14
14
|
*/
|
|
15
15
|
import type { GrantOrigin } from "../authz/types.js";
|
|
16
|
+
import { type AcceptancePredicate } from "../product-first-done-gate/acceptance-resolver.js";
|
|
16
17
|
import { type EvaluateVerifyAcOptions } from "../product-first-done-gate/evaluate.js";
|
|
17
18
|
/** Canonical namespaced key for typed acceptance evidence (#3305 / #1620). */
|
|
18
19
|
export declare const ACCEPTANCE_EVIDENCE_KEY: "x-directive/evidence";
|
|
@@ -56,6 +57,10 @@ export interface AcceptanceEvidenceGateResult {
|
|
|
56
57
|
readonly ok: boolean;
|
|
57
58
|
readonly message: string;
|
|
58
59
|
readonly reports: readonly CriterionAcceptanceReport[];
|
|
60
|
+
/** How the #3357 walk obtained AC (#3387). */
|
|
61
|
+
readonly servedFrom?: "bank" | "cache" | "executed";
|
|
62
|
+
/** Which acceptance check decided the walk (#3497). Undefined when no walk ran. */
|
|
63
|
+
readonly predicate?: AcceptancePredicate;
|
|
59
64
|
}
|
|
60
65
|
export declare function isAcceptanceEvidenceKind(value: unknown): value is AcceptanceEvidenceKind;
|
|
61
66
|
export declare function isAcceptanceDispositionKind(value: unknown): value is AcceptanceDispositionKind;
|
|
@@ -100,17 +105,24 @@ export declare function stampNamespacedEvidence(item: Record<string, unknown>, r
|
|
|
100
105
|
*/
|
|
101
106
|
export declare function stampNamespacedDisposition(item: Record<string, unknown>, record: AcceptanceDispositionRecord): void;
|
|
102
107
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
108
|
+
* Standing contract for scope:complete's acceptance precondition (#3357 / #3497).
|
|
109
|
+
*
|
|
110
|
+
* It no longer asserts a predicate ("empty or failing") — the actual predicate is
|
|
111
|
+
* named per refusal by the shared resolver. It also no longer tells operators to
|
|
112
|
+
* stamp by running verify:ac: verify:ac is the verifier and never writes the brief
|
|
113
|
+
* (a verifier that authors the acceptance it then checks is not a gate). Stamping
|
|
114
|
+
* happens at intake / promote via clause derivation (#3323).
|
|
105
115
|
*/
|
|
106
|
-
export declare const SCOPE_COMPLETE_ACCEPTANCE_REMEDIATION
|
|
116
|
+
export declare const SCOPE_COMPLETE_ACCEPTANCE_REMEDIATION: string;
|
|
107
117
|
/**
|
|
108
118
|
* Hard precondition for scope:complete (#3357 / #3267 / #3284).
|
|
109
119
|
*
|
|
110
|
-
* Runs the same verify:ac walk check uses
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
120
|
+
* Runs the same verify:ac walk check uses, through the one shared option profile and
|
|
121
|
+
* the one shared verdict resolver (#3497) — so scope:complete can no longer report a
|
|
122
|
+
* different story than verify:ac about the same artifact. Disposition on plan items
|
|
123
|
+
* does not skip it. Briefs with no stamped plan.acceptance and no executable commands
|
|
124
|
+
* keep the legacy #3267 "nothing to run" pass so existing evidence-only fixtures stay
|
|
125
|
+
* valid.
|
|
114
126
|
*/
|
|
115
127
|
export declare function evaluateScopeCompleteAcceptanceWalk(plan: Record<string, unknown>, options?: EvaluateVerifyAcOptions): AcceptanceEvidenceGateResult;
|
|
116
128
|
/**
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* ITEM_CORE is not expanded with bare keys; verify:vbrief-conformance rejects them.
|
|
14
14
|
*/
|
|
15
15
|
import { isHumanOrigin } from "../authz/origin.js";
|
|
16
|
+
import { formatAcceptanceVerdict, resolveAcceptanceGateProfile, resolveAcceptanceVerdict, } from "../product-first-done-gate/acceptance-resolver.js";
|
|
16
17
|
import { evaluateVerifyAcFromPlan, } from "../product-first-done-gate/evaluate.js";
|
|
17
18
|
/** Canonical namespaced key for typed acceptance evidence (#3305 / #1620). */
|
|
18
19
|
export const ACCEPTANCE_EVIDENCE_KEY = "x-directive/evidence";
|
|
@@ -371,41 +372,67 @@ function walkItems(items, pathPrefix, reports) {
|
|
|
371
372
|
});
|
|
372
373
|
}
|
|
373
374
|
/**
|
|
374
|
-
*
|
|
375
|
-
*
|
|
375
|
+
* Standing contract for scope:complete's acceptance precondition (#3357 / #3497).
|
|
376
|
+
*
|
|
377
|
+
* It no longer asserts a predicate ("empty or failing") — the actual predicate is
|
|
378
|
+
* named per refusal by the shared resolver. It also no longer tells operators to
|
|
379
|
+
* stamp by running verify:ac: verify:ac is the verifier and never writes the brief
|
|
380
|
+
* (a verifier that authors the acceptance it then checks is not a gate). Stamping
|
|
381
|
+
* happens at intake / promote via clause derivation (#3323).
|
|
376
382
|
*/
|
|
377
|
-
export const SCOPE_COMPLETE_ACCEPTANCE_REMEDIATION = "
|
|
383
|
+
export const SCOPE_COMPLETE_ACCEPTANCE_REMEDIATION = "scope:complete requires executable plan.acceptance that runs green; stamp commands on " +
|
|
384
|
+
"plan.acceptance.commands (or plan.metadata.swarm.verify_commands) — task verify:ac verifies, " +
|
|
385
|
+
"it does not stamp — then re-run task verify:ac -- <completing-xbrief> " +
|
|
386
|
+
"(disposition is not a substitute) (#3357/#3497)";
|
|
378
387
|
/**
|
|
379
388
|
* Hard precondition for scope:complete (#3357 / #3267 / #3284).
|
|
380
389
|
*
|
|
381
|
-
* Runs the same verify:ac walk check uses
|
|
382
|
-
*
|
|
383
|
-
*
|
|
384
|
-
*
|
|
390
|
+
* Runs the same verify:ac walk check uses, through the one shared option profile and
|
|
391
|
+
* the one shared verdict resolver (#3497) — so scope:complete can no longer report a
|
|
392
|
+
* different story than verify:ac about the same artifact. Disposition on plan items
|
|
393
|
+
* does not skip it. Briefs with no stamped plan.acceptance and no executable commands
|
|
394
|
+
* keep the legacy #3267 "nothing to run" pass so existing evidence-only fixtures stay
|
|
395
|
+
* valid.
|
|
385
396
|
*/
|
|
386
397
|
export function evaluateScopeCompleteAcceptanceWalk(plan, options = {}) {
|
|
387
398
|
const stamped = plan.acceptance !== undefined;
|
|
399
|
+
const profile = resolveAcceptanceGateProfile("complete");
|
|
388
400
|
const walk = evaluateVerifyAcFromPlan(plan, {
|
|
389
401
|
...options,
|
|
390
|
-
checkIntegrated:
|
|
391
|
-
captureFromNarratives: options.captureFromNarratives ??
|
|
402
|
+
checkIntegrated: profile.checkIntegrated,
|
|
403
|
+
captureFromNarratives: options.captureFromNarratives ?? profile.captureFromNarratives,
|
|
404
|
+
reuseMode: options.reuseMode ?? profile.reuseMode,
|
|
392
405
|
});
|
|
393
406
|
const rejectedCount = walk.rejected?.length ?? 0;
|
|
394
407
|
const hadWork = walk.runs.length > 0 || walk.commands.length > 0 || rejectedCount > 0;
|
|
408
|
+
const servedFrom = walk.servedFrom ?? "executed";
|
|
395
409
|
if (!stamped && !hadWork) {
|
|
396
410
|
return {
|
|
397
411
|
ok: true,
|
|
398
412
|
message: "Acceptance walk not required (no stamped plan.acceptance) (#3357)",
|
|
399
413
|
reports: [],
|
|
414
|
+
servedFrom: "executed",
|
|
400
415
|
};
|
|
401
416
|
}
|
|
417
|
+
const verdict = resolveAcceptanceVerdict(walk);
|
|
402
418
|
if (walk.ok) {
|
|
403
|
-
return {
|
|
419
|
+
return {
|
|
420
|
+
ok: true,
|
|
421
|
+
message: walk.message,
|
|
422
|
+
reports: [],
|
|
423
|
+
servedFrom,
|
|
424
|
+
predicate: verdict.predicate,
|
|
425
|
+
};
|
|
404
426
|
}
|
|
405
427
|
return {
|
|
406
428
|
ok: false,
|
|
407
|
-
|
|
429
|
+
// Name the check that refused and the value it read BEFORE the standing
|
|
430
|
+
// contract, so the first line the operator sees is the actual cause (#3497).
|
|
431
|
+
message: `scope:complete refused acceptance — ${formatAcceptanceVerdict(verdict)}\n` +
|
|
432
|
+
`${SCOPE_COMPLETE_ACCEPTANCE_REMEDIATION}\n${walk.message}`,
|
|
408
433
|
reports: [],
|
|
434
|
+
servedFrom,
|
|
435
|
+
predicate: verdict.predicate,
|
|
409
436
|
};
|
|
410
437
|
}
|
|
411
438
|
/**
|
|
@@ -99,13 +99,13 @@ export declare function verifyDeliveryAncestry(projectRoot: string, mergeCommit:
|
|
|
99
99
|
remoteTip: string | null;
|
|
100
100
|
};
|
|
101
101
|
/**
|
|
102
|
-
* Gate delivered completion for a code-bearing scope (#3041).
|
|
102
|
+
* Gate delivered completion for a code-bearing scope (#3041 / #3380).
|
|
103
103
|
*
|
|
104
104
|
* Returns ok=true with provenance when:
|
|
105
105
|
* - scope is not code-bearing (provenance may be null or non-code note), OR
|
|
106
106
|
* - explicit non-delivery disposition is provided, OR
|
|
107
|
-
* -
|
|
108
|
-
*
|
|
107
|
+
* - merge commit is an ancestor of the refreshed remote delivery ref (prBase is
|
|
108
|
+
* provenance only; it need not equal deliveryBranch).
|
|
109
109
|
*/
|
|
110
110
|
export declare function evaluateDeliveryGate(options: DeliveryGateOptions): DeliveryGateResult;
|
|
111
111
|
/** Stamp completion provenance onto plan.metadata (mutates plan). */
|
|
@@ -175,7 +175,7 @@ export function verifyDeliveryAncestry(projectRoot, mergeCommit, deliveryBranch,
|
|
|
175
175
|
return {
|
|
176
176
|
ok: false,
|
|
177
177
|
error: `merge commit ${mergeCommit} is not an ancestor of refreshed remote delivery ref ` +
|
|
178
|
-
`${refresh.remoteRef} (${remoteTip})
|
|
178
|
+
`${refresh.remoteRef} (${remoteTip}).`,
|
|
179
179
|
remoteTip,
|
|
180
180
|
};
|
|
181
181
|
}
|
|
@@ -199,14 +199,21 @@ function buildProvenance(input) {
|
|
|
199
199
|
uatVerified: e.uatVerified ?? null,
|
|
200
200
|
};
|
|
201
201
|
}
|
|
202
|
+
function deliveryEvidenceRemediation(deliveryBranch) {
|
|
203
|
+
return (`Pass scope:complete -- --merge-commit <sha> (and --pr <n> if you have one). ` +
|
|
204
|
+
`When develop is the real delivery target, type plan.policy.deliveryBranch ` +
|
|
205
|
+
`(task policy:show --field=deliveryBranch). ` +
|
|
206
|
+
`When ${deliveryBranch} is delivery, wait until the merge commit is an ancestor of ` +
|
|
207
|
+
`origin/${deliveryBranch}, then complete. Do not use --non-delivery for work that shipped.`);
|
|
208
|
+
}
|
|
202
209
|
/**
|
|
203
|
-
* Gate delivered completion for a code-bearing scope (#3041).
|
|
210
|
+
* Gate delivered completion for a code-bearing scope (#3041 / #3380).
|
|
204
211
|
*
|
|
205
212
|
* Returns ok=true with provenance when:
|
|
206
213
|
* - scope is not code-bearing (provenance may be null or non-code note), OR
|
|
207
214
|
* - explicit non-delivery disposition is provided, OR
|
|
208
|
-
* -
|
|
209
|
-
*
|
|
215
|
+
* - merge commit is an ancestor of the refreshed remote delivery ref (prBase is
|
|
216
|
+
* provenance only; it need not equal deliveryBranch).
|
|
210
217
|
*/
|
|
211
218
|
export function evaluateDeliveryGate(options) {
|
|
212
219
|
const runGit = options.runGit ?? defaultGitRunner;
|
|
@@ -267,10 +274,8 @@ export function evaluateDeliveryGate(options) {
|
|
|
267
274
|
return {
|
|
268
275
|
ok: false,
|
|
269
276
|
message: `Delivery evidence required for code-bearing scope completion (#3041). ` +
|
|
270
|
-
`
|
|
271
|
-
`
|
|
272
|
-
`(${NON_DELIVERY_DISPOSITIONS.join("|")}). ` +
|
|
273
|
-
`Merged-to-integration alone is not delivery.`,
|
|
277
|
+
`A merge commit that is an ancestor of refreshed origin/${deliveryBranch} is delivery; ` +
|
|
278
|
+
`PR base is provenance only. ${deliveryEvidenceRemediation(deliveryBranch)}`,
|
|
274
279
|
provenance: null,
|
|
275
280
|
codeBearing: true,
|
|
276
281
|
};
|
|
@@ -294,27 +299,11 @@ export function evaluateDeliveryGate(options) {
|
|
|
294
299
|
};
|
|
295
300
|
}
|
|
296
301
|
}
|
|
297
|
-
if (prBase !== null && prBase !== deliveryBranch) {
|
|
298
|
-
const provenance = buildProvenance({
|
|
299
|
-
evidence,
|
|
300
|
-
deliveryBranch,
|
|
301
|
-
disposition: "merged_to_integration",
|
|
302
|
-
handoffState: "merged_to_integration",
|
|
303
|
-
nowIso: options.nowIso,
|
|
304
|
-
verifier,
|
|
305
|
-
});
|
|
306
|
-
return {
|
|
307
|
-
ok: false,
|
|
308
|
-
message: `PR base '${prBase}' is not the configured delivery branch '${deliveryBranch}'. ` +
|
|
309
|
-
`A merge into an intermediate/feature/integration branch is not delivery evidence (#3041).`,
|
|
310
|
-
provenance,
|
|
311
|
-
codeBearing: true,
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
302
|
if (mergeCommit === null) {
|
|
315
303
|
return {
|
|
316
304
|
ok: false,
|
|
317
|
-
message: "Delivery evidence missing merge_commit_sha; cannot prove ancestry on delivery branch (#3041)."
|
|
305
|
+
message: "Delivery evidence missing merge_commit_sha; cannot prove ancestry on delivery branch (#3041). " +
|
|
306
|
+
deliveryEvidenceRemediation(deliveryBranch),
|
|
318
307
|
provenance: null,
|
|
319
308
|
codeBearing: true,
|
|
320
309
|
};
|
|
@@ -339,9 +328,15 @@ export function evaluateDeliveryGate(options) {
|
|
|
339
328
|
const ancestry = verifyDeliveryAncestry(options.projectRoot, mergeCommit, deliveryBranch, runGit);
|
|
340
329
|
if (!ancestry.ok) {
|
|
341
330
|
const integrationOnly = prBase !== null && prBase !== deliveryBranch;
|
|
331
|
+
const ancestryMsg = ancestry.error ?? "delivery ancestry check failed";
|
|
332
|
+
const rem = deliveryEvidenceRemediation(deliveryBranch);
|
|
333
|
+
const message = integrationOnly
|
|
334
|
+
? `${ancestryMsg} PR base '${prBase}' is provenance only; ` +
|
|
335
|
+
`the merge is not yet on origin/${deliveryBranch}. ${rem}`
|
|
336
|
+
: `${ancestryMsg} ${rem}`;
|
|
342
337
|
return {
|
|
343
338
|
ok: false,
|
|
344
|
-
message
|
|
339
|
+
message,
|
|
345
340
|
provenance: buildProvenance({
|
|
346
341
|
evidence,
|
|
347
342
|
deliveryBranch,
|
package/dist/scope/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export * from "./main.js";
|
|
|
12
12
|
export * from "./open-umbrella-warning.js";
|
|
13
13
|
export * from "./parent-lineage.js";
|
|
14
14
|
export * from "./project-context.js";
|
|
15
|
+
export * from "./project-invariant-coverage.js";
|
|
15
16
|
export * from "./promote-from-issue.js";
|
|
16
17
|
export * from "./promote-path.js";
|
|
17
18
|
export * from "./transition.js";
|
package/dist/scope/index.js
CHANGED
|
@@ -12,6 +12,7 @@ export * from "./main.js";
|
|
|
12
12
|
export * from "./open-umbrella-warning.js";
|
|
13
13
|
export * from "./parent-lineage.js";
|
|
14
14
|
export * from "./project-context.js";
|
|
15
|
+
export * from "./project-invariant-coverage.js";
|
|
15
16
|
export * from "./promote-from-issue.js";
|
|
16
17
|
export * from "./promote-path.js";
|
|
17
18
|
export * from "./transition.js";
|
|
@@ -98,20 +98,21 @@ export function extractChildCoverageDraft(child) {
|
|
|
98
98
|
candidates.push({ source: "plan", obj: plan });
|
|
99
99
|
candidates.push({ source: "root", obj: root });
|
|
100
100
|
for (const c of candidates) {
|
|
101
|
+
const nestedCoverage = asRecord(c.obj.coverage);
|
|
101
102
|
const hasMap = "coverage_map" in c.obj ||
|
|
102
103
|
"coverageMap" in c.obj ||
|
|
103
|
-
|
|
104
|
+
nestedCoverage?.coverage_map !== undefined ||
|
|
105
|
+
nestedCoverage?.coverageMap !== undefined;
|
|
104
106
|
if (!hasMap)
|
|
105
107
|
continue;
|
|
106
|
-
const coverageNested = asRecord(c.obj.coverage);
|
|
107
108
|
const coverage_map = c.obj.coverage_map ??
|
|
108
109
|
c.obj.coverageMap ??
|
|
109
|
-
|
|
110
|
-
|
|
110
|
+
nestedCoverage?.coverage_map ??
|
|
111
|
+
nestedCoverage?.coverageMap;
|
|
111
112
|
const behavioral_deltas = c.obj.behavioral_deltas ??
|
|
112
113
|
c.obj.behavioralDeltas ??
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
nestedCoverage?.behavioral_deltas ??
|
|
115
|
+
nestedCoverage?.behavioralDeltas;
|
|
115
116
|
return {
|
|
116
117
|
draft: {
|
|
117
118
|
coverage_map,
|