@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
|
@@ -12,9 +12,10 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { createHash } from "node:crypto";
|
|
14
14
|
import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync } from "node:fs";
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
15
|
+
import { join, resolve } from "node:path";
|
|
16
|
+
import { containedWrite } from "../fs/contained-write.js";
|
|
17
17
|
import { DEFAULT_SURPLUS_THRESHOLD, resolveAcPassBanking, } from "../policy/ac-pass-banking.js";
|
|
18
|
+
import { RunSummaryEmitter } from "../run-summary/emit.js";
|
|
18
19
|
import { detectHardEffortBudget, formatDeepeningSkippedNote, recommendVerificationDepth, } from "./effort-budget.js";
|
|
19
20
|
/** Durable bank ledger directory (gitignored under `.deft/`). */
|
|
20
21
|
export const AC_PASS_BANK_DIR = ".deft/ac-pass-banks";
|
|
@@ -320,6 +321,7 @@ export function bankAcPass(input) {
|
|
|
320
321
|
scopeId: input.scopeId,
|
|
321
322
|
bankedAt,
|
|
322
323
|
headSha: input.headSha ?? null,
|
|
324
|
+
productStateHash: input.productStateHash ?? prior?.productStateHash ?? null,
|
|
323
325
|
remainingTurns: input.budget.remainingTurns,
|
|
324
326
|
remainingBudget: input.budget.remainingBudget,
|
|
325
327
|
maxTurns: input.budget.maxTurns,
|
|
@@ -358,25 +360,31 @@ export function bankAcPass(input) {
|
|
|
358
360
|
durablePath = tmpPath;
|
|
359
361
|
}
|
|
360
362
|
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
363
|
+
try {
|
|
364
|
+
const env = { ...(input.environ ?? process.env) };
|
|
365
|
+
const emitter = new RunSummaryEmitter({
|
|
366
|
+
projectRoot: root,
|
|
367
|
+
env,
|
|
368
|
+
component: "ac-pass-banking",
|
|
369
|
+
});
|
|
370
|
+
emitter.emitAcPassBank({
|
|
371
|
+
scope_id: record.scopeId,
|
|
372
|
+
banked_at: record.bankedAt,
|
|
373
|
+
next_action: record.nextAction,
|
|
374
|
+
had_surplus: record.hadSurplus,
|
|
375
|
+
surplus_threshold: record.surplusThreshold,
|
|
376
|
+
remaining_fraction: input.surplus.remainingFraction,
|
|
377
|
+
remaining_turns: record.remainingTurns,
|
|
378
|
+
remaining_budget: record.remainingBudget,
|
|
379
|
+
max_turns: record.maxTurns,
|
|
380
|
+
max_budget: record.maxBudget,
|
|
381
|
+
head_sha: record.headSha,
|
|
377
382
|
path: durablePath,
|
|
378
|
-
}
|
|
379
|
-
}
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
catch {
|
|
386
|
+
// fail-open
|
|
387
|
+
}
|
|
380
388
|
return record;
|
|
381
389
|
}
|
|
382
390
|
/**
|
|
@@ -487,6 +495,7 @@ function recoveredStubRecord(scopeId, findings) {
|
|
|
487
495
|
// valid primary ledger (#3285 Greptile residual).
|
|
488
496
|
bankedAt: "1970-01-01T00:00:00Z",
|
|
489
497
|
headSha: null,
|
|
498
|
+
productStateHash: null,
|
|
490
499
|
remainingTurns: null,
|
|
491
500
|
remainingBudget: null,
|
|
492
501
|
maxTurns: null,
|
|
@@ -616,63 +625,6 @@ export function recordPostBankFinding(projectRoot, scopeId, finding) {
|
|
|
616
625
|
}
|
|
617
626
|
return updated;
|
|
618
627
|
}
|
|
619
|
-
/**
|
|
620
|
-
* Format one JSONL bank-event line for run-summary telemetry (#3285 / #3282).
|
|
621
|
-
*/
|
|
622
|
-
export function formatBankEventLine(event) {
|
|
623
|
-
return JSON.stringify({
|
|
624
|
-
...event,
|
|
625
|
-
ts: typeof event.bankedAt === "string" ? event.bankedAt : utcIso(),
|
|
626
|
-
source: "ac-pass-banking",
|
|
627
|
-
issue: 3285,
|
|
628
|
-
});
|
|
629
|
-
}
|
|
630
|
-
/**
|
|
631
|
-
* Append bank event to DEFT_RUN_SUMMARY_PATH when set.
|
|
632
|
-
* Unset = silent. `-` = stdout. Failures warn once to stderr (fail-open).
|
|
633
|
-
*/
|
|
634
|
-
export function appendBankEventToRunSummary(input) {
|
|
635
|
-
const environ = input.environ ?? process.env;
|
|
636
|
-
const raw = (environ[ENV_RUN_SUMMARY_PATH] ?? "").trim();
|
|
637
|
-
if (!raw) {
|
|
638
|
-
return { written: false, path: null };
|
|
639
|
-
}
|
|
640
|
-
const line = `${formatBankEventLine(input.event)}\n`;
|
|
641
|
-
if (raw === "-") {
|
|
642
|
-
process.stdout.write(line);
|
|
643
|
-
return { written: true, path: "-" };
|
|
644
|
-
}
|
|
645
|
-
try {
|
|
646
|
-
if (input.writeLine) {
|
|
647
|
-
input.writeLine(raw, line);
|
|
648
|
-
}
|
|
649
|
-
else {
|
|
650
|
-
const abs = resolve(raw);
|
|
651
|
-
const parent = dirname(abs);
|
|
652
|
-
if (!existsSync(parent)) {
|
|
653
|
-
mkdirSync(parent, { recursive: true });
|
|
654
|
-
}
|
|
655
|
-
// Contain under the parent directory of the summary file.
|
|
656
|
-
containedWrite({
|
|
657
|
-
root: parent,
|
|
658
|
-
target: abs,
|
|
659
|
-
data: line,
|
|
660
|
-
mode: "append",
|
|
661
|
-
});
|
|
662
|
-
}
|
|
663
|
-
return { written: true, path: raw };
|
|
664
|
-
}
|
|
665
|
-
catch (err) {
|
|
666
|
-
const msg = err instanceof ContainedWriteError
|
|
667
|
-
? err.message
|
|
668
|
-
: err instanceof Error
|
|
669
|
-
? err.message
|
|
670
|
-
: String(err);
|
|
671
|
-
const warn = input.warn ?? ((m) => process.stderr.write(`${m}\n`));
|
|
672
|
-
warn(`[deft ac-pass-banking] run-summary write failed path=${raw}: ${msg} (#3285)`);
|
|
673
|
-
return { written: false, path: raw };
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
628
|
/**
|
|
677
629
|
* Simulated run used by the surplus-insufficient acceptance test (#3285):
|
|
678
630
|
* AC passes → bank → extra checks would exceed budget → ship + report finding.
|
|
@@ -748,6 +700,7 @@ export function maybeBankOnAcPass(input) {
|
|
|
748
700
|
surplus: decision.surplus,
|
|
749
701
|
nextAction,
|
|
750
702
|
headSha: input.headSha ?? null,
|
|
703
|
+
productStateHash: input.productStateHash ?? null,
|
|
751
704
|
now: input.now,
|
|
752
705
|
environ: input.environ,
|
|
753
706
|
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bank / same-session cache reuse for verify:ac and scope:complete (#3387).
|
|
3
|
+
*
|
|
4
|
+
* Green bank + matching product-state hash → accept without re-execution.
|
|
5
|
+
* Missing, stale, or mismatched hash → full walk. Empty/failing still refuse.
|
|
6
|
+
*/
|
|
7
|
+
import { type AcPassBankRecord } from "./ac-pass-banking.js";
|
|
8
|
+
import { type HashProductStateInput } from "./product-state-hash.js";
|
|
9
|
+
import { type CachedVerifyAcSnapshot, type VerifyAcSessionCacheRecord } from "./verify-ac-session-cache.js";
|
|
10
|
+
export type { AcServedFrom } from "./verify-ac-session-cache.js";
|
|
11
|
+
export type AcReuseDecision = {
|
|
12
|
+
readonly kind: "cache";
|
|
13
|
+
readonly servedFrom: "cache";
|
|
14
|
+
readonly hash: string;
|
|
15
|
+
readonly cache: VerifyAcSessionCacheRecord;
|
|
16
|
+
} | {
|
|
17
|
+
readonly kind: "bank";
|
|
18
|
+
readonly servedFrom: "bank";
|
|
19
|
+
readonly hash: string;
|
|
20
|
+
readonly bank: AcPassBankRecord;
|
|
21
|
+
} | {
|
|
22
|
+
readonly kind: "miss";
|
|
23
|
+
readonly servedFrom: "executed";
|
|
24
|
+
readonly hash: string | null;
|
|
25
|
+
readonly reason: string;
|
|
26
|
+
};
|
|
27
|
+
export interface ResolveAcReuseInput extends HashProductStateInput {
|
|
28
|
+
readonly scopeId?: string | null;
|
|
29
|
+
readonly sessionId?: string | null;
|
|
30
|
+
readonly env?: Readonly<Record<string, string | undefined>>;
|
|
31
|
+
/** Default true. Complete walk uses bank; check uses cache then bank. */
|
|
32
|
+
readonly allowCache?: boolean;
|
|
33
|
+
readonly allowBank?: boolean;
|
|
34
|
+
}
|
|
35
|
+
export declare function resolveScopeIdForAcReuse(plan: Record<string, unknown>, explicit?: string | null): string | null;
|
|
36
|
+
/**
|
|
37
|
+
* Decide whether a green bank or same-session cache can replace execution.
|
|
38
|
+
*/
|
|
39
|
+
export declare function resolveAcReuse(input: ResolveAcReuseInput): AcReuseDecision;
|
|
40
|
+
export declare function snapshotFromReuseFields(input: {
|
|
41
|
+
readonly ok: boolean;
|
|
42
|
+
readonly code: 0 | 1 | 2;
|
|
43
|
+
readonly message: string;
|
|
44
|
+
readonly commands: readonly unknown[];
|
|
45
|
+
readonly runs: readonly unknown[];
|
|
46
|
+
readonly rejected?: readonly unknown[];
|
|
47
|
+
readonly sourceRung: string;
|
|
48
|
+
readonly noneStated: boolean;
|
|
49
|
+
readonly acceptance: unknown;
|
|
50
|
+
readonly resolution: string;
|
|
51
|
+
readonly resolvedCommandCount: number;
|
|
52
|
+
}): CachedVerifyAcSnapshot;
|
|
53
|
+
//# sourceMappingURL=ac-pass-reuse.d.ts.map
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bank / same-session cache reuse for verify:ac and scope:complete (#3387).
|
|
3
|
+
*
|
|
4
|
+
* Green bank + matching product-state hash → accept without re-execution.
|
|
5
|
+
* Missing, stale, or mismatched hash → full walk. Empty/failing still refuse.
|
|
6
|
+
*/
|
|
7
|
+
import { readAcPassBank } from "./ac-pass-banking.js";
|
|
8
|
+
import { hashProductState } from "./product-state-hash.js";
|
|
9
|
+
import { readVerifyAcSessionCache, resolveVerifyAcSessionId, } from "./verify-ac-session-cache.js";
|
|
10
|
+
function isUsableBank(bank) {
|
|
11
|
+
if (bank.bankedAt === "1970-01-01T00:00:00Z")
|
|
12
|
+
return false;
|
|
13
|
+
const hash = bank.productStateHash;
|
|
14
|
+
return typeof hash === "string" && hash.length > 0;
|
|
15
|
+
}
|
|
16
|
+
export function resolveScopeIdForAcReuse(plan, explicit) {
|
|
17
|
+
const injected = explicit?.trim() ?? "";
|
|
18
|
+
if (injected.length > 0)
|
|
19
|
+
return injected;
|
|
20
|
+
if (typeof plan.id === "string" && plan.id.trim().length > 0) {
|
|
21
|
+
return plan.id.trim();
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Decide whether a green bank or same-session cache can replace execution.
|
|
27
|
+
*/
|
|
28
|
+
export function resolveAcReuse(input) {
|
|
29
|
+
const allowCache = input.allowCache !== false;
|
|
30
|
+
const allowBank = input.allowBank !== false;
|
|
31
|
+
const scopeId = resolveScopeIdForAcReuse(input.plan, input.scopeId);
|
|
32
|
+
if (scopeId === null) {
|
|
33
|
+
return { kind: "miss", servedFrom: "executed", hash: null, reason: "no scope id" };
|
|
34
|
+
}
|
|
35
|
+
const hashed = hashProductState(input);
|
|
36
|
+
if (!hashed.complete) {
|
|
37
|
+
return {
|
|
38
|
+
kind: "miss",
|
|
39
|
+
servedFrom: "executed",
|
|
40
|
+
hash: hashed.digest,
|
|
41
|
+
reason: "incomplete product-state hash",
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const sessionId = resolveVerifyAcSessionId(input.env, input.sessionId);
|
|
45
|
+
if (allowCache && sessionId !== null) {
|
|
46
|
+
const cache = readVerifyAcSessionCache(input.projectRoot, sessionId, scopeId);
|
|
47
|
+
if (cache !== null && cache.productStateHash === hashed.digest) {
|
|
48
|
+
return { kind: "cache", servedFrom: "cache", hash: hashed.digest, cache };
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (allowBank) {
|
|
52
|
+
const bank = readAcPassBank(input.projectRoot, scopeId);
|
|
53
|
+
if (bank !== null && isUsableBank(bank) && bank.productStateHash === hashed.digest) {
|
|
54
|
+
return { kind: "bank", servedFrom: "bank", hash: hashed.digest, bank };
|
|
55
|
+
}
|
|
56
|
+
if (bank !== null && !isUsableBank(bank)) {
|
|
57
|
+
return {
|
|
58
|
+
kind: "miss",
|
|
59
|
+
servedFrom: "executed",
|
|
60
|
+
hash: hashed.digest,
|
|
61
|
+
reason: "stale or incomplete bank",
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
if (bank !== null && bank.productStateHash !== hashed.digest) {
|
|
65
|
+
return {
|
|
66
|
+
kind: "miss",
|
|
67
|
+
servedFrom: "executed",
|
|
68
|
+
hash: hashed.digest,
|
|
69
|
+
reason: "product-state hash mismatch",
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
kind: "miss",
|
|
75
|
+
servedFrom: "executed",
|
|
76
|
+
hash: hashed.digest,
|
|
77
|
+
reason: "no reusable result",
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export function snapshotFromReuseFields(input) {
|
|
81
|
+
return {
|
|
82
|
+
ok: input.ok,
|
|
83
|
+
code: input.code,
|
|
84
|
+
message: input.message,
|
|
85
|
+
commands: input.commands,
|
|
86
|
+
runs: input.runs,
|
|
87
|
+
rejected: input.rejected,
|
|
88
|
+
sourceRung: input.sourceRung,
|
|
89
|
+
noneStated: input.noneStated,
|
|
90
|
+
acceptance: input.acceptance,
|
|
91
|
+
resolution: input.resolution,
|
|
92
|
+
resolvedCommandCount: input.resolvedCommandCount,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=ac-pass-reuse.js.map
|
package/dist/session/git.js
CHANGED
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
|
+
function coerceGitBytes(value) {
|
|
4
|
+
if (Buffer.isBuffer(value))
|
|
5
|
+
return value;
|
|
6
|
+
if (typeof value === "string")
|
|
7
|
+
return Buffer.from(value, "utf8");
|
|
8
|
+
return Buffer.alloc(0);
|
|
9
|
+
}
|
|
10
|
+
/** `-z` porcelain is byte-oriented; UTF-8 would turn invalid names into U+FFFD. */
|
|
11
|
+
function gitStdoutString(raw, args) {
|
|
12
|
+
if (args.includes("-z"))
|
|
13
|
+
return raw.toString("latin1");
|
|
14
|
+
const utf8 = raw.toString("utf8");
|
|
15
|
+
if (Buffer.from(utf8, "utf8").equals(raw))
|
|
16
|
+
return utf8.trimEnd();
|
|
17
|
+
return raw.toString("latin1").trimEnd();
|
|
18
|
+
}
|
|
3
19
|
export const defaultGitRunner = (projectRoot, args) => {
|
|
4
20
|
try {
|
|
5
21
|
const stdout = execFileSync("git", [...args], {
|
|
6
22
|
cwd: projectRoot,
|
|
7
|
-
encoding: "utf8",
|
|
8
23
|
stdio: ["ignore", "pipe", "pipe"],
|
|
9
24
|
});
|
|
10
|
-
return { code: 0, stdout: stdout
|
|
25
|
+
return { code: 0, stdout: gitStdoutString(coerceGitBytes(stdout), args), stderr: "" };
|
|
11
26
|
}
|
|
12
27
|
catch (err) {
|
|
13
28
|
const e = err;
|
|
@@ -16,8 +31,8 @@ export const defaultGitRunner = (projectRoot, args) => {
|
|
|
16
31
|
}
|
|
17
32
|
return {
|
|
18
33
|
code: typeof e.status === "number" ? e.status : 2,
|
|
19
|
-
stdout:
|
|
20
|
-
stderr:
|
|
34
|
+
stdout: gitStdoutString(coerceGitBytes(e.stdout), args),
|
|
35
|
+
stderr: coerceGitBytes(e.stderr).toString("utf8").trimEnd(),
|
|
21
36
|
};
|
|
22
37
|
}
|
|
23
38
|
};
|
package/dist/session/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from "./ac-pass-banking.js";
|
|
2
|
+
export * from "./ac-pass-reuse.js";
|
|
2
3
|
export * from "./active-cli.js";
|
|
3
4
|
export * from "./ceremony-dial-evidence.js";
|
|
4
5
|
export * from "./compact-ritual.js";
|
|
@@ -6,11 +7,13 @@ export * from "./deposit-sha.js";
|
|
|
6
7
|
export * from "./effort-budget.js";
|
|
7
8
|
export * from "./git.js";
|
|
8
9
|
export * from "./json.js";
|
|
10
|
+
export * from "./occupancy.js";
|
|
9
11
|
export * from "./openclaw-soft-rebind-deposit.js";
|
|
10
12
|
export * from "./orientation-compression.js";
|
|
11
13
|
export * from "./orientation-state.js";
|
|
12
14
|
export * from "./posture.js";
|
|
13
15
|
export * from "./process-cost.js";
|
|
16
|
+
export * from "./product-state-hash.js";
|
|
14
17
|
export * from "./resume-conditions.js";
|
|
15
18
|
export * from "./ritual-sentinel.js";
|
|
16
19
|
export * from "./session-ready.js";
|
|
@@ -18,5 +21,6 @@ export * from "./session-start.js";
|
|
|
18
21
|
export * from "./session-start-hook.js";
|
|
19
22
|
export * from "./time.js";
|
|
20
23
|
export * from "./toolchain-preflight.js";
|
|
24
|
+
export * from "./verify-ac-session-cache.js";
|
|
21
25
|
export * from "./verify-session-ritual.js";
|
|
22
26
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/session/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from "./ac-pass-banking.js";
|
|
2
|
+
export * from "./ac-pass-reuse.js";
|
|
2
3
|
export * from "./active-cli.js";
|
|
3
4
|
export * from "./ceremony-dial-evidence.js";
|
|
4
5
|
export * from "./compact-ritual.js";
|
|
@@ -6,11 +7,13 @@ export * from "./deposit-sha.js";
|
|
|
6
7
|
export * from "./effort-budget.js";
|
|
7
8
|
export * from "./git.js";
|
|
8
9
|
export * from "./json.js";
|
|
10
|
+
export * from "./occupancy.js";
|
|
9
11
|
export * from "./openclaw-soft-rebind-deposit.js";
|
|
10
12
|
export * from "./orientation-compression.js";
|
|
11
13
|
export * from "./orientation-state.js";
|
|
12
14
|
export * from "./posture.js";
|
|
13
15
|
export * from "./process-cost.js";
|
|
16
|
+
export * from "./product-state-hash.js";
|
|
14
17
|
export * from "./resume-conditions.js";
|
|
15
18
|
export * from "./ritual-sentinel.js";
|
|
16
19
|
export * from "./session-ready.js";
|
|
@@ -18,5 +21,6 @@ export * from "./session-start.js";
|
|
|
18
21
|
export * from "./session-start-hook.js";
|
|
19
22
|
export * from "./time.js";
|
|
20
23
|
export * from "./toolchain-preflight.js";
|
|
24
|
+
export * from "./verify-ac-session-cache.js";
|
|
21
25
|
export * from "./verify-session-ritual.js";
|
|
22
26
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { basename } from "node:path";
|
|
2
|
+
import { containedWrite } from "../fs/contained-write.js";
|
|
3
|
+
import { applyWorktreeOccupancy, releaseOccupancy } from "./occupancy.js";
|
|
4
|
+
export function runOccupancyStressRounds(input) {
|
|
5
|
+
for (let i = 0; i < input.rounds; i += 1) {
|
|
6
|
+
const claimed = applyWorktreeOccupancy(input.root, {
|
|
7
|
+
sessionId: input.sessionId,
|
|
8
|
+
now: new Date(),
|
|
9
|
+
});
|
|
10
|
+
if (claimed.code !== 0)
|
|
11
|
+
continue;
|
|
12
|
+
containedWrite({
|
|
13
|
+
root: input.root,
|
|
14
|
+
target: basename(input.logPath),
|
|
15
|
+
data: `ENTER ${input.sessionId}\n`,
|
|
16
|
+
mode: "append",
|
|
17
|
+
});
|
|
18
|
+
containedWrite({
|
|
19
|
+
root: input.root,
|
|
20
|
+
target: basename(input.logPath),
|
|
21
|
+
data: `LEAVE ${input.sessionId}\n`,
|
|
22
|
+
mode: "append",
|
|
23
|
+
});
|
|
24
|
+
releaseOccupancy(input.root, { sessionId: input.sessionId, now: new Date() });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const root = process.env.OCCUPANCY_STRESS_ROOT ?? "";
|
|
28
|
+
if (root.length > 0) {
|
|
29
|
+
runOccupancyStressRounds({
|
|
30
|
+
root,
|
|
31
|
+
logPath: process.env.OCCUPANCY_STRESS_LOG ?? "",
|
|
32
|
+
sessionId: process.env.OCCUPANCY_STRESS_SESSION ?? "",
|
|
33
|
+
rounds: Number(process.env.OCCUPANCY_STRESS_ROUNDS ?? "0"),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=occupancy-stress-worker.js.map
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worktree occupancy lease (#3433).
|
|
3
|
+
*
|
|
4
|
+
* Ritual-state is "this session completed ceremony." Occupancy is "who may
|
|
5
|
+
* mutate this tree right now." Those lifetimes differ; do not overload
|
|
6
|
+
* ritual-state.json. Join negotiation (`occupancy:request`) is out of scope.
|
|
7
|
+
*
|
|
8
|
+
* Concurrency model:
|
|
9
|
+
* - Assumptions: local filesystem; cooperating processes on one machine.
|
|
10
|
+
* - Guarantees: mutual exclusion under crash-free operation; detect-and-abort
|
|
11
|
+
* if the sidecar lock is compromised (fence before rename/unlink).
|
|
12
|
+
* - Non-goals: network filesystems; Byzantine processes; perfect off-Linux
|
|
13
|
+
* PID-reuse detection (hard age cap + fence instead).
|
|
14
|
+
*/
|
|
15
|
+
import { type LockDeps } from "../slice/lock.js";
|
|
16
|
+
export declare const OCCUPANCY_SCHEMA_VERSION = 1;
|
|
17
|
+
export declare const OCCUPANCY_RELPATH: readonly [".deft", "occupancy.json"];
|
|
18
|
+
/** Crash recovery TTL: 20 minutes without heartbeat (15–30 window). */
|
|
19
|
+
export declare const OCCUPANCY_TTL_MS: number;
|
|
20
|
+
export declare const OCCUPANCY_INTENTS: readonly ["mutation", "swarm", "review"];
|
|
21
|
+
export type OccupancyIntent = (typeof OCCUPANCY_INTENTS)[number];
|
|
22
|
+
export declare const OCCUPANCY_JOIN_PROTOCOLS: readonly ["none", "heartbeat-file", "parent-message"];
|
|
23
|
+
export type OccupancyJoinProtocol = (typeof OCCUPANCY_JOIN_PROTOCOLS)[number];
|
|
24
|
+
export interface OccupancyRecord {
|
|
25
|
+
readonly schemaVersion: number;
|
|
26
|
+
readonly sessionId: string;
|
|
27
|
+
readonly worktreePath: string;
|
|
28
|
+
readonly intent: OccupancyIntent;
|
|
29
|
+
readonly claimedAt: Date;
|
|
30
|
+
readonly heartbeatAt: Date;
|
|
31
|
+
readonly host: string;
|
|
32
|
+
readonly address: string;
|
|
33
|
+
readonly retainCapable: boolean;
|
|
34
|
+
readonly joinProtocol: OccupancyJoinProtocol;
|
|
35
|
+
readonly raw: Record<string, unknown>;
|
|
36
|
+
}
|
|
37
|
+
export type OccupancyAction = "claimed" | "heartbeat" | "stolen" | "denied" | "released";
|
|
38
|
+
export interface OccupancyDecision {
|
|
39
|
+
readonly action: OccupancyAction;
|
|
40
|
+
readonly sessionId: string;
|
|
41
|
+
readonly record: OccupancyRecord | null;
|
|
42
|
+
readonly path: string;
|
|
43
|
+
readonly message: string;
|
|
44
|
+
readonly code: number;
|
|
45
|
+
}
|
|
46
|
+
export interface ApplyOccupancyInput {
|
|
47
|
+
readonly sessionId?: string;
|
|
48
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
49
|
+
readonly now?: Date;
|
|
50
|
+
readonly intent?: OccupancyIntent;
|
|
51
|
+
readonly newSessionId?: () => string;
|
|
52
|
+
readonly steal?: boolean;
|
|
53
|
+
readonly confirm?: boolean;
|
|
54
|
+
readonly occupant?: string;
|
|
55
|
+
readonly host?: string;
|
|
56
|
+
readonly address?: string;
|
|
57
|
+
readonly retainCapable?: boolean;
|
|
58
|
+
readonly joinProtocol?: OccupancyJoinProtocol;
|
|
59
|
+
/** When false, evaluate only (no write). Steal still writes. */
|
|
60
|
+
readonly write?: boolean;
|
|
61
|
+
/** Test seam for lock wait / timeout. */
|
|
62
|
+
readonly lockDeps?: LockDeps;
|
|
63
|
+
}
|
|
64
|
+
export declare function occupancyPath(projectRoot: string): string;
|
|
65
|
+
export declare function heartbeatAgeSeconds(record: OccupancyRecord, now?: Date): number;
|
|
66
|
+
export declare function isOccupancyExpired(record: OccupancyRecord, now?: Date, ttlMs?: number): boolean;
|
|
67
|
+
export declare function formatOccupancyRemediation(record: OccupancyRecord, now?: Date): string;
|
|
68
|
+
export declare function resolveOccupancySessionId(input?: ApplyOccupancyInput): string;
|
|
69
|
+
export declare function readOccupancy(projectRoot: string): OccupancyRecord | null;
|
|
70
|
+
export declare function liveOccupant(projectRoot: string, now?: Date, ttlMs?: number): OccupancyRecord | null;
|
|
71
|
+
export declare function applyWorktreeOccupancy(projectRoot: string, input?: ApplyOccupancyInput): OccupancyDecision;
|
|
72
|
+
export declare function stealOccupancy(projectRoot: string, input?: ApplyOccupancyInput): OccupancyDecision;
|
|
73
|
+
export declare function releaseOccupancy(projectRoot: string, input?: {
|
|
74
|
+
readonly sessionId?: string;
|
|
75
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
76
|
+
readonly now?: Date;
|
|
77
|
+
readonly swarmCloseout?: boolean;
|
|
78
|
+
readonly lockDeps?: LockDeps;
|
|
79
|
+
}): OccupancyDecision;
|
|
80
|
+
export declare function evaluateOccupancyWriteGate(projectRoot: string, input?: {
|
|
81
|
+
readonly sessionId?: string;
|
|
82
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
83
|
+
readonly now?: Date;
|
|
84
|
+
}): {
|
|
85
|
+
allow: boolean;
|
|
86
|
+
message: string | null;
|
|
87
|
+
occupant: OccupancyRecord | null;
|
|
88
|
+
};
|
|
89
|
+
/** Close-out identity comes from the launch manifest or DEFT_SESSION_ID — never occupancy.json. */
|
|
90
|
+
export declare function releaseSwarmOccupancy(projectRoot: string, input?: {
|
|
91
|
+
readonly sessionId?: string;
|
|
92
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
93
|
+
readonly now?: Date;
|
|
94
|
+
readonly lockDeps?: LockDeps;
|
|
95
|
+
}): OccupancyDecision;
|
|
96
|
+
export declare function runOccupancySteal(projectRoot: string, input?: ApplyOccupancyInput): OccupancyDecision;
|
|
97
|
+
//# sourceMappingURL=occupancy.d.ts.map
|