@deftai/directive-core 0.104.0 → 0.106.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/authz/classify.js +1108 -67
- 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 +34 -4
- 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/forward-coverage/diff-coverage.d.ts +39 -0
- package/dist/forward-coverage/diff-coverage.js +112 -0
- package/dist/forward-coverage/diff-lines.d.ts +19 -0
- package/dist/forward-coverage/diff-lines.js +173 -0
- package/dist/forward-coverage/evaluate.d.ts +24 -9
- package/dist/forward-coverage/evaluate.js +125 -19
- 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.d.ts +1 -1
- package/dist/init-deposit/agent-hooks.js +18 -16
- 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 +47 -1
- package/dist/intake/clause-derivation.js +238 -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/lifecycle-visible/evaluate.d.ts +98 -0
- package/dist/lifecycle-visible/evaluate.js +710 -0
- package/dist/lifecycle-visible/index.d.ts +2 -0
- package/dist/lifecycle-visible/index.js +2 -0
- package/dist/literal-acceptance/capture.d.ts +10 -0
- package/dist/literal-acceptance/capture.js +226 -77
- 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/orchestration/judgment-policy.d.ts +13 -0
- package/dist/orchestration/judgment-policy.js +15 -0
- package/dist/orchestration/probe-session.js +13 -8
- package/dist/orchestration/verify-judgment-gates.d.ts +4 -0
- package/dist/orchestration/verify-judgment-gates.js +43 -11
- 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 +11 -21
- 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/host-hooks.d.ts +20 -0
- package/dist/policy/host-hooks.js +121 -2
- package/dist/policy/index.d.ts +7 -0
- package/dist/policy/index.js +66 -7
- package/dist/policy/org-force-on-migration.js +2 -1
- package/dist/policy/plan-extensions.d.ts +1 -1
- package/dist/policy/plan-extensions.js +2 -0
- package/dist/policy/product-signal.js +6 -7
- package/dist/policy/project-invariants.d.ts +50 -0
- package/dist/policy/project-invariants.js +205 -0
- package/dist/policy/require-human-merge.js +8 -6
- package/dist/policy/resolve.d.ts +7 -2
- package/dist/policy/resolve.js +25 -8
- 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/policy/value-feedback.js +7 -8
- 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/preflight-cache/evaluate.d.ts +12 -0
- package/dist/preflight-cache/evaluate.js +15 -1
- package/dist/preflight-cache/index.d.ts +1 -1
- package/dist/preflight-cache/index.js +1 -1
- 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 +16 -0
- package/dist/product-first-done-gate/evaluate.js +298 -34
- 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/release/closed-verb-gate.d.ts +12 -0
- package/dist/release/closed-verb-gate.js +51 -0
- package/dist/release/index.d.ts +1 -0
- package/dist/release/index.js +1 -0
- package/dist/release/pipeline.js +7 -0
- package/dist/release/types.d.ts +12 -0
- package/dist/render/constants.d.ts +2 -1
- package/dist/render/constants.js +2 -1
- package/dist/render/framework-commands.js +4 -0
- package/dist/render/spec-validate.js +23 -12
- 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 +33 -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/main.js +15 -5
- 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/promote-from-issue.js +5 -5
- 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 +67 -7
- 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 +9 -36
- package/dist/session/ac-pass-banking.js +33 -79
- 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/process-cost.d.ts +32 -10
- package/dist/session/process-cost.js +189 -1
- package/dist/session/product-state-hash.d.ts +26 -0
- package/dist/session/product-state-hash.js +700 -0
- package/dist/session/ritual-entrypoint.js +16 -1
- package/dist/session/session-ready.d.ts +2 -0
- package/dist/session/session-ready.js +52 -30
- package/dist/session/session-start.d.ts +13 -0
- package/dist/session/session-start.js +103 -9
- 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 +28 -0
- package/dist/session/verify-session-ritual.js +97 -5
- 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-cli.d.ts +7 -2
- package/dist/swarm/finalize-cohort-cli.js +165 -35
- package/dist/swarm/finalize-cohort.d.ts +1 -0
- package/dist/swarm/finalize-cohort.js +47 -4
- 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 +15 -3
- package/dist/swarm/routing-verify.d.ts +13 -1
- package/dist/swarm/routing-verify.js +60 -21
- 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/triage/bootstrap/index.js +6 -6
- package/dist/triage/help/registry-data.d.ts +1 -1
- package/dist/triage/help/registry-data.js +1 -1
- package/dist/triage/welcome/writers.d.ts +1 -1
- package/dist/triage/welcome/writers.js +10 -5
- 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/value/readback.d.ts +4 -1
- package/dist/value/readback.js +51 -12
- 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/vbrief-validate/schema.d.ts +4 -0
- package/dist/vbrief-validate/schema.js +1 -1
- 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-env/agent-hook-readiness.d.ts +2 -2
- package/dist/verify-env/agent-hook-readiness.js +12 -8
- package/dist/verify-env/agent-hooks-live-probe.d.ts +5 -1
- package/dist/verify-env/agent-hooks-live-probe.js +26 -5
- package/dist/verify-env/agent-hooks.js +3 -4
- 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 +7 -3
package/dist/swarm/launch.js
CHANGED
|
@@ -5,6 +5,7 @@ import { inferGithubAuthMode } from "../intake/github-auth-modes.js";
|
|
|
5
5
|
import { getPlatformCapabilities } from "../intake/platform-capabilities.js";
|
|
6
6
|
import { hasArtifactSuffix, resolveLifecycleFolder, stripArtifactSuffix, } from "../layout/resolve.js";
|
|
7
7
|
import { evaluate as preflightEvaluate } from "../preflight/evaluate.js";
|
|
8
|
+
import { applyWorktreeOccupancy } from "../session/occupancy.js";
|
|
8
9
|
import { issueNumbersFromPlan, scopeMetadataRank } from "../triage/queue/scope-walk.js";
|
|
9
10
|
import { selectionOrderingKey } from "../triage/queue/selection.js";
|
|
10
11
|
import { DEFAULT_BASE_BRANCH, EXIT_CONFIG_ERROR, EXIT_GATE_FAILED, EXIT_OK, GATE_ADVISE, GATE_ENFORCE, LEAF_CODING_WORKER_ROLE, } from "./constants.js";
|
|
@@ -334,6 +335,121 @@ function deriveBranch(group, sid) {
|
|
|
334
335
|
function defaultWorktree(projectRoot, sid) {
|
|
335
336
|
return join(projectRoot, ".deft-scratch", "worktrees", safeSegment(sid)).replace(/\\/g, "/");
|
|
336
337
|
}
|
|
338
|
+
export const SWARM_LAUNCH_MANIFEST_RELPATH = [".deft", "swarm-launch-manifest.json"];
|
|
339
|
+
export const SWARM_LAUNCH_OCCUPANCY_DIR = [".deft", "swarm-launch-occupancy"];
|
|
340
|
+
export function swarmLaunchManifestPath(projectRoot) {
|
|
341
|
+
return join(resolve(projectRoot), ...SWARM_LAUNCH_MANIFEST_RELPATH);
|
|
342
|
+
}
|
|
343
|
+
export function occupancyCohortKey(allocationPlanId, storyIds = []) {
|
|
344
|
+
const plan = allocationPlanId?.trim() ?? "";
|
|
345
|
+
if (plan.length > 0)
|
|
346
|
+
return `plan:${plan}`;
|
|
347
|
+
const stories = [...storyIds].map((id) => id.trim()).filter((id) => id.length > 0);
|
|
348
|
+
stories.sort();
|
|
349
|
+
return `stories:${stories.join(",")}`;
|
|
350
|
+
}
|
|
351
|
+
export function launchOccupancyRecordRelpath(cohortKey) {
|
|
352
|
+
return [...SWARM_LAUNCH_OCCUPANCY_DIR, `${safeSegment(cohortKey)}.json`];
|
|
353
|
+
}
|
|
354
|
+
function parseLaunchOccupancyRecord(payload) {
|
|
355
|
+
if (payload === null || typeof payload !== "object" || Array.isArray(payload))
|
|
356
|
+
return null;
|
|
357
|
+
const obj = payload;
|
|
358
|
+
const sessionId = typeof obj.occupancy_session_id === "string" ? obj.occupancy_session_id.trim() : "";
|
|
359
|
+
if (sessionId.length === 0)
|
|
360
|
+
return null;
|
|
361
|
+
const cohortKey = typeof obj.cohort_key === "string" ? obj.cohort_key.trim() : "";
|
|
362
|
+
if (cohortKey.length === 0)
|
|
363
|
+
return null;
|
|
364
|
+
const planRaw = obj.allocation_plan_id;
|
|
365
|
+
const allocationPlanId = typeof planRaw === "string" && planRaw.trim().length > 0 ? planRaw.trim() : null;
|
|
366
|
+
const storyIds = Array.isArray(obj.story_ids)
|
|
367
|
+
? obj.story_ids.filter((id) => typeof id === "string" && id.trim().length > 0)
|
|
368
|
+
: [];
|
|
369
|
+
return {
|
|
370
|
+
allocation_plan_id: allocationPlanId,
|
|
371
|
+
occupancy_session_id: sessionId,
|
|
372
|
+
story_ids: storyIds,
|
|
373
|
+
cohort_key: cohortKey,
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
function storySetEquals(left, right) {
|
|
377
|
+
if (left.length !== right.size)
|
|
378
|
+
return false;
|
|
379
|
+
return left.every((id) => right.has(id));
|
|
380
|
+
}
|
|
381
|
+
function readLaunchOccupancyFile(projectRoot, cohortKey) {
|
|
382
|
+
const path = join(resolve(projectRoot), ...launchOccupancyRecordRelpath(cohortKey));
|
|
383
|
+
try {
|
|
384
|
+
if (!existsSync(path))
|
|
385
|
+
return null;
|
|
386
|
+
return parseLaunchOccupancyRecord(JSON.parse(readFileSync(path, { encoding: "utf8" })));
|
|
387
|
+
}
|
|
388
|
+
catch {
|
|
389
|
+
return null;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
function listLaunchOccupancyRecords(projectRoot) {
|
|
393
|
+
const dir = join(resolve(projectRoot), ...SWARM_LAUNCH_OCCUPANCY_DIR);
|
|
394
|
+
if (!existsSync(dir))
|
|
395
|
+
return [];
|
|
396
|
+
const out = [];
|
|
397
|
+
for (const name of readdirSync(dir)) {
|
|
398
|
+
if (!name.endsWith(".json"))
|
|
399
|
+
continue;
|
|
400
|
+
try {
|
|
401
|
+
const parsed = parseLaunchOccupancyRecord(JSON.parse(readFileSync(join(dir, name), { encoding: "utf8" })));
|
|
402
|
+
if (parsed !== null)
|
|
403
|
+
out.push(parsed);
|
|
404
|
+
}
|
|
405
|
+
catch {
|
|
406
|
+
/* skip unreadable cohort slot */
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return out;
|
|
410
|
+
}
|
|
411
|
+
export function persistLaunchOccupancyRecord(projectRoot, record) {
|
|
412
|
+
const relpath = launchOccupancyRecordRelpath(record.cohort_key);
|
|
413
|
+
const absDir = join(resolve(projectRoot), ...SWARM_LAUNCH_OCCUPANCY_DIR);
|
|
414
|
+
mkdirSync(absDir, { recursive: true });
|
|
415
|
+
containedWrite({
|
|
416
|
+
root: projectRoot,
|
|
417
|
+
target: join(...relpath),
|
|
418
|
+
data: `${JSON.stringify(record, null, 2)}\n`,
|
|
419
|
+
mode: "replace",
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
export function resolveLaunchOccupancySessionId(projectRoot, query = {}) {
|
|
423
|
+
const storyIds = (query.storyIds ?? []).map((id) => id.trim()).filter((id) => id.length > 0);
|
|
424
|
+
const requestedKey = occupancyCohortKey(query.allocationPlanId, storyIds);
|
|
425
|
+
const exact = readLaunchOccupancyFile(projectRoot, requestedKey);
|
|
426
|
+
if (exact !== null) {
|
|
427
|
+
const wantedPlan = query.allocationPlanId?.trim() ?? "";
|
|
428
|
+
if (exact.cohort_key !== requestedKey) {
|
|
429
|
+
return { sessionId: "", reason: "wrong-cohort" };
|
|
430
|
+
}
|
|
431
|
+
if (wantedPlan.length > 0 && exact.allocation_plan_id !== wantedPlan) {
|
|
432
|
+
return { sessionId: "", reason: "wrong-cohort" };
|
|
433
|
+
}
|
|
434
|
+
return { sessionId: exact.occupancy_session_id, reason: "ok" };
|
|
435
|
+
}
|
|
436
|
+
if ((query.allocationPlanId?.trim() ?? "").length > 0) {
|
|
437
|
+
return { sessionId: "", reason: "missing" };
|
|
438
|
+
}
|
|
439
|
+
if (storyIds.length === 0) {
|
|
440
|
+
return { sessionId: "", reason: "missing" };
|
|
441
|
+
}
|
|
442
|
+
const wanted = new Set(storyIds);
|
|
443
|
+
const matches = listLaunchOccupancyRecords(projectRoot).filter((rec) => storySetEquals(rec.story_ids, wanted));
|
|
444
|
+
if (matches.length === 0) {
|
|
445
|
+
return { sessionId: "", reason: "missing" };
|
|
446
|
+
}
|
|
447
|
+
const sessionIds = new Set(matches.map((rec) => rec.occupancy_session_id));
|
|
448
|
+
if (sessionIds.size !== 1) {
|
|
449
|
+
return { sessionId: "", reason: "wrong-cohort" };
|
|
450
|
+
}
|
|
451
|
+
return { sessionId: matches[0]?.occupancy_session_id ?? "", reason: "ok" };
|
|
452
|
+
}
|
|
337
453
|
export function buildManifest(resolved, options) {
|
|
338
454
|
const cohortVbriefs = resolved.map((s) => s.relpath);
|
|
339
455
|
const records = options.worktreeRecords ?? new Map();
|
|
@@ -360,6 +476,9 @@ export function buildManifest(resolved, options) {
|
|
|
360
476
|
branch: deriveBranch(options.group ?? null, story.story_id),
|
|
361
477
|
allocation_context: allocationContext,
|
|
362
478
|
};
|
|
479
|
+
if (options.occupancySessionId !== undefined && options.occupancySessionId !== null) {
|
|
480
|
+
entry.occupancy_session_id = options.occupancySessionId;
|
|
481
|
+
}
|
|
363
482
|
if (options.subagentBackend !== undefined && options.subagentBackend !== null) {
|
|
364
483
|
entry.subagent_backend = options.subagentBackend;
|
|
365
484
|
}
|
|
@@ -562,6 +681,17 @@ export function swarmLaunch(args) {
|
|
|
562
681
|
? dispatchProviderFor(backend.backend_id)
|
|
563
682
|
: null;
|
|
564
683
|
const workerRoleValue = routingFile !== null || backend !== null ? LEAF_CODING_WORKER_ROLE : null;
|
|
684
|
+
const occupancy = applyWorktreeOccupancy(projectRoot, {
|
|
685
|
+
env: args.environ ?? process.env,
|
|
686
|
+
intent: "swarm",
|
|
687
|
+
});
|
|
688
|
+
if (occupancy.code !== 0) {
|
|
689
|
+
return {
|
|
690
|
+
exitCode: EXIT_GATE_FAILED,
|
|
691
|
+
stdout: "",
|
|
692
|
+
stderr: `${occupancy.message}\n`,
|
|
693
|
+
};
|
|
694
|
+
}
|
|
565
695
|
const manifest = buildManifest(ordered, {
|
|
566
696
|
projectRoot,
|
|
567
697
|
group: args.group ?? null,
|
|
@@ -578,8 +708,33 @@ export function swarmLaunch(args) {
|
|
|
578
708
|
modelSource,
|
|
579
709
|
runtimeMode,
|
|
580
710
|
githubAuthMode,
|
|
711
|
+
occupancySessionId: occupancy.sessionId,
|
|
581
712
|
});
|
|
582
713
|
const rendered = `${JSON.stringify(manifest, null, 2)}\n`;
|
|
714
|
+
const storyIds = ordered.map((story) => story.story_id);
|
|
715
|
+
const cohortKey = occupancyCohortKey(allocationPlanId, storyIds);
|
|
716
|
+
try {
|
|
717
|
+
mkdirSync(dirname(swarmLaunchManifestPath(projectRoot)), { recursive: true });
|
|
718
|
+
containedWrite({
|
|
719
|
+
root: projectRoot,
|
|
720
|
+
target: join(...SWARM_LAUNCH_MANIFEST_RELPATH),
|
|
721
|
+
data: rendered,
|
|
722
|
+
mode: "replace",
|
|
723
|
+
});
|
|
724
|
+
persistLaunchOccupancyRecord(projectRoot, {
|
|
725
|
+
allocation_plan_id: allocationPlanId,
|
|
726
|
+
occupancy_session_id: occupancy.sessionId,
|
|
727
|
+
story_ids: storyIds,
|
|
728
|
+
cohort_key: cohortKey,
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
catch (exc) {
|
|
732
|
+
return {
|
|
733
|
+
exitCode: EXIT_CONFIG_ERROR,
|
|
734
|
+
stdout: "",
|
|
735
|
+
stderr: `Error: could not persist launch occupancy_session_id: ${String(exc)}\n`,
|
|
736
|
+
};
|
|
737
|
+
}
|
|
583
738
|
if (args.output !== undefined && args.output !== null) {
|
|
584
739
|
try {
|
|
585
740
|
// #2980 wave D: product write sink routes through containedWrite.
|
|
@@ -1,3 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* `routing set` CLI entry.
|
|
4
|
+
*
|
|
5
|
+
* `environ` is the same injected-environment seam `resolveDispatchProvider` and
|
|
6
|
+
* `resolveRoutingPath` already carry (default `process.env`, so production
|
|
7
|
+
* behaviour is unchanged). Tests drive this entry with a constructed
|
|
8
|
+
* environment instead of subtracting known host vars from the ambient one --
|
|
9
|
+
* a denylist that silently rots every time a new host signal is added (#3494,
|
|
10
|
+
* after #3134 / #3492).
|
|
11
|
+
*/
|
|
12
|
+
export declare function routingSetMain(argv?: string[], environ?: NodeJS.ProcessEnv): number;
|
|
3
13
|
//# sourceMappingURL=routing-set-cli.d.ts.map
|
|
@@ -4,7 +4,17 @@ import { fileURLToPath } from "node:url";
|
|
|
4
4
|
import { PROJECTION_CONTAINMENT_REFUSED_EXIT_CODE, ProjectionContainmentError, } from "../fs/projection-containment.js";
|
|
5
5
|
import { EXIT_CONFIG_ERROR, EXIT_OK } from "./constants.js";
|
|
6
6
|
import { HARNESS_BOUND_PROVIDERS, ROUTING_MODE_HARNESS_DEFAULT, ROUTING_MODE_PINNED, resolveDispatchProvider, resolveRoutingPath, SWARM_WORKER_ROLES, writeModelDecision, } from "./routing.js";
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* `routing set` CLI entry.
|
|
9
|
+
*
|
|
10
|
+
* `environ` is the same injected-environment seam `resolveDispatchProvider` and
|
|
11
|
+
* `resolveRoutingPath` already carry (default `process.env`, so production
|
|
12
|
+
* behaviour is unchanged). Tests drive this entry with a constructed
|
|
13
|
+
* environment instead of subtracting known host vars from the ambient one --
|
|
14
|
+
* a denylist that silently rots every time a new host signal is added (#3494,
|
|
15
|
+
* after #3134 / #3492).
|
|
16
|
+
*/
|
|
17
|
+
export function routingSetMain(argv = process.argv.slice(2), environ = process.env) {
|
|
8
18
|
let projectRoot = ".";
|
|
9
19
|
let provider = null;
|
|
10
20
|
let role = null;
|
|
@@ -12,6 +22,8 @@ export function routingSetMain(argv = process.argv.slice(2)) {
|
|
|
12
22
|
let harnessDefault = false;
|
|
13
23
|
for (let i = 0; i < argv.length; i += 1) {
|
|
14
24
|
const arg = argv[i];
|
|
25
|
+
if (arg === "--")
|
|
26
|
+
continue;
|
|
15
27
|
if (arg === "--project-root" && argv[i + 1] !== undefined) {
|
|
16
28
|
projectRoot = argv[i + 1] ?? ".";
|
|
17
29
|
i += 1;
|
|
@@ -49,7 +61,7 @@ export function routingSetMain(argv = process.argv.slice(2)) {
|
|
|
49
61
|
// Same key as launch + verify:routing: OPENCLAW / sessions_spawn → openclaw
|
|
50
62
|
// (#2875 Greptile P1). Do not map via runtimeMode alone — OpenClaw-only envs
|
|
51
63
|
// are often local-unsandboxed while still dispatching under provider openclaw.
|
|
52
|
-
resolvedProvider = resolveDispatchProvider(
|
|
64
|
+
resolvedProvider = resolveDispatchProvider(environ);
|
|
53
65
|
}
|
|
54
66
|
if (harnessDefault) {
|
|
55
67
|
if (model !== null) {
|
|
@@ -63,7 +75,7 @@ export function routingSetMain(argv = process.argv.slice(2)) {
|
|
|
63
75
|
return EXIT_CONFIG_ERROR;
|
|
64
76
|
}
|
|
65
77
|
const root = resolve(projectRoot);
|
|
66
|
-
const path = resolveRoutingPath(root);
|
|
78
|
+
const path = resolveRoutingPath(root, environ);
|
|
67
79
|
try {
|
|
68
80
|
writeModelDecision(root, path, resolvedProvider, role, {
|
|
69
81
|
model,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { type RoutingFile } from "./routing.js";
|
|
2
|
+
export declare const ROUTING_SET_CMD = "deft swarm:routing-set --role <role> --model <slug> (or --harness-default)";
|
|
2
3
|
/** Roles the pre-dispatch gate checks by default: the actual model lever. */
|
|
3
4
|
export declare const DEFAULT_GATED_ROLES: readonly ["leaf-implementation"];
|
|
4
5
|
export interface VerifyRoutingOptions {
|
|
@@ -16,5 +17,16 @@ export interface VerifyRoutingResult {
|
|
|
16
17
|
exitCode: number;
|
|
17
18
|
report: string;
|
|
18
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Dedicated host-unrecognized honesty line (#3469). Disclosure, not a gate:
|
|
22
|
+
* names the empty probes, that dispatch is still allowed, and the pin or
|
|
23
|
+
* inherit that will be used. Must not be folded into "all roles decided."
|
|
24
|
+
*/
|
|
25
|
+
export declare function formatHostUnrecognizedHonestyLine(options: {
|
|
26
|
+
environ?: NodeJS.ProcessEnv;
|
|
27
|
+
provider: string;
|
|
28
|
+
roles: readonly string[];
|
|
29
|
+
file: RoutingFile | null;
|
|
30
|
+
}): string;
|
|
19
31
|
export declare function verifyRouting(options: VerifyRoutingOptions): VerifyRoutingResult;
|
|
20
32
|
//# sourceMappingURL=routing-verify.d.ts.map
|
|
@@ -5,12 +5,14 @@
|
|
|
5
5
|
* - enforce (pre-dispatch): a hard gate in the pre-`start_agent` /
|
|
6
6
|
* `swarm:launch` gate stack. Three-state exit:
|
|
7
7
|
* 0 = every in-scope role is decided (pinned or explicit harness-default)
|
|
8
|
+
* OR provider is unrecognized (`unknown`) -- disclosure, not a gate (#3469)
|
|
8
9
|
* 1 = at least one in-scope role is undecided / not dispatchable
|
|
9
10
|
* 2 = config error (unreadable / malformed route file)
|
|
11
|
+
* Unrecognized host never exits 1/2 solely because the host was unknown.
|
|
10
12
|
*/
|
|
11
13
|
import { EXIT_CONFIG_ERROR, EXIT_GATE_FAILED, EXIT_OK } from "./constants.js";
|
|
12
|
-
import { dispatchProviderFromRuntime, HARNESS_BOUND_PROVIDERS, loadRoutingFile, ROUTING_MODE_HARNESS_DEFAULT, resolveDispatchProvider, resolveModelRoute, resolveRoutingPath, } from "./routing.js";
|
|
13
|
-
export const ROUTING_SET_CMD = "
|
|
14
|
+
import { dispatchProviderFromRuntime, emptyHostDetectProbes, HARNESS_BOUND_PROVIDERS, loadRoutingFile, ROUTING_MODE_HARNESS_DEFAULT, resolveDispatchProvider, resolveModelRoute, resolveRoutingPath, } from "./routing.js";
|
|
15
|
+
export const ROUTING_SET_CMD = "deft swarm:routing-set --role <role> --model <slug> (or --harness-default)";
|
|
14
16
|
/** Roles the pre-dispatch gate checks by default: the actual model lever. */
|
|
15
17
|
export const DEFAULT_GATED_ROLES = ["leaf-implementation"];
|
|
16
18
|
function resolveProvider(options) {
|
|
@@ -29,6 +31,29 @@ function resolveProvider(options) {
|
|
|
29
31
|
}
|
|
30
32
|
return resolveDispatchProvider(options.environ ?? process.env);
|
|
31
33
|
}
|
|
34
|
+
function isUnrecognizedHost(provider) {
|
|
35
|
+
return provider === "unknown";
|
|
36
|
+
}
|
|
37
|
+
function formatUsedPin(file, provider, role) {
|
|
38
|
+
const resolution = resolveModelRoute(file, provider, role);
|
|
39
|
+
if (resolution.decided && resolution.source !== "invalid") {
|
|
40
|
+
const value = resolution.model ?? "harness-default";
|
|
41
|
+
return `${provider}.${role}=${value}`;
|
|
42
|
+
}
|
|
43
|
+
return `inherit (no ${provider}.${role} pin)`;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Dedicated host-unrecognized honesty line (#3469). Disclosure, not a gate:
|
|
47
|
+
* names the empty probes, that dispatch is still allowed, and the pin or
|
|
48
|
+
* inherit that will be used. Must not be folded into "all roles decided."
|
|
49
|
+
*/
|
|
50
|
+
export function formatHostUnrecognizedHonestyLine(options) {
|
|
51
|
+
const empty = emptyHostDetectProbes(options.environ ?? process.env);
|
|
52
|
+
const emptyText = empty.length > 0 ? empty.join(", ") : "(none)";
|
|
53
|
+
const used = options.roles.map((role) => formatUsedPin(options.file, options.provider, role));
|
|
54
|
+
return (`[deft routing] host unrecognized (#3469): empty probes: ${emptyText}. ` +
|
|
55
|
+
`Dispatch still allowed. Using ${used.join("; ")}.`);
|
|
56
|
+
}
|
|
32
57
|
export function verifyRouting(options) {
|
|
33
58
|
const roles = options.roles && options.roles.length > 0 ? options.roles : DEFAULT_GATED_ROLES;
|
|
34
59
|
const provider = resolveProvider(options);
|
|
@@ -64,6 +89,15 @@ export function verifyRouting(options) {
|
|
|
64
89
|
const modelText = resolution.model ?? "<runtime default>";
|
|
65
90
|
resolvedLines.push(` ${role}: model ${modelText} (resolved-via ${resolution.source})`);
|
|
66
91
|
}
|
|
92
|
+
const unrecognized = isUnrecognizedHost(provider);
|
|
93
|
+
const honesty = unrecognized
|
|
94
|
+
? formatHostUnrecognizedHonestyLine({
|
|
95
|
+
environ: options.environ ?? process.env,
|
|
96
|
+
provider,
|
|
97
|
+
roles,
|
|
98
|
+
file: data,
|
|
99
|
+
})
|
|
100
|
+
: "";
|
|
67
101
|
if (invalid.length > 0 && !options.advise) {
|
|
68
102
|
return {
|
|
69
103
|
exitCode: EXIT_CONFIG_ERROR,
|
|
@@ -71,25 +105,29 @@ export function verifyRouting(options) {
|
|
|
71
105
|
};
|
|
72
106
|
}
|
|
73
107
|
if (options.advise) {
|
|
108
|
+
const note = "[deft routing] NOTE: plan.policy.swarmSubagentBackend enum is deprecated (#1891); use 'deft swarm:routing-set' / .deft/routing.local.json instead.";
|
|
109
|
+
let body;
|
|
74
110
|
if (undecided.length === 0 && invalid.length === 0) {
|
|
75
|
-
|
|
76
|
-
exitCode: EXIT_OK,
|
|
77
|
-
report: `[deft routing] provider '${provider}': all ${roles.length} gated role(s) decided.\n[deft routing] NOTE: plan.policy.swarmSubagentBackend enum is deprecated (#1891); use 'task swarm:routing-set' / .deft/routing.local.json instead.`,
|
|
78
|
-
};
|
|
111
|
+
body = `[deft routing] provider '${provider}': all ${roles.length} gated role(s) decided.`;
|
|
79
112
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
113
|
+
else {
|
|
114
|
+
const parts = [];
|
|
115
|
+
if (undecided.length > 0) {
|
|
116
|
+
parts.push(`undecided role(s): ${undecided.join(", ")}`);
|
|
117
|
+
}
|
|
118
|
+
if (invalid.length > 0) {
|
|
119
|
+
parts.push(`invalid: ${invalid.length}`);
|
|
120
|
+
}
|
|
121
|
+
// Unrecognized host is disclosure: do not force routing-set (#3469).
|
|
122
|
+
const decide = unrecognized
|
|
123
|
+
? "Dispatch still allowed."
|
|
124
|
+
: `Decide before swarm dispatch: ${ROUTING_SET_CMD}`;
|
|
125
|
+
body = `[deft routing] provider '${provider}' -- ${parts.join("; ")}. ${decide}`;
|
|
83
126
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
return {
|
|
88
|
-
exitCode: EXIT_OK,
|
|
89
|
-
report: `[deft routing] provider '${provider}' -- ${parts.join("; ")}. Decide before swarm dispatch: ${ROUTING_SET_CMD}\n[deft routing] NOTE: plan.policy.swarmSubagentBackend enum is deprecated (#1891); use 'task swarm:routing-set' / .deft/routing.local.json instead.`,
|
|
90
|
-
};
|
|
127
|
+
const report = honesty.length > 0 ? `${honesty}\n${body}\n${note}` : `${body}\n${note}`;
|
|
128
|
+
return { exitCode: EXIT_OK, report };
|
|
91
129
|
}
|
|
92
|
-
if (undecided.length > 0) {
|
|
130
|
+
if (undecided.length > 0 && !unrecognized) {
|
|
93
131
|
return {
|
|
94
132
|
exitCode: EXIT_GATE_FAILED,
|
|
95
133
|
report: `routing gate: provider '${provider}' has undecided role(s): ${undecided.join(", ")}.\n` +
|
|
@@ -97,9 +135,10 @@ export function verifyRouting(options) {
|
|
|
97
135
|
`Decide: ${ROUTING_SET_CMD}`,
|
|
98
136
|
};
|
|
99
137
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
};
|
|
138
|
+
const decidedBody = undecided.length > 0
|
|
139
|
+
? `routing gate: provider '${provider}' -- dispatch allowed (host unrecognized is disclosure, not a gate).`
|
|
140
|
+
: `routing gate: provider '${provider}' -- all gated role(s) decided.\n${resolvedLines.join("\n")}`;
|
|
141
|
+
const report = honesty.length > 0 ? `${honesty}\n${decidedBody}` : decidedBody;
|
|
142
|
+
return { exitCode: EXIT_OK, report };
|
|
104
143
|
}
|
|
105
144
|
//# sourceMappingURL=routing-verify.js.map
|
package/dist/swarm/routing.d.ts
CHANGED
|
@@ -9,6 +9,19 @@ export declare const ROUTING_MODE_HARNESS_DEFAULT = "harness-default";
|
|
|
9
9
|
export declare const ROUTING_FILENAME = "routing.local.json";
|
|
10
10
|
/** Providers whose model is harness-bound -- deft cannot pin or verify a slug. */
|
|
11
11
|
export declare const HARNESS_BOUND_PROVIDERS: Set<string>;
|
|
12
|
+
/**
|
|
13
|
+
* Live routing key for Grok Build. A `grok-build` file key is a trap (#3469):
|
|
14
|
+
* read it as `grok` when the live provider is grok, or ignore it without
|
|
15
|
+
* blocking launch.
|
|
16
|
+
*/
|
|
17
|
+
export declare const GROK_ROUTING_KEY = "grok";
|
|
18
|
+
export declare const GROK_BUILD_FILE_KEY = "grok-build";
|
|
19
|
+
/**
|
|
20
|
+
* Env / probe names that identify Grok Build. Same set `probeMonitoringTier`
|
|
21
|
+
* already uses, plus `GROK_BUILD` / `DEFT_AGENT_RUNTIME=grok-build`.
|
|
22
|
+
* Named on the host-unrecognized honesty line when empty (#3469).
|
|
23
|
+
*/
|
|
24
|
+
export declare const HOST_DETECT_PROBE_NAMES: readonly ["GROK_BUILD", "DEFT_AGENT_RUNTIME", "DEFT_HAS_SPAWN_SUBAGENT", "DEFT_PROBE_GROK_BUILD", "DEFT_PROBE_SPAWN_SUBAGENT"];
|
|
12
25
|
/** Providers whose per-role model must be decided before sub-agent dispatch (#1739 / #1877 / #2875 / #3134). */
|
|
13
26
|
export declare const ROUTING_GATED_DISPATCH_PROVIDERS: Set<string>;
|
|
14
27
|
export interface RouteDecision {
|
|
@@ -41,6 +54,7 @@ export declare function loadRoutingFile(path: string): {
|
|
|
41
54
|
data: RoutingFile | null;
|
|
42
55
|
error: string | null;
|
|
43
56
|
};
|
|
57
|
+
export declare function emptyHostDetectProbes(environ?: NodeJS.ProcessEnv): string[];
|
|
44
58
|
/**
|
|
45
59
|
* Resolve a (provider, role) route. Tri-state by KEY PRESENCE:
|
|
46
60
|
* - key present, model "<slug>" -> pinned
|
package/dist/swarm/routing.js
CHANGED
|
@@ -33,6 +33,25 @@ export const ROUTING_MODE_HARNESS_DEFAULT = "harness-default";
|
|
|
33
33
|
export const ROUTING_FILENAME = "routing.local.json";
|
|
34
34
|
/** Providers whose model is harness-bound -- deft cannot pin or verify a slug. */
|
|
35
35
|
export const HARNESS_BOUND_PROVIDERS = new Set(["grok"]);
|
|
36
|
+
/**
|
|
37
|
+
* Live routing key for Grok Build. A `grok-build` file key is a trap (#3469):
|
|
38
|
+
* read it as `grok` when the live provider is grok, or ignore it without
|
|
39
|
+
* blocking launch.
|
|
40
|
+
*/
|
|
41
|
+
export const GROK_ROUTING_KEY = "grok";
|
|
42
|
+
export const GROK_BUILD_FILE_KEY = "grok-build";
|
|
43
|
+
/**
|
|
44
|
+
* Env / probe names that identify Grok Build. Same set `probeMonitoringTier`
|
|
45
|
+
* already uses, plus `GROK_BUILD` / `DEFT_AGENT_RUNTIME=grok-build`.
|
|
46
|
+
* Named on the host-unrecognized honesty line when empty (#3469).
|
|
47
|
+
*/
|
|
48
|
+
export const HOST_DETECT_PROBE_NAMES = [
|
|
49
|
+
"GROK_BUILD",
|
|
50
|
+
"DEFT_AGENT_RUNTIME",
|
|
51
|
+
"DEFT_HAS_SPAWN_SUBAGENT",
|
|
52
|
+
"DEFT_PROBE_GROK_BUILD",
|
|
53
|
+
"DEFT_PROBE_SPAWN_SUBAGENT",
|
|
54
|
+
];
|
|
36
55
|
/** Providers whose per-role model must be decided before sub-agent dispatch (#1739 / #1877 / #2875 / #3134). */
|
|
37
56
|
export const ROUTING_GATED_DISPATCH_PROVIDERS = new Set([
|
|
38
57
|
"cursor",
|
|
@@ -100,6 +119,12 @@ function providerBlockOf(file, provider) {
|
|
|
100
119
|
}
|
|
101
120
|
return block;
|
|
102
121
|
}
|
|
122
|
+
export function emptyHostDetectProbes(environ = process.env) {
|
|
123
|
+
return HOST_DETECT_PROBE_NAMES.filter((name) => (environ[name] ?? "").trim().length === 0);
|
|
124
|
+
}
|
|
125
|
+
function decisionLooksPinned(decision) {
|
|
126
|
+
return typeof decision.model === "string" && decision.model.trim().length > 0;
|
|
127
|
+
}
|
|
103
128
|
/**
|
|
104
129
|
* Resolve a (provider, role) route. Tri-state by KEY PRESENCE:
|
|
105
130
|
* - key present, model "<slug>" -> pinned
|
|
@@ -107,7 +132,28 @@ function providerBlockOf(file, provider) {
|
|
|
107
132
|
* - key absent -> undecided (fail loud upstream)
|
|
108
133
|
*/
|
|
109
134
|
export function resolveModelRoute(file, provider, role) {
|
|
110
|
-
|
|
135
|
+
let block = providerBlockOf(file, provider);
|
|
136
|
+
if ((block === null || !(role in block)) && provider === GROK_ROUTING_KEY) {
|
|
137
|
+
const alias = providerBlockOf(file, GROK_BUILD_FILE_KEY);
|
|
138
|
+
if (alias !== null && role in alias) {
|
|
139
|
+
const aliasDecision = alias[role];
|
|
140
|
+
// Dead `grok-build` pins must not fail-close a harness-bound grok
|
|
141
|
+
// provider (#3469). Read the pin as grok harness-default.
|
|
142
|
+
if (typeof aliasDecision === "object" &&
|
|
143
|
+
aliasDecision !== null &&
|
|
144
|
+
!Array.isArray(aliasDecision) &&
|
|
145
|
+
decisionLooksPinned(aliasDecision)) {
|
|
146
|
+
return {
|
|
147
|
+
decided: true,
|
|
148
|
+
model: null,
|
|
149
|
+
mode: ROUTING_MODE_HARNESS_DEFAULT,
|
|
150
|
+
source: "harness-default explicit",
|
|
151
|
+
error: null,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
block = alias;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
111
157
|
if (block === null || !(role in block)) {
|
|
112
158
|
return { decided: false, model: null, mode: null, source: "undecided", error: null };
|
|
113
159
|
}
|
|
@@ -198,8 +244,12 @@ export function resolveDispatchProvider(environ = process.env) {
|
|
|
198
244
|
runtime === "openclaw") {
|
|
199
245
|
return "openclaw";
|
|
200
246
|
}
|
|
201
|
-
if (envTruthy(environ, "GROK_BUILD") ||
|
|
202
|
-
|
|
247
|
+
if (envTruthy(environ, "GROK_BUILD") ||
|
|
248
|
+
envTruthy(environ, "DEFT_HAS_SPAWN_SUBAGENT") ||
|
|
249
|
+
envTruthy(environ, "DEFT_PROBE_GROK_BUILD") ||
|
|
250
|
+
envTruthy(environ, "DEFT_PROBE_SPAWN_SUBAGENT") ||
|
|
251
|
+
runtime === "grok-build") {
|
|
252
|
+
return GROK_ROUTING_KEY;
|
|
203
253
|
}
|
|
204
254
|
if (runtime === "cloud" || runtime === "headless") {
|
|
205
255
|
return "cloud-headless";
|
|
@@ -85,6 +85,16 @@ export const DEFAULT_TRIAL_STEPS = [
|
|
|
85
85
|
emitter.emitKnownToolTurnDenominator();
|
|
86
86
|
},
|
|
87
87
|
},
|
|
88
|
+
{
|
|
89
|
+
kind: "ac_pass_bank",
|
|
90
|
+
invoke: (emitter) => {
|
|
91
|
+
emitter.emitAcPassBank({
|
|
92
|
+
scope_id: "fake-trial",
|
|
93
|
+
banked_at: "2026-08-16T00:00:00Z",
|
|
94
|
+
next_action: "finalize_and_ship",
|
|
95
|
+
});
|
|
96
|
+
},
|
|
97
|
+
},
|
|
88
98
|
];
|
|
89
99
|
function createConsumerShapedRoot() {
|
|
90
100
|
const root = mkdtempSync(join(tmpdir(), "deft-telemetry-trial-"));
|
|
@@ -13,6 +13,7 @@ export const EVENT_KIND_TO_EMITTER_METHODS = {
|
|
|
13
13
|
verification: ["emitVerification"],
|
|
14
14
|
acceptance: ["emitAcceptance"],
|
|
15
15
|
acceptance_stamp: ["emitAcceptanceStamp"],
|
|
16
|
+
ac_pass_bank: ["emitAcPassBank"],
|
|
16
17
|
};
|
|
17
18
|
/**
|
|
18
19
|
* Kinds asserted by the shared fake-trial harness.
|
|
@@ -29,6 +30,7 @@ export const ENROLLED_FIELD_FIXTURE_KINDS = [
|
|
|
29
30
|
"verification",
|
|
30
31
|
"acceptance",
|
|
31
32
|
"acceptance_stamp",
|
|
33
|
+
"ac_pass_bank",
|
|
32
34
|
];
|
|
33
35
|
const GENERIC_EMIT_METHODS = new Set(["emit"]);
|
|
34
36
|
/** True when a discovered class method is a distinct event surface (not the generic emit). */
|
|
@@ -64,7 +64,10 @@ function defaultIssueIngest() {
|
|
|
64
64
|
// Delegate to the native TS intake path (#2350). The legacy Python
|
|
65
65
|
// `scripts/issue_ingest.py` shell-out was orphaned when #1933 removed the
|
|
66
66
|
// Python surface, leaving `triage:accept` raising ModuleNotFoundError.
|
|
67
|
-
const [, path] = ingestSingleForAcceptTs(issueNumber, repo, { projectRoot });
|
|
67
|
+
const [, path, msg] = ingestSingleForAcceptTs(issueNumber, repo, { projectRoot });
|
|
68
|
+
if (typeof msg === "string" && msg.includes("\n")) {
|
|
69
|
+
process.stderr.write(`${msg}\n`);
|
|
70
|
+
}
|
|
68
71
|
return path;
|
|
69
72
|
},
|
|
70
73
|
};
|
|
@@ -370,12 +370,12 @@ export function formatSummary(result) {
|
|
|
370
370
|
if (result.exitCode === 0) {
|
|
371
371
|
lines.push("");
|
|
372
372
|
lines.push("Next steps:");
|
|
373
|
-
lines.push("
|
|
374
|
-
lines.push("
|
|
375
|
-
lines.push("
|
|
376
|
-
lines.push("
|
|
377
|
-
lines.push("
|
|
378
|
-
lines.push("
|
|
373
|
+
lines.push(" deft cache:fetch-all --source=github-issue --repo OWNER/NAME # refresh the cache (#883 Story 2)");
|
|
374
|
+
lines.push(" deft cache:get github-issue OWNER/NAME/<N> # inspect cached issue N");
|
|
375
|
+
lines.push(" deft triage:accept --issue <N> --repo OWNER/NAME # accept issue N (#845 Story 3)");
|
|
376
|
+
lines.push(" deft triage:reject --issue <N> --repo OWNER/NAME --reason 'why' # reject issue N");
|
|
377
|
+
lines.push(" deft triage:bulk-accept --repo OWNER/NAME --label adoption-blocker # bulk accept");
|
|
378
|
+
lines.push(" deft triage:refresh-active # pre-swarm freshness gate");
|
|
379
379
|
}
|
|
380
380
|
return lines.join("\n");
|
|
381
381
|
}
|
|
@@ -357,7 +357,7 @@ export declare const registryData: {
|
|
|
357
357
|
readonly name: "task triage:metrics";
|
|
358
358
|
readonly summary: "Attributed-value trend from the events ledger";
|
|
359
359
|
readonly refs: "(#1709)";
|
|
360
|
-
readonly description: "Report value-feedback attribution trends from .deft-cache/events.jsonl: total signal count plus per-class (value, bypass, adoption, friction) and per-event breakdowns over a time window. Alias of the value:show handler.
|
|
360
|
+
readonly description: "Report value-feedback attribution trends from .deft-cache/events.jsonl: total signal count plus per-class (value, bypass, adoption, friction) and per-event breakdowns over a time window. Also composes a ceremony-cost rollup (#3508): last cold vs re-arm CLI process time, per-step ms, blocked-ritual count, recovery-tier distribution. Alias of the value:show handler. Attribution requires plan.policy.valueFeedback.enabled (default OFF) — exits blocked when disabled, but still prints the ceremony-cost section. An empty attribution ledger prints a no-signals message. In the maintainer repo, attribution is skipped unless DEFT_VALUE_SELF_DOGFOOD=1.";
|
|
361
361
|
readonly usage: "task triage:metrics [-- --window=7d] [--format=text|json]";
|
|
362
362
|
readonly flags: readonly [readonly ["--window WINDOW", "7d", "Time window (e.g. 7d, 30d, 24h)."], readonly ["--format text|json", "text", "Output shape (json emits the full trend object)."]];
|
|
363
363
|
readonly examples: readonly ["task triage:metrics", "task triage:metrics -- --window=30d --format=json"];
|
|
@@ -628,7 +628,7 @@ export const registryData = {
|
|
|
628
628
|
name: "task triage:metrics",
|
|
629
629
|
summary: "Attributed-value trend from the events ledger",
|
|
630
630
|
refs: "(#1709)",
|
|
631
|
-
description: "Report value-feedback attribution trends from .deft-cache/events.jsonl: total signal count plus per-class (value, bypass, adoption, friction) and per-event breakdowns over a time window. Alias of the value:show handler.
|
|
631
|
+
description: "Report value-feedback attribution trends from .deft-cache/events.jsonl: total signal count plus per-class (value, bypass, adoption, friction) and per-event breakdowns over a time window. Also composes a ceremony-cost rollup (#3508): last cold vs re-arm CLI process time, per-step ms, blocked-ritual count, recovery-tier distribution. Alias of the value:show handler. Attribution requires plan.policy.valueFeedback.enabled (default OFF) — exits blocked when disabled, but still prints the ceremony-cost section. An empty attribution ledger prints a no-signals message. In the maintainer repo, attribution is skipped unless DEFT_VALUE_SELF_DOGFOOD=1.",
|
|
632
632
|
usage: "task triage:metrics [-- --window=7d] [--format=text|json]",
|
|
633
633
|
flags: [
|
|
634
634
|
["--window WINDOW", "7d", "Time window (e.g. 7d, 30d, 24h)."],
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare function appendAuditEntry(projectRoot: string, entry: string): string;
|
|
1
|
+
export declare function appendAuditEntry(projectRoot: string, entry: string, changed?: boolean): string;
|
|
2
2
|
export declare function writeTriageScope(projectRoot: string, rules: Array<Record<string, unknown>>, options?: {
|
|
3
3
|
presetLabel: string;
|
|
4
4
|
actor?: string;
|