@deftai/directive-core 0.107.0 → 0.109.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/architecture/sor-preflight.js +2 -0
- package/dist/cache/operations.js +1 -1
- package/dist/check/cached-orchestrator.js +28 -3
- package/dist/check/gate-lists.d.ts +14 -0
- package/dist/check/gate-lists.js +26 -3
- package/dist/check/named-cause.js +18 -3
- package/dist/check/session-completed-ac.d.ts +1 -1
- package/dist/check/session-completed-ac.js +1 -1
- package/dist/codebase/provider.js +7 -1
- package/dist/consumer-check-contract/evaluate.d.ts +47 -0
- package/dist/consumer-check-contract/evaluate.js +181 -15
- package/dist/delivery-attempt/evaluate.d.ts +9 -1
- package/dist/delivery-attempt/evaluate.js +69 -0
- package/dist/delivery-attempt/handoff.js +1 -1
- package/dist/delivery-attempt/index.d.ts +1 -1
- package/dist/delivery-attempt/index.js +1 -1
- package/dist/deposit/live-procedure-exclusions.d.ts +18 -0
- package/dist/deposit/live-procedure-exclusions.js +110 -0
- package/dist/deposit/live-procedure-targets.d.ts +45 -0
- package/dist/deposit/live-procedure-targets.js +274 -0
- package/dist/deposit/python-free.d.ts +6 -0
- package/dist/deposit/python-free.js +15 -0
- package/dist/deposit/rewrite-deposit-links.d.ts +42 -0
- package/dist/deposit/rewrite-deposit-links.js +148 -0
- package/dist/deposit/run-stage-content-pack.d.ts +2 -0
- package/dist/deposit/run-stage-content-pack.js +3 -0
- package/dist/deposit/stage-content-pack.d.ts +17 -0
- package/dist/deposit/stage-content-pack.js +91 -0
- package/dist/design-critique/citation-grammar.d.ts +60 -0
- package/dist/design-critique/citation-grammar.js +303 -0
- package/dist/design-critique/completed-arc-record.d.ts +62 -0
- package/dist/design-critique/completed-arc-record.js +277 -0
- package/dist/freshness/bind.d.ts +32 -3
- package/dist/freshness/bind.js +58 -12
- package/dist/hooks/classify/host-session-identity.d.ts +89 -0
- package/dist/hooks/classify/host-session-identity.js +467 -0
- package/dist/hooks/classify/index.d.ts +3 -2
- package/dist/hooks/classify/index.js +3 -2
- package/dist/hooks/classify/paths.d.ts +9 -0
- package/dist/hooks/classify/paths.js +39 -0
- package/dist/hooks/classify/stdin.d.ts +5 -0
- package/dist/hooks/classify/stdin.js +94 -1
- package/dist/hooks/dest-form.d.ts +20 -1
- package/dist/hooks/dest-form.js +158 -21
- package/dist/hooks/dispatcher.d.ts +58 -3
- package/dist/hooks/dispatcher.js +762 -73
- package/dist/hooks/fixtures/cases.d.ts +22 -2
- package/dist/hooks/fixtures/cases.js +228 -0
- package/dist/hooks/git-destructive-log.d.ts +32 -0
- package/dist/hooks/git-destructive-log.js +46 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.js +2 -0
- package/dist/hooks/scope.js +3 -1
- package/dist/hooks/shell-write-targets.d.ts +10 -0
- package/dist/hooks/shell-write-targets.js +274 -0
- package/dist/hooks/tools.d.ts +20 -2
- package/dist/hooks/tools.js +30 -1
- package/dist/init-deposit/agent-hooks.d.ts +2 -1
- package/dist/init-deposit/agent-hooks.js +8 -1
- package/dist/init-deposit/gitignore.d.ts +7 -0
- package/dist/init-deposit/gitignore.js +24 -0
- package/dist/init-deposit/hook-runtime-travel.d.ts +77 -0
- package/dist/init-deposit/hook-runtime-travel.js +269 -0
- package/dist/init-deposit/init-deposit.js +3 -0
- package/dist/init-deposit/refresh.js +7 -0
- package/dist/init-deposit/runtime-writers.d.ts +14 -0
- package/dist/init-deposit/runtime-writers.js +33 -0
- package/dist/intake/clause-derivation.js +9 -3
- package/dist/intake/issue-ingest.d.ts +6 -1
- package/dist/intake/issue-ingest.js +83 -4
- package/dist/intake/platform-capabilities.d.ts +9 -2
- package/dist/intake/platform-capabilities.js +38 -9
- package/dist/intake/reconcile-issues.js +13 -13
- package/dist/lifecycle/brief-envelope.d.ts +25 -0
- package/dist/lifecycle/brief-envelope.js +42 -0
- package/dist/lifecycle/index.d.ts +1 -0
- package/dist/lifecycle/index.js +1 -0
- package/dist/literal-acceptance/evaluate.js +14 -5
- package/dist/literal-acceptance/index.d.ts +1 -1
- package/dist/literal-acceptance/index.js +1 -1
- package/dist/literal-acceptance/run.d.ts +2 -0
- package/dist/literal-acceptance/run.js +19 -1
- package/dist/orphan-active/candidate-scope.d.ts +53 -0
- package/dist/orphan-active/candidate-scope.js +157 -0
- package/dist/orphan-active/evaluate.d.ts +52 -0
- package/dist/orphan-active/evaluate.js +250 -128
- package/dist/orphan-active/index.d.ts +2 -0
- package/dist/orphan-active/index.js +2 -0
- package/dist/orphan-active/issue-state.d.ts +121 -0
- package/dist/orphan-active/issue-state.js +278 -0
- package/dist/platform/cursor-managed-runtime.d.ts +95 -0
- package/dist/platform/cursor-managed-runtime.js +241 -0
- package/dist/platform/index.d.ts +1 -0
- package/dist/platform/index.js +1 -0
- package/dist/platform/platform-capabilities.d.ts +23 -1
- package/dist/platform/platform-capabilities.js +55 -15
- package/dist/policy/ceremony-dial.js +5 -9
- package/dist/policy/host-hooks.js +4 -9
- package/dist/policy/merge-approval-head.js +7 -6
- package/dist/policy/org-force-on-migration.js +5 -10
- package/dist/policy/plan-extensions.d.ts +14 -2
- package/dist/policy/plan-extensions.js +24 -3
- package/dist/policy/product-signal.js +5 -10
- package/dist/policy/require-human-merge.js +5 -9
- package/dist/policy/resolve.js +77 -16
- package/dist/policy/value-feedback.js +9 -18
- package/dist/pr-closeout-attestable/evaluate.d.ts +80 -0
- package/dist/pr-closeout-attestable/evaluate.js +306 -0
- package/dist/pr-closeout-attestable/index.d.ts +2 -0
- package/dist/pr-closeout-attestable/index.js +2 -0
- package/dist/pr-closing-keywords/gh.js +32 -9
- package/dist/pr-closing-keywords/main.d.ts +1 -0
- package/dist/pr-closing-keywords/main.js +68 -3
- package/dist/pr-closing-keywords/types.d.ts +2 -0
- package/dist/pr-merge-readiness/gh.js +32 -9
- package/dist/pr-protected-issues/gh.d.ts +6 -2
- package/dist/pr-protected-issues/gh.js +42 -11
- package/dist/pr-wait-mergeable/cascade.d.ts +9 -1
- package/dist/pr-wait-mergeable/cascade.js +21 -1
- package/dist/pr-wait-mergeable/types.d.ts +2 -0
- package/dist/pr-wait-mergeable/wrappers.d.ts +6 -0
- package/dist/pr-wait-mergeable/wrappers.js +14 -3
- package/dist/preflight/evaluate.d.ts +15 -0
- package/dist/preflight/evaluate.js +29 -3
- package/dist/product-first-done-gate/acceptance-resolver.d.ts +14 -2
- package/dist/product-first-done-gate/acceptance-resolver.js +13 -2
- package/dist/product-first-done-gate/evaluate.js +23 -9
- package/dist/product-first-done-gate/types.js +2 -0
- package/dist/release/cli-drift-report.d.ts +68 -0
- package/dist/release/cli-drift-report.js +189 -0
- package/dist/release/consumer-hard-stops.d.ts +48 -0
- package/dist/release/consumer-hard-stops.js +140 -0
- package/dist/release/consumer-readiness-disclosure.d.ts +18 -0
- package/dist/release/consumer-readiness-disclosure.js +51 -0
- package/dist/release/index.d.ts +3 -0
- package/dist/release/index.js +3 -0
- package/dist/release/issue-state-fetch.d.ts +5 -3
- package/dist/release/issue-state-fetch.js +86 -21
- package/dist/release/native-steps.js +1 -0
- package/dist/release/pipeline.js +74 -0
- package/dist/release/run-consumer-readiness.d.ts +15 -0
- package/dist/release/run-consumer-readiness.js +24 -0
- package/dist/release/types.d.ts +20 -0
- package/dist/render/constants.d.ts +4 -0
- package/dist/render/constants.js +11 -8
- package/dist/render/export-spec.js +31 -5
- package/dist/render/index.d.ts +1 -1
- package/dist/render/index.js +1 -1
- package/dist/render/prd-render.d.ts +4 -1
- package/dist/render/prd-render.js +82 -23
- package/dist/render/project-render.js +14 -7
- package/dist/render/scope-outlook.d.ts +2 -0
- package/dist/render/scope-outlook.js +3 -0
- package/dist/render/spec-render.js +2 -2
- package/dist/resolution/package-manager.d.ts +33 -4
- package/dist/resolution/package-manager.js +210 -9
- package/dist/review-monitor/constants.d.ts +7 -0
- package/dist/review-monitor/constants.js +7 -0
- package/dist/review-monitor/github-lease.d.ts +98 -1
- package/dist/review-monitor/github-lease.js +186 -4
- package/dist/review-monitor/lease-comment.d.ts +36 -0
- package/dist/review-monitor/lease-comment.js +103 -2
- package/dist/run-summary/types.d.ts +2 -2
- package/dist/scm/build-command.d.ts +2 -2
- package/dist/scm/build-command.js +2 -2
- package/dist/scm/call-shape.d.ts +25 -0
- package/dist/scm/call-shape.js +59 -0
- package/dist/scm/call.d.ts +7 -4
- package/dist/scm/call.js +48 -9
- package/dist/scm/design-critique-chip.d.ts +1 -0
- package/dist/scm/design-critique-chip.js +22 -6
- package/dist/scm/gh-rest.d.ts +34 -13
- package/dist/scm/gh-rest.js +168 -15
- package/dist/scm/index.d.ts +2 -0
- package/dist/scm/index.js +2 -0
- package/dist/scm/readiness.d.ts +2 -0
- package/dist/scm/readiness.js +28 -4
- package/dist/scm/spawn-status.d.ts +33 -0
- package/dist/scm/spawn-status.js +53 -0
- package/dist/scope/acceptance-evidence.d.ts +1 -1
- package/dist/scope/project-definition-sync.js +14 -7
- package/dist/scope/transition.js +4 -14
- package/dist/session/ac-pass-banking.d.ts +2 -2
- package/dist/session/ac-pass-banking.js +2 -2
- package/dist/session/git.d.ts +24 -0
- package/dist/session/git.js +138 -2
- package/dist/session/host-session-owner.d.ts +53 -0
- package/dist/session/host-session-owner.js +89 -0
- package/dist/session/index.d.ts +1 -0
- package/dist/session/index.js +1 -0
- package/dist/session/occupancy.d.ts +259 -13
- package/dist/session/occupancy.js +877 -33
- package/dist/session/ritual-sentinel.d.ts +5 -0
- package/dist/session/ritual-sentinel.js +5 -0
- package/dist/session/session-ready.d.ts +5 -1
- package/dist/session/session-ready.js +98 -8
- package/dist/session/session-start.d.ts +5 -1
- package/dist/session/session-start.js +32 -17
- package/dist/session/toolchain-preflight.d.ts +13 -3
- package/dist/session/toolchain-preflight.js +93 -18
- package/dist/session/verify-ac-session-cache.d.ts +2 -2
- package/dist/session/verify-ac-session-cache.js +2 -2
- package/dist/session/verify-session-ritual.d.ts +11 -0
- package/dist/session/verify-session-ritual.js +60 -15
- package/dist/slice/constants.d.ts +1 -1
- package/dist/spec-authority/constants.d.ts +10 -2
- package/dist/spec-authority/constants.js +53 -8
- package/dist/spec-authority/resolver.d.ts +3 -0
- package/dist/spec-authority/resolver.js +55 -7
- package/dist/subprocess/max-buffer.d.ts +14 -0
- package/dist/subprocess/max-buffer.js +15 -0
- package/dist/swarm/complete-cohort.d.ts +2 -0
- package/dist/swarm/complete-cohort.js +21 -13
- package/dist/swarm/index.d.ts +1 -0
- package/dist/swarm/index.js +1 -0
- package/dist/swarm/launch-cli.js +53 -33
- package/dist/swarm/launch.d.ts +8 -0
- package/dist/swarm/launch.js +63 -43
- package/dist/swarm/pre-dispatch-cli.js +2 -1
- package/dist/swarm/pre-dispatch.js +10 -1
- package/dist/swarm/subagent-status-dir.d.ts +27 -0
- package/dist/swarm/subagent-status-dir.js +42 -0
- package/dist/swarm/worktrees.d.ts +17 -3
- package/dist/swarm/worktrees.js +48 -4
- package/dist/triage/evaluate/worktrees.js +153 -6
- package/dist/triage/scope/mutations-core.d.ts +2 -6
- package/dist/triage/scope/mutations-core.js +23 -55
- package/dist/triage/scope-drift/add-ignore.js +5 -39
- package/dist/triage/subscribe/index.d.ts +2 -6
- package/dist/triage/subscribe/index.js +15 -65
- package/dist/triage/welcome/writers.js +15 -74
- package/dist/umbrella-current-shape/index.d.ts +51 -3
- package/dist/umbrella-current-shape/index.js +106 -18
- package/dist/validate-content/deposit-required.d.ts +39 -0
- package/dist/validate-content/deposit-required.js +147 -0
- package/dist/validate-content/index.d.ts +1 -0
- package/dist/validate-content/index.js +1 -0
- package/dist/validate-content/validate-links.d.ts +2 -3
- package/dist/validate-content/validate-links.js +29 -2
- package/dist/vbrief-activate/activate.d.ts +7 -2
- package/dist/vbrief-activate/activate.js +26 -13
- package/dist/vbrief-build/index.d.ts +2 -1
- package/dist/vbrief-build/index.js +2 -1
- package/dist/vbrief-build/parity-scenarios.js +5 -5
- package/dist/vbrief-build/project-definition-io.d.ts +63 -3
- package/dist/vbrief-build/project-definition-io.js +357 -31
- package/dist/vbrief-build/project-definition-mutation.d.ts +32 -0
- package/dist/vbrief-build/project-definition-mutation.js +43 -0
- package/dist/vbrief-validate/conformance.d.ts +1 -0
- package/dist/vbrief-validate/conformance.js +85 -8
- package/dist/vbrief-validate/main.js +2 -0
- package/dist/vbrief-validate/precutover.js +5 -10
- package/dist/verify-ac/clauses.d.ts +62 -2
- package/dist/verify-ac/clauses.js +183 -111
- package/dist/verify-ac/evaluate.d.ts +9 -0
- package/dist/verify-ac/evaluate.js +32 -9
- package/dist/verify-ac/index.d.ts +1 -1
- package/dist/verify-ac/index.js +1 -1
- package/dist/verify-env/node-runtime.d.ts +8 -4
- package/dist/verify-env/node-runtime.js +9 -6
- package/dist/verify-env/toolchain-check.d.ts +35 -3
- package/dist/verify-env/toolchain-check.js +155 -36
- package/dist/verify-source/deposit-closure.d.ts +23 -0
- package/dist/verify-source/deposit-closure.js +162 -0
- package/dist/verify-source/index.d.ts +2 -0
- package/dist/verify-source/index.js +2 -0
- package/dist/verify-source/project-definition-mutation-boundary.d.ts +104 -0
- package/dist/verify-source/project-definition-mutation-boundary.js +326 -0
- package/dist/verify-source/semantic-single-source.d.ts +36 -0
- package/dist/verify-source/semantic-single-source.js +349 -0
- package/package.json +7 -3
|
@@ -421,6 +421,75 @@ function evaluatePreDispatchNatural(ledger, input) {
|
|
|
421
421
|
resume: null,
|
|
422
422
|
});
|
|
423
423
|
}
|
|
424
|
+
/**
|
|
425
|
+
* Elapsed budget for a run already queued or running (#3983).
|
|
426
|
+
* Pre-dispatch cannot see this case: an active attempt is DENY_DUPLICATE_ACTIVE.
|
|
427
|
+
*/
|
|
428
|
+
export function evaluateInFlight(ledger, input = {}) {
|
|
429
|
+
const nowIso = utcIso(input.now);
|
|
430
|
+
const synthetic = {
|
|
431
|
+
scopeId: ledger.scopeId,
|
|
432
|
+
targetId: ledger.targetId,
|
|
433
|
+
workflowId: ledger.workflowId,
|
|
434
|
+
sourceRevision: ledger.lastSourceRevision ?? "in-flight",
|
|
435
|
+
trigger: "resume",
|
|
436
|
+
now: nowIso,
|
|
437
|
+
policy: input.policy,
|
|
438
|
+
};
|
|
439
|
+
const policy = mergePolicy(input.policy);
|
|
440
|
+
const active = activeAttempts(ledger);
|
|
441
|
+
if (active.length === 0) {
|
|
442
|
+
return result(synthetic, ledger, "ALLOW_FIRST_ATTEMPT", "no in-flight attempt", {
|
|
443
|
+
retryability: null,
|
|
444
|
+
fingerprint: null,
|
|
445
|
+
sameFailureCount: 0,
|
|
446
|
+
materialClass: "none",
|
|
447
|
+
resume: null,
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
const current = active[0];
|
|
451
|
+
if (current === undefined) {
|
|
452
|
+
return result(synthetic, ledger, "ALLOW_FIRST_ATTEMPT", "no in-flight attempt", {
|
|
453
|
+
retryability: null,
|
|
454
|
+
fingerprint: null,
|
|
455
|
+
sameFailureCount: 0,
|
|
456
|
+
materialClass: "none",
|
|
457
|
+
resume: null,
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
const startedMs = Date.parse(current.startedAt);
|
|
461
|
+
const nowMs = Date.parse(nowIso);
|
|
462
|
+
const liveSeconds = Number.isFinite(startedMs) && Number.isFinite(nowMs)
|
|
463
|
+
? Math.max(0, (nowMs - startedMs) / 1000)
|
|
464
|
+
: 0;
|
|
465
|
+
const elapsed = ledger.totalElapsedSeconds + liveSeconds;
|
|
466
|
+
if (elapsed >= policy.maxElapsedSeconds) {
|
|
467
|
+
const resume = {
|
|
468
|
+
kind: "operator-override",
|
|
469
|
+
description: "elapsed budget exhausted on in-flight attempt; override or phase reset required",
|
|
470
|
+
satisfied: false,
|
|
471
|
+
};
|
|
472
|
+
return result(synthetic, ledger, "BLOCK_ELAPSED_BUDGET", "in-flight elapsed-time budget exhausted", {
|
|
473
|
+
retryability: ledger.lastFailure?.retryability ?? null,
|
|
474
|
+
fingerprint: ledger.lastFailure?.fingerprint ?? null,
|
|
475
|
+
sameFailureCount: 0,
|
|
476
|
+
materialClass: "none",
|
|
477
|
+
resume,
|
|
478
|
+
handoffLedger: {
|
|
479
|
+
...ledger,
|
|
480
|
+
resumeCondition: resume,
|
|
481
|
+
blockedDecision: "BLOCK_ELAPSED_BUDGET",
|
|
482
|
+
},
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
return result(synthetic, ledger, "ALLOW_RESUME", "in-flight elapsed under budget", {
|
|
486
|
+
retryability: null,
|
|
487
|
+
fingerprint: null,
|
|
488
|
+
sameFailureCount: 0,
|
|
489
|
+
materialClass: "none",
|
|
490
|
+
resume: ledger.resumeCondition,
|
|
491
|
+
});
|
|
492
|
+
}
|
|
424
493
|
/**
|
|
425
494
|
* Convenience: evaluate against ledger, and if blocked, return handoff suitable
|
|
426
495
|
* for persistence via markBlocked + saveUnitLedger.
|
|
@@ -8,7 +8,7 @@ import { utcIso } from "./types.js";
|
|
|
8
8
|
export function nextSafeActionFor(decision) {
|
|
9
9
|
switch (decision) {
|
|
10
10
|
case "DENY_DUPLICATE_ACTIVE":
|
|
11
|
-
return "
|
|
11
|
+
return "A running attempt is not proof the worker is alive. Takeover: swarm:pre-dispatch --action cancel, then begin. REDISPATCH_OK does not lift this deny.";
|
|
12
12
|
case "BLOCK_NON_RETRYABLE":
|
|
13
13
|
return "Fix the deterministic configuration/schema/permission failure, record a relevant material delta, then resume.";
|
|
14
14
|
case "BLOCK_NO_MATERIAL_PROGRESS":
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* @see content/docs/delivery-attempt.md
|
|
9
9
|
*/
|
|
10
10
|
export { type BeginAttemptOnDiskInput, beginAttemptOnDisk, type CompleteAttemptOnDiskInput, completeAttemptOnDisk, } from "./disk-begin.js";
|
|
11
|
-
export { evaluateAndPrepareBlock, evaluatePreDispatch, } from "./evaluate.js";
|
|
11
|
+
export { evaluateAndPrepareBlock, evaluateInFlight, evaluatePreDispatch, } from "./evaluate.js";
|
|
12
12
|
export { buildFailureInfo, computeFailureFingerprint, type FingerprintInput, inferRetryability, normalizeFailureMessage, } from "./fingerprint.js";
|
|
13
13
|
export { buildTerminalHandoff, defaultResumeFor, formatHandoffReport, nextSafeActionFor, redactHandoffForPersist, } from "./handoff.js";
|
|
14
14
|
export { activeAttempts, beginAttempt, clearBlockIfResumed, completeAttempt, deliveryAttemptsDir, emptyUnitLedger, hasActiveAttempt, isUnitLockReclaimable, type LoadUnitLedgerResult, listUnitLedgers, loadOrCreateUnitLedger, loadUnitLedger, loadUnitLedgerResult, MemoryLedgerStore, markBlocked, newAttemptId, parseUnitLedger, recordOperatorOverride, saveUnitLedger, UNIT_LOCK_STALE_MS, unitLedgerFilename, unitLedgerPath, withUnitLock, } from "./ledger.js";
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* @see content/docs/delivery-attempt.md
|
|
9
9
|
*/
|
|
10
10
|
export { beginAttemptOnDisk, completeAttemptOnDisk, } from "./disk-begin.js";
|
|
11
|
-
export { evaluateAndPrepareBlock, evaluatePreDispatch, } from "./evaluate.js";
|
|
11
|
+
export { evaluateAndPrepareBlock, evaluateInFlight, evaluatePreDispatch, } from "./evaluate.js";
|
|
12
12
|
export { buildFailureInfo, computeFailureFingerprint, inferRetryability, normalizeFailureMessage, } from "./fingerprint.js";
|
|
13
13
|
export { buildTerminalHandoff, defaultResumeFor, formatHandoffReport, nextSafeActionFor, redactHandoffForPersist, } from "./handoff.js";
|
|
14
14
|
export { activeAttempts, beginAttempt, clearBlockIfResumed, completeAttempt, deliveryAttemptsDir, emptyUnitLedger, hasActiveAttempt, isUnitLockReclaimable, listUnitLedgers, loadOrCreateUnitLedger, loadUnitLedger, loadUnitLedgerResult, MemoryLedgerStore, markBlocked, newAttemptId, parseUnitLedger, recordOperatorOverride, saveUnitLedger, UNIT_LOCK_STALE_MS, unitLedgerFilename, unitLedgerPath, withUnitLock, } from "./ledger.js";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* C3 live-procedure exclusion declaration (#3602 / #3899).
|
|
3
|
+
*
|
|
4
|
+
* History, examples, and prohibitions are skipped by this list, not by
|
|
5
|
+
* matching prose patterns. A file that names a deleted Python script in
|
|
6
|
+
* order to forbid treating it as a live path must appear here as
|
|
7
|
+
* `prohibition` or C3 will mis-fire.
|
|
8
|
+
*/
|
|
9
|
+
export type LiveProcedureExclusionKind = "history" | "example" | "prohibition";
|
|
10
|
+
export interface LiveProcedureExclusion {
|
|
11
|
+
/** POSIX path relative to a flattened consumer deposit root. */
|
|
12
|
+
readonly path: string;
|
|
13
|
+
readonly kind: LiveProcedureExclusionKind;
|
|
14
|
+
readonly reason: string;
|
|
15
|
+
}
|
|
16
|
+
export declare const LIVE_PROCEDURE_EXCLUSIONS: readonly LiveProcedureExclusion[];
|
|
17
|
+
export declare function isDeclaredLiveProcedureExclusion(relativePath: string): boolean;
|
|
18
|
+
//# sourceMappingURL=live-procedure-exclusions.d.ts.map
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* C3 live-procedure exclusion declaration (#3602 / #3899).
|
|
3
|
+
*
|
|
4
|
+
* History, examples, and prohibitions are skipped by this list, not by
|
|
5
|
+
* matching prose patterns. A file that names a deleted Python script in
|
|
6
|
+
* order to forbid treating it as a live path must appear here as
|
|
7
|
+
* `prohibition` or C3 will mis-fire.
|
|
8
|
+
*/
|
|
9
|
+
export const LIVE_PROCEDURE_EXCLUSIONS = [
|
|
10
|
+
{
|
|
11
|
+
path: "scm/github.md",
|
|
12
|
+
kind: "prohibition",
|
|
13
|
+
reason: "Names deleted Python scripts to forbid treating them as live implementation paths (#2022).",
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
path: "UPGRADING.md",
|
|
17
|
+
kind: "history",
|
|
18
|
+
reason: "Migration history of Python helpers on pinned pre-Python-free releases.",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
path: "deployments/aws/via-elastic-beanstalk.md",
|
|
22
|
+
kind: "example",
|
|
23
|
+
reason: "Consumer AWS sample `scripts/create_admin.py` is not a deposit helper.",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
path: "conventions/machine-generated-banner.md",
|
|
27
|
+
kind: "history",
|
|
28
|
+
reason: "Registry of historical Python writers that produced the banner; not a live consumer procedure.",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
path: "docs/BROWNFIELD.md",
|
|
32
|
+
kind: "history",
|
|
33
|
+
reason: "Brownfield migration history of the Python migrator on pinned releases.",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
path: "languages/python.md",
|
|
37
|
+
kind: "example",
|
|
38
|
+
reason: "Python language pack names consumer application files, not deposit helpers.",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
path: "languages/kotlin.md",
|
|
42
|
+
kind: "example",
|
|
43
|
+
reason: "Kotlin stdlib `run` scoping function is not the deposit Python launcher.",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
path: "deployments/aws/via-lambda.md",
|
|
47
|
+
kind: "example",
|
|
48
|
+
reason: "AWS Lambda sample `src/app.py` is a consumer application, not a deposit helper.",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
path: "deployments/fly-io/via-dockerfile.md",
|
|
52
|
+
kind: "example",
|
|
53
|
+
reason: "Fly.io sample `app.py` / `manage.py` are consumer application files.",
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
path: "coding/toolchain.md",
|
|
57
|
+
kind: "example",
|
|
58
|
+
reason: "Cites framework test paths that pin the toolchain contract; not a live helper.",
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
path: "coding/testing.md",
|
|
62
|
+
kind: "example",
|
|
63
|
+
reason: "Documents `_test.py` naming for consumer Python tests, not a deposit helper.",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
path: "contracts/deterministic-questions.md",
|
|
67
|
+
kind: "example",
|
|
68
|
+
reason: "Cites the contract's own test path; not a live consumer helper.",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
path: "conventions/task-caching.md",
|
|
72
|
+
kind: "example",
|
|
73
|
+
reason: "Cites framework tests that pin task-caching; not a live helper.",
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
path: "events/README.md",
|
|
77
|
+
kind: "history",
|
|
78
|
+
reason: "Maintainer event-registry history naming retired Python writers and their tests.",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
path: "templates/agents-entry.placeholders.md",
|
|
82
|
+
kind: "example",
|
|
83
|
+
reason: "Cites the agents-entry contract test; not a live helper.",
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
path: "templates/swarm-greptile-poller-prompt.md",
|
|
87
|
+
kind: "example",
|
|
88
|
+
reason: "Cites the poller-template contract test; not a live helper.",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
path: "verification/plan-checking.md",
|
|
92
|
+
kind: "example",
|
|
93
|
+
reason: "Swarm-spec example names `tests/test_auth.py` as consumer test layout.",
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
path: "swarm/swarm.md",
|
|
97
|
+
kind: "example",
|
|
98
|
+
reason: "Swarm-spec example names `src/auth.py` / `tests/test_auth.py` as consumer files.",
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
path: "skills/deft-directive-setup/SKILL.md",
|
|
102
|
+
kind: "example",
|
|
103
|
+
reason: "Setup skill Python example names `src/ui.py` as a consumer application file.",
|
|
104
|
+
},
|
|
105
|
+
];
|
|
106
|
+
const EXCLUSION_PATHS = new Set(LIVE_PROCEDURE_EXCLUSIONS.map((entry) => entry.path));
|
|
107
|
+
export function isDeclaredLiveProcedureExclusion(relativePath) {
|
|
108
|
+
return EXCLUSION_PATHS.has(relativePath.replace(/\\/g, "/"));
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=live-procedure-exclusions.js.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* C3 live-procedure target validation (#3602 / #3899).
|
|
3
|
+
*
|
|
4
|
+
* A shipped live procedure must not name a helper the deposit does not
|
|
5
|
+
* contain. Python helpers are identified via python-free; markdown is
|
|
6
|
+
* walked with the validate-links skip set and extractLinkTargets. History,
|
|
7
|
+
* examples, and prohibitions are skipped by declaration.
|
|
8
|
+
*
|
|
9
|
+
* Metric: unique live-invalid helper targets (not occurrences, not matching
|
|
10
|
+
* lines). Prefer a zero unique-target assertion; do not freeze raw counts.
|
|
11
|
+
*/
|
|
12
|
+
export interface LiveProcedureHit {
|
|
13
|
+
readonly file: string;
|
|
14
|
+
readonly line: number;
|
|
15
|
+
readonly target: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ExtraMarkdownFile {
|
|
18
|
+
readonly relativePath: string;
|
|
19
|
+
readonly absolutePath: string;
|
|
20
|
+
}
|
|
21
|
+
export interface EvaluateLiveProcedureTargetsOptions {
|
|
22
|
+
readonly stagedRoot: string;
|
|
23
|
+
readonly extraFiles?: readonly ExtraMarkdownFile[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Metric used by C3: unique live-invalid helper targets.
|
|
27
|
+
* Not occurrence count, not matching-line count.
|
|
28
|
+
*/
|
|
29
|
+
export declare const LIVE_PROCEDURE_METRIC: "unique-targets";
|
|
30
|
+
export interface LiveProcedureEvaluation {
|
|
31
|
+
readonly metric: typeof LIVE_PROCEDURE_METRIC;
|
|
32
|
+
readonly hits: readonly LiveProcedureHit[];
|
|
33
|
+
readonly uniqueTargets: readonly string[];
|
|
34
|
+
}
|
|
35
|
+
export declare function normalizePythonHelperTarget(raw: string): string | null;
|
|
36
|
+
export declare function evaluateLiveProcedureTargets(options: EvaluateLiveProcedureTargetsOptions): LiveProcedureEvaluation;
|
|
37
|
+
export declare function extraDepositMarkdownFiles(root: string): ExtraMarkdownFile[];
|
|
38
|
+
export declare class LiveProcedureTargetsError extends Error {
|
|
39
|
+
readonly evaluation: LiveProcedureEvaluation;
|
|
40
|
+
constructor(evaluation: LiveProcedureEvaluation);
|
|
41
|
+
}
|
|
42
|
+
/** Fail closed when a deposit's live procedures name pruned Python helpers (#3602 C3). */
|
|
43
|
+
export declare function assertLiveProcedureDepositClean(depositDir: string): void;
|
|
44
|
+
export declare function formatLiveProcedureFailure(result: LiveProcedureEvaluation): string;
|
|
45
|
+
//# sourceMappingURL=live-procedure-targets.d.ts.map
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* C3 live-procedure target validation (#3602 / #3899).
|
|
3
|
+
*
|
|
4
|
+
* A shipped live procedure must not name a helper the deposit does not
|
|
5
|
+
* contain. Python helpers are identified via python-free; markdown is
|
|
6
|
+
* walked with the validate-links skip set and extractLinkTargets. History,
|
|
7
|
+
* examples, and prohibitions are skipped by declaration.
|
|
8
|
+
*
|
|
9
|
+
* Metric: unique live-invalid helper targets (not occurrences, not matching
|
|
10
|
+
* lines). Prefer a zero unique-target assertion; do not freeze raw counts.
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
13
|
+
import { join, relative, resolve, sep } from "node:path";
|
|
14
|
+
import { NON_PRODUCT_DIRS } from "../fs/non-product-dirs.js";
|
|
15
|
+
import { extractLinkTargets, shouldSkipLinkTarget } from "../validate-content/link-parser.js";
|
|
16
|
+
import { isDeclaredLiveProcedureExclusion } from "./live-procedure-exclusions.js";
|
|
17
|
+
import { isPrunedPythonArtifactPath } from "./python-free.js";
|
|
18
|
+
const SKIP_DIRS = new Set([...NON_PRODUCT_DIRS, ".planning", "specs"]);
|
|
19
|
+
/**
|
|
20
|
+
* Metric used by C3: unique live-invalid helper targets.
|
|
21
|
+
* Not occurrence count, not matching-line count.
|
|
22
|
+
*/
|
|
23
|
+
export const LIVE_PROCEDURE_METRIC = "unique-targets";
|
|
24
|
+
function shouldSkipPath(parts) {
|
|
25
|
+
if (parts.some((p) => SKIP_DIRS.has(p)))
|
|
26
|
+
return true;
|
|
27
|
+
return parts.includes("history") && parts.includes("archive");
|
|
28
|
+
}
|
|
29
|
+
function toPosix(rel) {
|
|
30
|
+
return rel.split(sep).join("/");
|
|
31
|
+
}
|
|
32
|
+
function collectMarkdownFiles(root) {
|
|
33
|
+
const out = [];
|
|
34
|
+
const walk = (dir, parts) => {
|
|
35
|
+
if (shouldSkipPath(parts))
|
|
36
|
+
return;
|
|
37
|
+
let entries;
|
|
38
|
+
try {
|
|
39
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
45
|
+
const full = join(dir, entry.name);
|
|
46
|
+
const nextParts = [...parts, entry.name];
|
|
47
|
+
if (shouldSkipPath(nextParts))
|
|
48
|
+
continue;
|
|
49
|
+
if (entry.isDirectory()) {
|
|
50
|
+
walk(full, nextParts);
|
|
51
|
+
}
|
|
52
|
+
else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
53
|
+
out.push(full);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
walk(root, []);
|
|
58
|
+
return out.sort();
|
|
59
|
+
}
|
|
60
|
+
const PATH_CHAR = /[A-Za-z0-9_.-]/;
|
|
61
|
+
const PY_HELPER_TOKEN = /^(?:[A-Za-z0-9_.-]+\/)+[A-Za-z0-9_.-]+\.py[c]?$/;
|
|
62
|
+
const RUN_SHIM_TOKEN = /^(?:\.deft\/core\/run|deft\/run|run)$/;
|
|
63
|
+
/** Known pruned deposit helpers named without a directory. Not consumer app.py. */
|
|
64
|
+
const PRUNED_BARE_HELPER_BASENAMES = new Set([
|
|
65
|
+
"gh_rest.py",
|
|
66
|
+
"ip_risk.py",
|
|
67
|
+
"preflight_implementation.py",
|
|
68
|
+
"preflight_gh.py",
|
|
69
|
+
"migrate_vbrief.py",
|
|
70
|
+
"slug_normalize.py",
|
|
71
|
+
"slice_record.py",
|
|
72
|
+
"validate_strategy_output.py",
|
|
73
|
+
"_precutover.py",
|
|
74
|
+
"swarm_mint_jwt.py",
|
|
75
|
+
]);
|
|
76
|
+
function stripRelativePrefix(posix) {
|
|
77
|
+
let out = posix;
|
|
78
|
+
while (out.startsWith("./"))
|
|
79
|
+
out = out.slice(2);
|
|
80
|
+
while (out.startsWith("../"))
|
|
81
|
+
out = out.slice(3);
|
|
82
|
+
return out;
|
|
83
|
+
}
|
|
84
|
+
export function normalizePythonHelperTarget(raw) {
|
|
85
|
+
const clean = (raw.split("#")[0] ?? "").split("?")[0] ?? "";
|
|
86
|
+
const posix = clean.replace(/\\/g, "/");
|
|
87
|
+
if (posix.includes("://"))
|
|
88
|
+
return null;
|
|
89
|
+
const stripped = stripRelativePrefix(posix);
|
|
90
|
+
if (stripped.includes(".."))
|
|
91
|
+
return null;
|
|
92
|
+
const scriptsIdx = stripped.lastIndexOf("scripts/");
|
|
93
|
+
const token = scriptsIdx >= 0 ? stripped.slice(scriptsIdx) : stripped;
|
|
94
|
+
if (RUN_SHIM_TOKEN.test(token) || RUN_SHIM_TOKEN.test(stripped)) {
|
|
95
|
+
if (stripped === ".deft/core/run" || stripped.endsWith("/.deft/core/run")) {
|
|
96
|
+
return ".deft/core/run";
|
|
97
|
+
}
|
|
98
|
+
if (stripped === "deft/run" || stripped.endsWith("/deft/run"))
|
|
99
|
+
return "deft/run";
|
|
100
|
+
if (token === "run" || stripped === "run")
|
|
101
|
+
return "run";
|
|
102
|
+
}
|
|
103
|
+
if (!token.includes("/") && PRUNED_BARE_HELPER_BASENAMES.has(token)) {
|
|
104
|
+
return token;
|
|
105
|
+
}
|
|
106
|
+
if (!PY_HELPER_TOKEN.test(token))
|
|
107
|
+
return null;
|
|
108
|
+
return token;
|
|
109
|
+
}
|
|
110
|
+
function isPathChar(ch) {
|
|
111
|
+
if (ch === undefined)
|
|
112
|
+
return false;
|
|
113
|
+
return PATH_CHAR.test(ch) || ch === "/" || ch === "\\";
|
|
114
|
+
}
|
|
115
|
+
function extractBacktickPythonHelpers(line) {
|
|
116
|
+
const out = [];
|
|
117
|
+
const suffixes = [".pyc", ".py"];
|
|
118
|
+
for (const suffix of suffixes) {
|
|
119
|
+
let from = 0;
|
|
120
|
+
while (from < line.length) {
|
|
121
|
+
const idx = line.indexOf(suffix, from);
|
|
122
|
+
if (idx < 0)
|
|
123
|
+
break;
|
|
124
|
+
const after = line[idx + suffix.length];
|
|
125
|
+
if (isPathChar(after)) {
|
|
126
|
+
from = idx + suffix.length;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
let start = idx;
|
|
130
|
+
while (start > 0 && isPathChar(line[start - 1]))
|
|
131
|
+
start -= 1;
|
|
132
|
+
const token = line.slice(start, idx + suffix.length);
|
|
133
|
+
from = idx + suffix.length;
|
|
134
|
+
const normalized = normalizePythonHelperTarget(token);
|
|
135
|
+
if (normalized)
|
|
136
|
+
out.push(normalized);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
for (const spelling of [".deft/core/run", "deft/run"]) {
|
|
140
|
+
if (line.includes(spelling)) {
|
|
141
|
+
const normalized = normalizePythonHelperTarget(spelling);
|
|
142
|
+
if (normalized)
|
|
143
|
+
out.push(normalized);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
let tick = 0;
|
|
147
|
+
while (tick < line.length) {
|
|
148
|
+
const open = line.indexOf("`", tick);
|
|
149
|
+
if (open < 0)
|
|
150
|
+
break;
|
|
151
|
+
const close = line.indexOf("`", open + 1);
|
|
152
|
+
if (close < 0)
|
|
153
|
+
break;
|
|
154
|
+
const inner = line.slice(open + 1, close).trim();
|
|
155
|
+
const parts = inner.split(/\s+/).filter((p) => p.length > 0);
|
|
156
|
+
const first = (parts[0] ?? "").replace(/^\.\//, "");
|
|
157
|
+
const arg = parts[1];
|
|
158
|
+
const launcherArgs = new Set([
|
|
159
|
+
"bootstrap",
|
|
160
|
+
"spec",
|
|
161
|
+
"init",
|
|
162
|
+
"project",
|
|
163
|
+
"upgrade",
|
|
164
|
+
"doctor",
|
|
165
|
+
"validate",
|
|
166
|
+
"reset",
|
|
167
|
+
]);
|
|
168
|
+
if (first === "run" && (arg === undefined || launcherArgs.has(arg))) {
|
|
169
|
+
const normalized = normalizePythonHelperTarget("run");
|
|
170
|
+
if (normalized)
|
|
171
|
+
out.push(normalized);
|
|
172
|
+
}
|
|
173
|
+
tick = close + 1;
|
|
174
|
+
}
|
|
175
|
+
return out;
|
|
176
|
+
}
|
|
177
|
+
function extractLineTargets(line) {
|
|
178
|
+
const found = new Set();
|
|
179
|
+
for (const raw of extractLinkTargets(line)) {
|
|
180
|
+
if (raw.startsWith("http://") ||
|
|
181
|
+
raw.startsWith("https://") ||
|
|
182
|
+
raw.startsWith("mailto:") ||
|
|
183
|
+
raw.startsWith("#")) {
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
if (shouldSkipLinkTarget(raw))
|
|
187
|
+
continue;
|
|
188
|
+
const normalized = normalizePythonHelperTarget(raw);
|
|
189
|
+
if (normalized)
|
|
190
|
+
found.add(normalized);
|
|
191
|
+
}
|
|
192
|
+
for (const token of extractBacktickPythonHelpers(line))
|
|
193
|
+
found.add(token);
|
|
194
|
+
return [...found];
|
|
195
|
+
}
|
|
196
|
+
function scanMarkdownFile(absolutePath, relativePath) {
|
|
197
|
+
if (isDeclaredLiveProcedureExclusion(relativePath))
|
|
198
|
+
return [];
|
|
199
|
+
let text;
|
|
200
|
+
try {
|
|
201
|
+
text = readFileSync(absolutePath, "utf8");
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
return [];
|
|
205
|
+
}
|
|
206
|
+
const hits = [];
|
|
207
|
+
const lines = text.split("\n");
|
|
208
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
209
|
+
const line = lines[i] ?? "";
|
|
210
|
+
for (const target of extractLineTargets(line)) {
|
|
211
|
+
if (!isPrunedPythonArtifactPath(target))
|
|
212
|
+
continue;
|
|
213
|
+
hits.push({ file: relativePath, line: i + 1, target });
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return hits;
|
|
217
|
+
}
|
|
218
|
+
export function evaluateLiveProcedureTargets(options) {
|
|
219
|
+
const stagedRoot = resolve(options.stagedRoot);
|
|
220
|
+
const hits = [];
|
|
221
|
+
if (existsSync(stagedRoot)) {
|
|
222
|
+
for (const md of collectMarkdownFiles(stagedRoot)) {
|
|
223
|
+
const rel = toPosix(relative(stagedRoot, md));
|
|
224
|
+
hits.push(...scanMarkdownFile(md, rel));
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
for (const extra of options.extraFiles ?? []) {
|
|
228
|
+
const rel = extra.relativePath.replace(/\\/g, "/");
|
|
229
|
+
hits.push(...scanMarkdownFile(extra.absolutePath, rel));
|
|
230
|
+
}
|
|
231
|
+
const unique = [...new Set(hits.map((h) => h.target))].sort();
|
|
232
|
+
return { metric: LIVE_PROCEDURE_METRIC, hits, uniqueTargets: unique };
|
|
233
|
+
}
|
|
234
|
+
export function extraDepositMarkdownFiles(root) {
|
|
235
|
+
const extras = [];
|
|
236
|
+
for (const name of ["main.md", "SKILL.md"]) {
|
|
237
|
+
const absolutePath = join(root, name);
|
|
238
|
+
if (existsSync(absolutePath)) {
|
|
239
|
+
extras.push({ relativePath: name, absolutePath });
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return extras;
|
|
243
|
+
}
|
|
244
|
+
export class LiveProcedureTargetsError extends Error {
|
|
245
|
+
evaluation;
|
|
246
|
+
constructor(evaluation) {
|
|
247
|
+
super(formatLiveProcedureFailure(evaluation));
|
|
248
|
+
this.name = "LiveProcedureTargetsError";
|
|
249
|
+
this.evaluation = evaluation;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
/** Fail closed when a deposit's live procedures name pruned Python helpers (#3602 C3). */
|
|
253
|
+
export function assertLiveProcedureDepositClean(depositDir) {
|
|
254
|
+
const result = evaluateLiveProcedureTargets({
|
|
255
|
+
stagedRoot: depositDir,
|
|
256
|
+
extraFiles: extraDepositMarkdownFiles(depositDir),
|
|
257
|
+
});
|
|
258
|
+
if (result.uniqueTargets.length > 0) {
|
|
259
|
+
throw new LiveProcedureTargetsError(result);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
export function formatLiveProcedureFailure(result) {
|
|
263
|
+
const lines = [
|
|
264
|
+
`C3 live-procedure target validation failed: ${result.uniqueTargets.length} unique live-invalid helper target(s) (metric=${result.metric}).`,
|
|
265
|
+
];
|
|
266
|
+
for (const hit of result.hits.slice(0, 40)) {
|
|
267
|
+
lines.push(` ${hit.file}:${hit.line} -> ${hit.target}`);
|
|
268
|
+
}
|
|
269
|
+
if (result.hits.length > 40) {
|
|
270
|
+
lines.push(` ... ${result.hits.length - 40} more occurrence(s)`);
|
|
271
|
+
}
|
|
272
|
+
return lines.join("\n");
|
|
273
|
+
}
|
|
274
|
+
//# sourceMappingURL=live-procedure-targets.js.map
|
|
@@ -5,6 +5,12 @@
|
|
|
5
5
|
* Python-only artifacts that must not ship to npm consumers: the legacy
|
|
6
6
|
* `scripts/` tree, `.py` files, and Python `run` shims.
|
|
7
7
|
*/
|
|
8
|
+
/** True when a named helper path is a Python artifact the deposit prunes (#3602 C3). */
|
|
9
|
+
export declare function isPythonHelperPath(relPath: string): boolean;
|
|
10
|
+
/** Path spellings of the Python `run` launcher python-free removes (#3602 C3). */
|
|
11
|
+
export declare function isPythonRunShimPath(relPath: string): boolean;
|
|
12
|
+
/** True when C3 should treat a named path as a pruned Python deposit helper. */
|
|
13
|
+
export declare function isPrunedPythonArtifactPath(relPath: string): boolean;
|
|
8
14
|
export interface PythonArtifact {
|
|
9
15
|
readonly path: string;
|
|
10
16
|
readonly kind: "py-file" | "scripts-tree" | "run-shim";
|
|
@@ -11,6 +11,21 @@ import { join, relative } from "node:path";
|
|
|
11
11
|
import { containedRemove } from "../fs/contained-write.js";
|
|
12
12
|
const PY_SUFFIX = ".py";
|
|
13
13
|
const PYC_SUFFIX = ".pyc";
|
|
14
|
+
/** True when a named helper path is a Python artifact the deposit prunes (#3602 C3). */
|
|
15
|
+
export function isPythonHelperPath(relPath) {
|
|
16
|
+
const posix = relPath.replace(/\\/g, "/");
|
|
17
|
+
const base = posix.split("/").pop() ?? posix;
|
|
18
|
+
return base.endsWith(PY_SUFFIX) || base.endsWith(PYC_SUFFIX);
|
|
19
|
+
}
|
|
20
|
+
/** Path spellings of the Python `run` launcher python-free removes (#3602 C3). */
|
|
21
|
+
export function isPythonRunShimPath(relPath) {
|
|
22
|
+
const posix = relPath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
23
|
+
return posix === "run" || posix === ".deft/core/run" || posix === "deft/run";
|
|
24
|
+
}
|
|
25
|
+
/** True when C3 should treat a named path as a pruned Python deposit helper. */
|
|
26
|
+
export function isPrunedPythonArtifactPath(relPath) {
|
|
27
|
+
return isPythonHelperPath(relPath) || isPythonRunShimPath(relPath);
|
|
28
|
+
}
|
|
14
29
|
function isPythonRunShim(_path, head) {
|
|
15
30
|
if (!head.startsWith("#!"))
|
|
16
31
|
return false;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flatten-aware rewrite of relative markdown links from the source tree onto
|
|
3
|
+
* the C1 packed layout (#3937).
|
|
4
|
+
*
|
|
5
|
+
* Source checkout: content/X lives under content/; root main.md / SKILL.md stay
|
|
6
|
+
* at the repo root. Deposit: content/ children flatten to the payload root, and
|
|
7
|
+
* harness entries land beside them. A naive `./content/` strip cannot express
|
|
8
|
+
* the reverse `../../main.md` escape. This rewrite maps each relative target
|
|
9
|
+
* through the source path, then emits a deposit-relative href.
|
|
10
|
+
*/
|
|
11
|
+
export declare const DEPOSIT_LINK_REWRITE_VERSION = "1";
|
|
12
|
+
export declare const REWRITE_MARKER_PREFIX = "<!-- deft:deposit-link-rewrite";
|
|
13
|
+
export declare function isUrlLikeTarget(target: string): boolean;
|
|
14
|
+
/** Map a repo-relative source path to its packed-deposit relative path. */
|
|
15
|
+
export declare function mapSourceToPackRelative(sourceRel: string): string | null;
|
|
16
|
+
/** Inverse: packed path -> source path the file was copied from. */
|
|
17
|
+
export declare function sourceRelForPackRel(packRel: string): string;
|
|
18
|
+
export declare function resolveSourceTargetRel(sourceFileRel: string, rawPath: string): string;
|
|
19
|
+
export declare function splitLinkHash(target: string): {
|
|
20
|
+
path: string;
|
|
21
|
+
suffix: string;
|
|
22
|
+
};
|
|
23
|
+
export interface RewriteLinkResult {
|
|
24
|
+
readonly next: string;
|
|
25
|
+
readonly rewritten: boolean;
|
|
26
|
+
readonly packMapped: boolean;
|
|
27
|
+
}
|
|
28
|
+
export declare function rewriteRelativeLink(options: {
|
|
29
|
+
readonly sourceFileRel: string;
|
|
30
|
+
readonly packFileRel: string;
|
|
31
|
+
readonly target: string;
|
|
32
|
+
}): RewriteLinkResult;
|
|
33
|
+
export declare function rewriteMarker(sourceRel: string): string;
|
|
34
|
+
export declare function rewriteMarkdownDepositLinks(options: {
|
|
35
|
+
readonly content: string;
|
|
36
|
+
readonly sourceFileRel: string;
|
|
37
|
+
readonly packFileRel: string;
|
|
38
|
+
}): {
|
|
39
|
+
content: string;
|
|
40
|
+
rewriteCount: number;
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=rewrite-deposit-links.d.ts.map
|