@deftai/directive-core 0.103.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 +682 -35
- package/dist/check/cached-orchestrator.d.ts +1 -1
- package/dist/check/cached-orchestrator.js +2 -2
- package/dist/check/gate-lists.d.ts +3 -2
- package/dist/check/gate-lists.js +5 -2
- package/dist/check/index.d.ts +1 -0
- package/dist/check/index.js +1 -0
- package/dist/check/named-cause.d.ts +1 -1
- package/dist/check/named-cause.js +33 -3
- package/dist/check/session-completed-ac.d.ts +39 -0
- package/dist/check/session-completed-ac.js +198 -0
- 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 -14
- package/dist/doctor/types.d.ts +9 -0
- package/dist/fs/contained-write.d.ts +115 -1
- package/dist/fs/contained-write.js +242 -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 +2 -0
- package/dist/index.js +3 -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 +74 -0
- package/dist/intake/clause-derivation.js +409 -0
- package/dist/intake/index.d.ts +1 -0
- package/dist/intake/index.js +1 -0
- package/dist/intake/issue-ingest.d.ts +3 -1
- package/dist/intake/issue-ingest.js +36 -43
- 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 +9 -0
- package/dist/preflight/evaluate.js +49 -1
- package/dist/preflight/index.d.ts +5 -1
- 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 +5 -2
- package/dist/product-first-done-gate/empty-resolution.js +13 -2
- package/dist/product-first-done-gate/evaluate.d.ts +29 -0
- package/dist/product-first-done-gate/evaluate.js +307 -33
- package/dist/product-first-done-gate/index.d.ts +3 -1
- package/dist/product-first-done-gate/index.js +2 -1
- package/dist/release/build-dist.d.ts +101 -0
- package/dist/release/build-dist.js +428 -46
- package/dist/run-summary/emit.d.ts +50 -4
- package/dist/run-summary/emit.js +262 -26
- 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/share.d.ts +1 -1
- package/dist/run-summary/share.js +2 -2
- package/dist/run-summary/types.d.ts +38 -6
- package/dist/run-summary/types.js +1 -0
- package/dist/scope/acceptance-activate-gate.d.ts +1 -1
- package/dist/scope/acceptance-activate-gate.js +4 -4
- package/dist/scope/acceptance-evidence.d.ts +27 -0
- package/dist/scope/acceptance-evidence.js +66 -0
- package/dist/scope/capacity-stamp.d.ts +2 -0
- package/dist/scope/capacity-stamp.js +4 -0
- package/dist/scope/delivery-evidence.d.ts +9 -3
- package/dist/scope/delivery-evidence.js +39 -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 +66 -4
- 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/ceremony-dial-evidence.d.ts +42 -0
- package/dist/session/ceremony-dial-evidence.js +194 -0
- package/dist/session/git.js +19 -4
- package/dist/session/index.d.ts +5 -0
- package/dist/session/index.js +5 -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 +88 -5
- 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 +21 -4
- package/dist/slice/lock.d.ts +16 -1
- package/dist/slice/lock.js +137 -11
- package/dist/slice/record.d.ts +8 -5
- package/dist/slice/record.js +21 -13
- 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/evaluate.d.ts +42 -0
- package/dist/telemetry-coverage/evaluate.js +148 -0
- package/dist/telemetry-coverage/fake-trial.d.ts +45 -0
- package/dist/telemetry-coverage/fake-trial.js +204 -0
- package/dist/telemetry-coverage/index.d.ts +5 -0
- package/dist/telemetry-coverage/index.js +5 -0
- package/dist/telemetry-coverage/kinds.d.ts +19 -0
- package/dist/telemetry-coverage/kinds.js +54 -0
- package/dist/telemetry-coverage/scan-callers.d.ts +25 -0
- package/dist/telemetry-coverage/scan-callers.js +168 -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 +3 -1
- package/dist/vbrief-reconcile/index.js +2 -1
- package/dist/vbrief-reconcile/origin-freshness.d.ts +44 -0
- package/dist/vbrief-reconcile/origin-freshness.js +221 -0
- 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/index.d.ts +1 -0
- package/dist/verify-source/index.js +1 -0
- package/dist/verify-source/verify-stubs.d.ts +15 -1
- package/dist/verify-source/verify-stubs.js +20 -16
- package/dist/vitest-runner/win32-coverage-tmp-setup.d.ts +5 -6
- package/dist/vitest-runner/win32-coverage-tmp-setup.js +5 -6
- package/dist/xbrief-migrate/migrate-project.js +2 -5
- package/package.json +3 -3
package/dist/hooks/dispatcher.js
CHANGED
|
@@ -10,6 +10,7 @@ import { classifyMcpTool, DEFAULT_RUNTIME_AUTHORITY_POLICY, evaluateRuntimeAutho
|
|
|
10
10
|
import { loadStoryWriteFenceFromPath, resolveWriteFence } from "../policy/write-fence.js";
|
|
11
11
|
import { appendSoftAgentsRebindToMessage, decisionCarriesSoftAgentsRebind, formatSoftAgentsRebindChecklist, } from "../session/compact-ritual.js";
|
|
12
12
|
import { detectBranch } from "../session/git.js";
|
|
13
|
+
import { evaluateOccupancyWriteGate } from "../session/occupancy.js";
|
|
13
14
|
import { emitSessionRitualBlockedProcessCost } from "../session/process-cost.js";
|
|
14
15
|
import { markRitualStaleAfterCompact } from "../session/ritual-sentinel.js";
|
|
15
16
|
import { runSessionStartHookWrite } from "../session/session-start-hook.js";
|
|
@@ -598,6 +599,19 @@ function inspectMutationGates(input, toolName, seams, options) {
|
|
|
598
599
|
return deny(input, "ritual-not-ready", toolName, `Directive could not inspect the gated session ritual: ${String(cause)}. ` +
|
|
599
600
|
formatRitualRecoveryInstruction("cold"));
|
|
600
601
|
}
|
|
602
|
+
const occupancyGate = isSpawnTool(toolName)
|
|
603
|
+
? { allow: true, message: null, occupant: null }
|
|
604
|
+
: evaluateOccupancyWriteGate(projectRoot, { env: environ });
|
|
605
|
+
if (!occupancyGate.allow && occupancyGate.message !== null) {
|
|
606
|
+
const ritualNote = ritual.code !== 0 ? ` Also ritual-not-ready: ${ritual.message}` : "";
|
|
607
|
+
emitSessionRitualBlockedProcessCost({
|
|
608
|
+
toolName,
|
|
609
|
+
code: "occupancy-occupied",
|
|
610
|
+
recoveryTier: ritual.recoveryTier === "rearm" ? "rearm" : "cold",
|
|
611
|
+
detail: occupancyGate.message,
|
|
612
|
+
}, { projectRoot });
|
|
613
|
+
return deny(input, "occupancy-occupied", toolName, `Directive denied ${toolName}: ${occupancyGate.message}${ritualNote}`);
|
|
614
|
+
}
|
|
601
615
|
if (ritual.code !== 0) {
|
|
602
616
|
// #2992: prefer re-arm recovery when age/compact stale; cold when bind invalid.
|
|
603
617
|
const recoveryTier = ritual.recoveryTier === "rearm" ? "rearm" : "cold";
|
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export * as authz from "./authz/index.js";
|
|
|
13
13
|
export * as branch from "./branch/index.js";
|
|
14
14
|
export * as cache from "./cache/index.js";
|
|
15
15
|
export * as capacity from "./capacity/index.js";
|
|
16
|
+
export * as check from "./check/index.js";
|
|
16
17
|
export * as codebase from "./codebase/index.js";
|
|
17
18
|
export * as consumerCheckContract from "./consumer-check-contract/index.js";
|
|
18
19
|
export * from "./coverage-hotspots/index.js";
|
|
@@ -29,6 +30,7 @@ export * as events from "./events/attribution-ledger.js";
|
|
|
29
30
|
export * from "./forward-coverage/evaluate.js";
|
|
30
31
|
export * as freshness from "./freshness/index.js";
|
|
31
32
|
export { ContainedWriteError, ContainedWriteErrorCode, type ContainedWriteInput, type ContainedWriteMode, type ContainedWriteResult, containedWrite, resolveContainedTarget, } from "./fs/contained-write.js";
|
|
33
|
+
export { AGENT_HOST_WORKING_DIRS, AGENT_SCRATCH_DIRS, NON_PRODUCT_DIRS, } from "./fs/non-product-dirs.js";
|
|
32
34
|
export { assertDestinationNotSymlink, assertDirectoryNotSymlink, assertProjectionContained, assertWriteTargetSafe, PROJECTION_CONTAINMENT_REFUSED_EXIT_CODE, ProjectionContainmentError, walkDirectoryRejectSymlinks, } from "./fs/projection-containment.js";
|
|
33
35
|
export * as handoffEvidence from "./handoff-evidence/index.js";
|
|
34
36
|
export * as intake from "./intake/index.js";
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,7 @@ export * as authz from "./authz/index.js";
|
|
|
13
13
|
export * as branch from "./branch/index.js";
|
|
14
14
|
export * as cache from "./cache/index.js";
|
|
15
15
|
export * as capacity from "./capacity/index.js";
|
|
16
|
+
export * as check from "./check/index.js";
|
|
16
17
|
export * as codebase from "./codebase/index.js";
|
|
17
18
|
export * as consumerCheckContract from "./consumer-check-contract/index.js";
|
|
18
19
|
export * from "./coverage-hotspots/index.js";
|
|
@@ -30,6 +31,8 @@ export * from "./forward-coverage/evaluate.js";
|
|
|
30
31
|
export * as freshness from "./freshness/index.js";
|
|
31
32
|
// #2951 Phase 1: contained-write API for product sinks.
|
|
32
33
|
export { ContainedWriteError, ContainedWriteErrorCode, containedWrite, resolveContainedTarget, } from "./fs/contained-write.js";
|
|
34
|
+
// #3487: single source of truth for walk exclusions, shared by every gate.
|
|
35
|
+
export { AGENT_HOST_WORKING_DIRS, AGENT_SCRATCH_DIRS, NON_PRODUCT_DIRS, } from "./fs/non-product-dirs.js";
|
|
33
36
|
export { assertDestinationNotSymlink, assertDirectoryNotSymlink, assertProjectionContained, assertWriteTargetSafe, PROJECTION_CONTAINMENT_REFUSED_EXIT_CODE, ProjectionContainmentError, walkDirectoryRejectSymlinks, } from "./fs/projection-containment.js";
|
|
34
37
|
export * as handoffEvidence from "./handoff-evidence/index.js";
|
|
35
38
|
export * as intake from "./intake/index.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { existsSync, readFileSync
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { basename, dirname, join, resolve } from "node:path";
|
|
3
3
|
import { assertDepositContained } from "../deposit/contain.js";
|
|
4
|
-
import { containedWrite } from "../fs/contained-write.js";
|
|
4
|
+
import { containedRemove, containedRename, containedWrite } from "../fs/contained-write.js";
|
|
5
5
|
import { DIRECT_WRITE_HOOK_MATCHER, MCP_HOOK_MATCHER, SHELL_HOOK_MATCHER, SPAWN_HOOK_MATCHER, } from "../hooks/tools.js";
|
|
6
6
|
import { isHostHookDepositEnabled, loadHostHooksPolicyFromProject, } from "../policy/host-hooks.js";
|
|
7
7
|
export { DIRECT_WRITE_HOOK_MATCHER, MCP_HOOK_MATCHER, SHELL_HOOK_MATCHER, SPAWN_HOOK_MATCHER, } from "../hooks/tools.js";
|
|
@@ -217,7 +217,7 @@ function mergeCursorConfig(config, path) {
|
|
|
217
217
|
];
|
|
218
218
|
return { ...config, version: 1, hooks };
|
|
219
219
|
}
|
|
220
|
-
function writeJsonIfChanged(projectRoot, path, payload) {
|
|
220
|
+
function writeJsonIfChanged(projectRoot, path, payload, kind) {
|
|
221
221
|
const next = `${JSON.stringify(payload, null, 2)}\n`;
|
|
222
222
|
if (existsSync(path) && readFileSync(path, "utf8") === next)
|
|
223
223
|
return false;
|
|
@@ -231,12 +231,18 @@ function writeJsonIfChanged(projectRoot, path, payload) {
|
|
|
231
231
|
target: temporary,
|
|
232
232
|
data: next,
|
|
233
233
|
mode: "replace",
|
|
234
|
+
mutation: { kind, path },
|
|
235
|
+
});
|
|
236
|
+
containedRename({
|
|
237
|
+
root: resolve(projectRoot),
|
|
238
|
+
from: temporary,
|
|
239
|
+
to: path,
|
|
240
|
+
mutation: false,
|
|
234
241
|
});
|
|
235
|
-
renameSync(temporary, path);
|
|
236
242
|
}
|
|
237
243
|
catch (err) {
|
|
238
244
|
try {
|
|
239
|
-
|
|
245
|
+
containedRemove({ root: resolve(projectRoot), target: temporary, mutation: false });
|
|
240
246
|
}
|
|
241
247
|
catch {
|
|
242
248
|
/* best-effort cleanup */
|
|
@@ -298,7 +304,7 @@ export function writeAgentHookDeposit(projectRoot, io = { printf: () => undefine
|
|
|
298
304
|
for (const item of prepared) {
|
|
299
305
|
if (item.mode === "skip")
|
|
300
306
|
continue;
|
|
301
|
-
if (writeJsonIfChanged(projectRoot, item.absolute, item.payload)) {
|
|
307
|
+
if (writeJsonIfChanged(projectRoot, item.absolute, item.payload, item.mode === "strip" ? "stripped" : "wrote")) {
|
|
302
308
|
if (item.mode === "strip")
|
|
303
309
|
strippedPaths.push(item.path);
|
|
304
310
|
else
|
|
@@ -309,29 +315,25 @@ export function writeAgentHookDeposit(projectRoot, io = { printf: () => undefine
|
|
|
309
315
|
".cursor/hooks/deft-cursor-hook-adapter.mjs",
|
|
310
316
|
".cursor/hooks/deft-cursor-hook-adapter.test.mjs",
|
|
311
317
|
];
|
|
312
|
-
let
|
|
318
|
+
let adaptersRemoved = 0;
|
|
313
319
|
for (const relative of legacyAdapterPaths) {
|
|
314
320
|
const absolute = join(projectRoot, relative);
|
|
315
321
|
assertDepositContained(projectRoot, absolute);
|
|
316
|
-
if (
|
|
317
|
-
|
|
318
|
-
removedLegacyAdapter = true;
|
|
322
|
+
if (containedRemove({ root: projectRoot, target: absolute }).removed) {
|
|
323
|
+
adaptersRemoved += 1;
|
|
319
324
|
}
|
|
320
325
|
}
|
|
321
|
-
if (removedLegacyAdapter && !changedPaths.includes(AGENT_HOOK_PATHS[2])) {
|
|
322
|
-
changedPaths.push(AGENT_HOOK_PATHS[2]);
|
|
323
|
-
}
|
|
324
326
|
if (changedPaths.length > 0) {
|
|
325
327
|
io.printf(`Installed Directive agent hooks: ${changedPaths.join(", ")}\n`);
|
|
326
328
|
}
|
|
327
329
|
if (strippedPaths.length > 0) {
|
|
328
330
|
io.printf(`Removed Directive-managed agent hooks (plan.policy.hostHooks opt-out): ${strippedPaths.join(", ")}\n`);
|
|
329
331
|
}
|
|
330
|
-
if (changedPaths.length === 0 && strippedPaths.length === 0) {
|
|
332
|
+
if (changedPaths.length === 0 && strippedPaths.length === 0 && adaptersRemoved === 0) {
|
|
331
333
|
io.printf("Directive agent hooks already current.\n");
|
|
332
334
|
}
|
|
333
335
|
return {
|
|
334
|
-
changed: changedPaths.length + strippedPaths.length > 0,
|
|
336
|
+
changed: changedPaths.length + strippedPaths.length + adaptersRemoved > 0,
|
|
335
337
|
changedPaths: [...changedPaths, ...strippedPaths],
|
|
336
338
|
};
|
|
337
339
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedded python3 pin/lock checker for deposited deft-core-guard (#3193 / #3427).
|
|
3
|
+
* Twin of cmd/deft-install/core_guard_pin_content.embed — keep byte-identical.
|
|
4
|
+
* Not a .py file; CodeQL default setup must not see Python here.
|
|
5
|
+
*/
|
|
6
|
+
export declare const CORE_GUARD_PIN_CONTENT_PYTHON: string;
|
|
7
|
+
//# sourceMappingURL=core-guard-pin-content.d.ts.map
|
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedded python3 pin/lock checker for deposited deft-core-guard (#3193 / #3427).
|
|
3
|
+
* Twin of cmd/deft-install/core_guard_pin_content.embed — keep byte-identical.
|
|
4
|
+
* Not a .py file; CodeQL default setup must not see Python here.
|
|
5
|
+
*/
|
|
6
|
+
export const CORE_GUARD_PIN_CONTENT_PYTHON = [
|
|
7
|
+
"# Content-aware pin unit for deposited deft-core-guard (#3193).",
|
|
8
|
+
'# Invoked as: python3 - "$BASE_SHA" "$HEAD_SHA"',
|
|
9
|
+
"# Mirrors packages/core/src/init-deposit/hygiene.ts isUpgradePinPathContentAllowed.",
|
|
10
|
+
"from __future__ import annotations",
|
|
11
|
+
"",
|
|
12
|
+
"import json",
|
|
13
|
+
"import re",
|
|
14
|
+
"import subprocess",
|
|
15
|
+
"import sys",
|
|
16
|
+
"",
|
|
17
|
+
"_Q = chr(39) + chr(34) # ' and \" without raw-string quote pain",
|
|
18
|
+
"",
|
|
19
|
+
"",
|
|
20
|
+
"def git_show(sha, path):",
|
|
21
|
+
" try:",
|
|
22
|
+
" return subprocess.check_output(",
|
|
23
|
+
' ["git", "show", f"{sha}:{path}"], text=True, stderr=subprocess.DEVNULL',
|
|
24
|
+
" )",
|
|
25
|
+
" except subprocess.CalledProcessError:",
|
|
26
|
+
' return ""',
|
|
27
|
+
"",
|
|
28
|
+
"",
|
|
29
|
+
"def changed_names(base_sha, head_sha):",
|
|
30
|
+
" out = subprocess.check_output(",
|
|
31
|
+
' ["git", "diff", "--name-only", base_sha, head_sha], text=True',
|
|
32
|
+
" )",
|
|
33
|
+
" return [p for p in out.splitlines() if p]",
|
|
34
|
+
"",
|
|
35
|
+
"",
|
|
36
|
+
"def is_dir_key(n):",
|
|
37
|
+
' return n.startswith("@deftai/directive")',
|
|
38
|
+
"",
|
|
39
|
+
"",
|
|
40
|
+
"DEP_FIELDS = (",
|
|
41
|
+
' "dependencies",',
|
|
42
|
+
' "devDependencies",',
|
|
43
|
+
' "optionalDependencies",',
|
|
44
|
+
' "peerDependencies",',
|
|
45
|
+
")",
|
|
46
|
+
"",
|
|
47
|
+
"",
|
|
48
|
+
"def deep_eq(a, b):",
|
|
49
|
+
" if a is b:",
|
|
50
|
+
" return True",
|
|
51
|
+
" if type(a) is not type(b):",
|
|
52
|
+
" return False",
|
|
53
|
+
" if isinstance(a, dict):",
|
|
54
|
+
" if set(a) != set(b):",
|
|
55
|
+
" return False",
|
|
56
|
+
" return all(deep_eq(a[k], b[k]) for k in a)",
|
|
57
|
+
" if isinstance(a, list):",
|
|
58
|
+
" return len(a) == len(b) and all(deep_eq(x, y) for x, y in zip(a, b))",
|
|
59
|
+
" return a == b",
|
|
60
|
+
"",
|
|
61
|
+
"",
|
|
62
|
+
"def strip_pins(obj):",
|
|
63
|
+
" if not isinstance(obj, dict):",
|
|
64
|
+
" return obj",
|
|
65
|
+
" out = {}",
|
|
66
|
+
" for k, v in obj.items():",
|
|
67
|
+
" if k in DEP_FIELDS and isinstance(v, dict):",
|
|
68
|
+
" out[k] = {dk: dv for dk, dv in v.items() if not is_dir_key(dk)}",
|
|
69
|
+
" else:",
|
|
70
|
+
" out[k] = v",
|
|
71
|
+
" return out",
|
|
72
|
+
"",
|
|
73
|
+
"",
|
|
74
|
+
"def pkg_pin_only(base, head):",
|
|
75
|
+
" try:",
|
|
76
|
+
' b, h = json.loads(base or "{}"), json.loads(head or "{}")',
|
|
77
|
+
" except json.JSONDecodeError:",
|
|
78
|
+
" return False",
|
|
79
|
+
" return deep_eq(strip_pins(b), strip_pins(h))",
|
|
80
|
+
"",
|
|
81
|
+
"",
|
|
82
|
+
"def collect_deps(pkg):",
|
|
83
|
+
" out = {}",
|
|
84
|
+
" if not isinstance(pkg, dict):",
|
|
85
|
+
" return out",
|
|
86
|
+
" for f in DEP_FIELDS:",
|
|
87
|
+
" block = pkg.get(f)",
|
|
88
|
+
" if isinstance(block, dict):",
|
|
89
|
+
" for k, v in block.items():",
|
|
90
|
+
" if isinstance(v, str):",
|
|
91
|
+
" out[k] = v",
|
|
92
|
+
' elif isinstance(v, dict) and isinstance(v.get("version"), str):',
|
|
93
|
+
' out[k] = v["version"]',
|
|
94
|
+
" elif v is not None:",
|
|
95
|
+
" out[k] = str(v)",
|
|
96
|
+
" return out",
|
|
97
|
+
"",
|
|
98
|
+
"",
|
|
99
|
+
"def only_dir_diff(bd, hd):",
|
|
100
|
+
" keys = set(bd) | set(hd)",
|
|
101
|
+
" for k in keys:",
|
|
102
|
+
" if is_dir_key(k):",
|
|
103
|
+
" continue",
|
|
104
|
+
" if bd.get(k) != hd.get(k):",
|
|
105
|
+
" return False",
|
|
106
|
+
" return True",
|
|
107
|
+
"",
|
|
108
|
+
"",
|
|
109
|
+
"def npm_root_deps(lock):",
|
|
110
|
+
' pkgs = lock.get("packages") if isinstance(lock, dict) else None',
|
|
111
|
+
' if isinstance(pkgs, dict) and isinstance(pkgs.get(""), dict):',
|
|
112
|
+
' return collect_deps(pkgs[""])',
|
|
113
|
+
' deps = lock.get("dependencies") if isinstance(lock, dict) else None',
|
|
114
|
+
" out = {}",
|
|
115
|
+
" if isinstance(deps, dict):",
|
|
116
|
+
" for k, v in deps.items():",
|
|
117
|
+
" if isinstance(v, dict):",
|
|
118
|
+
' out[k] = str(v.get("version", v))',
|
|
119
|
+
" elif isinstance(v, str):",
|
|
120
|
+
" out[k] = v",
|
|
121
|
+
" return out",
|
|
122
|
+
"",
|
|
123
|
+
"",
|
|
124
|
+
"def npm_lock_ok(base, head):",
|
|
125
|
+
" try:",
|
|
126
|
+
' b, h = json.loads(base or "{}"), json.loads(head or "{}")',
|
|
127
|
+
" except json.JSONDecodeError:",
|
|
128
|
+
" return False",
|
|
129
|
+
" br, hr = npm_root_deps(b), npm_root_deps(h)",
|
|
130
|
+
" if not only_dir_diff(br, hr):",
|
|
131
|
+
" return False",
|
|
132
|
+
' bp, hp = b.get("packages") or {}, h.get("packages") or {}',
|
|
133
|
+
" if not isinstance(bp, dict):",
|
|
134
|
+
" bp = {}",
|
|
135
|
+
" if not isinstance(hp, dict):",
|
|
136
|
+
" hp = {}",
|
|
137
|
+
" all_keys = set(bp) | set(hp)",
|
|
138
|
+
" for key in all_keys:",
|
|
139
|
+
' if key == "":',
|
|
140
|
+
" continue",
|
|
141
|
+
' if "node_modules/@deftai/directive" in key or "/@deftai/directive/" in key:',
|
|
142
|
+
" continue",
|
|
143
|
+
" if not deep_eq(bp.get(key), hp.get(key)):",
|
|
144
|
+
" return False",
|
|
145
|
+
" # lockfileVersion 1: freeze nested dependencies tree without directive keys",
|
|
146
|
+
" if not bp and not hp:",
|
|
147
|
+
" def strip_dir(v):",
|
|
148
|
+
" if not isinstance(v, dict):",
|
|
149
|
+
" return v",
|
|
150
|
+
" out = {}",
|
|
151
|
+
" for k, val in v.items():",
|
|
152
|
+
" if is_dir_key(k):",
|
|
153
|
+
" continue",
|
|
154
|
+
" if isinstance(val, dict):",
|
|
155
|
+
" nxt = dict(val)",
|
|
156
|
+
' if "dependencies" in val:',
|
|
157
|
+
' nxt["dependencies"] = strip_dir(val["dependencies"])',
|
|
158
|
+
" out[k] = nxt",
|
|
159
|
+
" else:",
|
|
160
|
+
" out[k] = val",
|
|
161
|
+
" return out",
|
|
162
|
+
' if not deep_eq(strip_dir(b.get("dependencies")), strip_dir(h.get("dependencies"))):',
|
|
163
|
+
" return False",
|
|
164
|
+
" return True",
|
|
165
|
+
"",
|
|
166
|
+
"",
|
|
167
|
+
"def unq(s):",
|
|
168
|
+
" s = s.strip()",
|
|
169
|
+
" if len(s) >= 2 and s[0] == s[-1] and s[0] in _Q:",
|
|
170
|
+
" return s[1:-1]",
|
|
171
|
+
" return s",
|
|
172
|
+
"",
|
|
173
|
+
"",
|
|
174
|
+
"def pnpm_root_deps(raw):",
|
|
175
|
+
" out = {}",
|
|
176
|
+
" in_imp = in_root = in_dep = False",
|
|
177
|
+
" cur = None",
|
|
178
|
+
" for line in raw.splitlines():",
|
|
179
|
+
' if re.match(r"^importers:\\s*$", line):',
|
|
180
|
+
" in_imp, in_root, in_dep, cur = True, False, False, None",
|
|
181
|
+
" continue",
|
|
182
|
+
" if not in_imp:",
|
|
183
|
+
" continue",
|
|
184
|
+
' if re.match(r"^[^\\s#]", line) and not line.startswith("importers"):',
|
|
185
|
+
" break",
|
|
186
|
+
' if re.match(r"^ {2}(?:\\.|\'\\.\'|\\"\\.\\"):\\s*$", line):',
|
|
187
|
+
" in_root, in_dep, cur = True, False, None",
|
|
188
|
+
" continue",
|
|
189
|
+
' if in_root and re.match(r"^ {2}\\S", line) and not re.match(r"^ {2}\\.", line):',
|
|
190
|
+
" in_root, in_dep, cur = False, False, None",
|
|
191
|
+
" continue",
|
|
192
|
+
" if not in_root:",
|
|
193
|
+
" continue",
|
|
194
|
+
" if re.match(",
|
|
195
|
+
' r"^ {4}(?:dependencies|devDependencies|optionalDependencies|peerDependencies):\\s*$",',
|
|
196
|
+
" line,",
|
|
197
|
+
" ):",
|
|
198
|
+
" in_dep, cur = True, None",
|
|
199
|
+
" continue",
|
|
200
|
+
' if in_dep and re.match(r"^ {4}\\S", line):',
|
|
201
|
+
" in_dep, cur = False, None",
|
|
202
|
+
" continue",
|
|
203
|
+
" if not in_dep:",
|
|
204
|
+
" continue",
|
|
205
|
+
' m = re.match(r"^ {6}(.+?):\\s*$", line)',
|
|
206
|
+
" if m:",
|
|
207
|
+
" cur = unq(m.group(1))",
|
|
208
|
+
" continue",
|
|
209
|
+
" if cur:",
|
|
210
|
+
' vm = re.match(r"^ {8}version:\\s*(.+?)\\s*$", line)',
|
|
211
|
+
" if vm:",
|
|
212
|
+
" out[cur] = unq(vm.group(1))",
|
|
213
|
+
" cur = None",
|
|
214
|
+
" return out",
|
|
215
|
+
"",
|
|
216
|
+
"",
|
|
217
|
+
"def pnpm_packages_by_name(raw):",
|
|
218
|
+
" out = {}",
|
|
219
|
+
" blocks = {}",
|
|
220
|
+
" in_pkg = False",
|
|
221
|
+
" cur = None",
|
|
222
|
+
" buf = []",
|
|
223
|
+
"",
|
|
224
|
+
" def flush():",
|
|
225
|
+
" nonlocal cur, buf",
|
|
226
|
+
" if cur is None:",
|
|
227
|
+
" return",
|
|
228
|
+
' blocks.setdefault(cur, []).append("\\n".join(buf))',
|
|
229
|
+
" cur, buf = None, []",
|
|
230
|
+
"",
|
|
231
|
+
" for line in raw.splitlines():",
|
|
232
|
+
' if re.match(r"^packages:\\s*$", line):',
|
|
233
|
+
" flush()",
|
|
234
|
+
" in_pkg = True",
|
|
235
|
+
" continue",
|
|
236
|
+
" if not in_pkg:",
|
|
237
|
+
" continue",
|
|
238
|
+
' if re.match(r"^[^\\s#]", line) and not line.startswith("packages"):',
|
|
239
|
+
" flush()",
|
|
240
|
+
" break",
|
|
241
|
+
' m = re.match(r"^ {2}(.+?):\\s*$", line)',
|
|
242
|
+
" if m:",
|
|
243
|
+
" flush()",
|
|
244
|
+
" key = unq(m.group(1))",
|
|
245
|
+
' at = key.find("@", 1) if key.startswith("@") else key.find("@")',
|
|
246
|
+
" cur = key[:at] if at > 0 else key",
|
|
247
|
+
" buf = [line]",
|
|
248
|
+
" continue",
|
|
249
|
+
" if cur is not None:",
|
|
250
|
+
" buf.append(line)",
|
|
251
|
+
" flush()",
|
|
252
|
+
" for name, blist in blocks.items():",
|
|
253
|
+
' out[name] = "\\n---\\n".join(sorted(blist))',
|
|
254
|
+
" return out",
|
|
255
|
+
"",
|
|
256
|
+
"",
|
|
257
|
+
"def pnpm_section_by_name(raw, section):",
|
|
258
|
+
" blocks, out = {}, {}",
|
|
259
|
+
" in_sec, cur, buf = False, None, []",
|
|
260
|
+
' sec_re = re.compile(r"^" + re.escape(section) + r":\\s*$")',
|
|
261
|
+
"",
|
|
262
|
+
" def flush():",
|
|
263
|
+
" nonlocal cur, buf",
|
|
264
|
+
" if cur is None:",
|
|
265
|
+
" return",
|
|
266
|
+
' blocks.setdefault(cur, []).append("\\n".join(buf))',
|
|
267
|
+
" cur, buf = None, []",
|
|
268
|
+
"",
|
|
269
|
+
" for line in raw.splitlines():",
|
|
270
|
+
" if sec_re.match(line):",
|
|
271
|
+
" flush()",
|
|
272
|
+
" in_sec = True",
|
|
273
|
+
" continue",
|
|
274
|
+
" if not in_sec:",
|
|
275
|
+
" continue",
|
|
276
|
+
' if re.match(r"^[^\\s#]", line) and not line.startswith(section):',
|
|
277
|
+
" flush()",
|
|
278
|
+
" break",
|
|
279
|
+
' m = re.match(r"^ {2}(.+?):\\s*$", line)',
|
|
280
|
+
" if m:",
|
|
281
|
+
" flush()",
|
|
282
|
+
" key = unq(m.group(1))",
|
|
283
|
+
' at = key.find("@", 1) if key.startswith("@") else key.find("@")',
|
|
284
|
+
" cur = key[:at] if at > 0 else key",
|
|
285
|
+
" buf = [line]",
|
|
286
|
+
" continue",
|
|
287
|
+
" if cur is not None:",
|
|
288
|
+
" buf.append(line)",
|
|
289
|
+
" flush()",
|
|
290
|
+
" for name, blist in blocks.items():",
|
|
291
|
+
' out[name] = "\\n---\\n".join(sorted(blist))',
|
|
292
|
+
" return out",
|
|
293
|
+
"",
|
|
294
|
+
"",
|
|
295
|
+
"def pnpm_ok(base, head):",
|
|
296
|
+
" br, hr = pnpm_root_deps(base), pnpm_root_deps(head)",
|
|
297
|
+
" if not only_dir_diff(br, hr):",
|
|
298
|
+
" return False",
|
|
299
|
+
' for section in ("packages", "snapshots"):',
|
|
300
|
+
" bp, hp = pnpm_section_by_name(base, section), pnpm_section_by_name(head, section)",
|
|
301
|
+
" for name in set(bp) | set(hp):",
|
|
302
|
+
" if is_dir_key(name):",
|
|
303
|
+
" continue",
|
|
304
|
+
" if bp.get(name) != hp.get(name):",
|
|
305
|
+
" return False",
|
|
306
|
+
" return True",
|
|
307
|
+
"",
|
|
308
|
+
"",
|
|
309
|
+
"def yarn_blocks(raw):",
|
|
310
|
+
" blocks = {}",
|
|
311
|
+
" names, buf = [], []",
|
|
312
|
+
"",
|
|
313
|
+
" def flush():",
|
|
314
|
+
" nonlocal names, buf",
|
|
315
|
+
" if not names:",
|
|
316
|
+
" return",
|
|
317
|
+
' body = "\\n".join(buf)',
|
|
318
|
+
" for n in names:",
|
|
319
|
+
" blocks[n] = body",
|
|
320
|
+
" names, buf = [], []",
|
|
321
|
+
"",
|
|
322
|
+
" for line in raw.splitlines():",
|
|
323
|
+
' if line == "" or line.startswith("#"):',
|
|
324
|
+
' if names and line == "":',
|
|
325
|
+
" flush()",
|
|
326
|
+
" continue",
|
|
327
|
+
' if not re.match(r"^\\s", line) and line.endswith(":"):',
|
|
328
|
+
" flush()",
|
|
329
|
+
" header = line[:-1]",
|
|
330
|
+
" names = []",
|
|
331
|
+
' for part in header.split(","):',
|
|
332
|
+
" p = part.strip()",
|
|
333
|
+
" if len(p) >= 2 and p[0] == p[-1] and p[0] in _Q:",
|
|
334
|
+
" p = p[1:-1]",
|
|
335
|
+
' at = p.find("@", 1) if p.startswith("@") else p.find("@")',
|
|
336
|
+
" names.append(p[:at] if at > 0 else p)",
|
|
337
|
+
" buf = [line]",
|
|
338
|
+
" continue",
|
|
339
|
+
" if names:",
|
|
340
|
+
" buf.append(line)",
|
|
341
|
+
" flush()",
|
|
342
|
+
" return blocks",
|
|
343
|
+
"",
|
|
344
|
+
"",
|
|
345
|
+
"def yarn_ok(base, head):",
|
|
346
|
+
" bb, hb = yarn_blocks(base), yarn_blocks(head)",
|
|
347
|
+
" for name in set(bb) | set(hb):",
|
|
348
|
+
" if is_dir_key(name):",
|
|
349
|
+
" continue",
|
|
350
|
+
" if bb.get(name) != hb.get(name):",
|
|
351
|
+
" return False",
|
|
352
|
+
" return True",
|
|
353
|
+
"",
|
|
354
|
+
"",
|
|
355
|
+
"def main(argv: list[str] | None = None) -> int:",
|
|
356
|
+
" args = list(sys.argv[1:] if argv is None else argv)",
|
|
357
|
+
" if len(args) < 2:",
|
|
358
|
+
' print("usage: core_guard_pin_content <base_sha> <head_sha>", file=sys.stderr)',
|
|
359
|
+
" return 2",
|
|
360
|
+
" base_sha, head_sha = args[0], args[1]",
|
|
361
|
+
" paths = changed_names(base_sha, head_sha)",
|
|
362
|
+
' core = [p for p in paths if p == ".deft/core" or p.startswith(".deft/core/")]',
|
|
363
|
+
" if not core:",
|
|
364
|
+
" return 0",
|
|
365
|
+
" checks = {",
|
|
366
|
+
' "package.json": pkg_pin_only,',
|
|
367
|
+
' "package-lock.json": npm_lock_ok,',
|
|
368
|
+
' "pnpm-lock.yaml": pnpm_ok,',
|
|
369
|
+
' "yarn.lock": yarn_ok,',
|
|
370
|
+
" }",
|
|
371
|
+
" bad = []",
|
|
372
|
+
" for path, fn in checks.items():",
|
|
373
|
+
" if path not in paths:",
|
|
374
|
+
" continue",
|
|
375
|
+
" if not fn(git_show(base_sha, path), git_show(head_sha, path)):",
|
|
376
|
+
" bad.append(path)",
|
|
377
|
+
" if bad:",
|
|
378
|
+
" print(",
|
|
379
|
+
' "::error title=deft-core guard (#3193)::package/lock co-travel with "',
|
|
380
|
+
' ".deft/core/** must be @deftai/directive* pin-only + lock follow-through. "',
|
|
381
|
+
' "Rejected: " + ", ".join(bad)',
|
|
382
|
+
" )",
|
|
383
|
+
' print("--- content-rejected pin/lock paths ---")',
|
|
384
|
+
' print("\\n".join(bad))',
|
|
385
|
+
" return 1",
|
|
386
|
+
' print("OK: package/lock content is Directive pin unit (#3193).")',
|
|
387
|
+
" return 0",
|
|
388
|
+
"",
|
|
389
|
+
"",
|
|
390
|
+
'if __name__ == "__main__":',
|
|
391
|
+
" sys.exit(main())",
|
|
392
|
+
].join("\n") + "\n";
|
|
393
|
+
//# sourceMappingURL=core-guard-pin-content.js.map
|
|
@@ -29,7 +29,16 @@ export const CANONICAL_GITIGNORE_BASELINE = [
|
|
|
29
29
|
".deft/.cli/",
|
|
30
30
|
".deft/ritual-state.json",
|
|
31
31
|
".deft/last-session.json",
|
|
32
|
+
".deft/occupancy.json",
|
|
32
33
|
".deft/routing.local.json",
|
|
34
|
+
// Agent-host working state (#3502). Selective, NEVER blanket `.claude/`:
|
|
35
|
+
// `.claude/settings.json`, `.claude/skills/` and `.claude/commands/` are
|
|
36
|
+
// MANAGED DEPOSITS (agent-hooks.ts / skill-discovery-hosts.ts) and must stay
|
|
37
|
+
// trackable -- same #1144 hybrid rule that forbids blanket `.eval/`.
|
|
38
|
+
// Un-ignored agent worktrees leave a permanently dirty tree, which refuses
|
|
39
|
+
// release Step 1 for every consumer that dispatches subagents.
|
|
40
|
+
".claude/worktrees/",
|
|
41
|
+
".claude/settings.local.json",
|
|
33
42
|
// #3282: opt-in default run-summary JSONL at repo root (collectible; must not dirty trees).
|
|
34
43
|
".deft-run-summary.json",
|
|
35
44
|
// Temporary test/local kill-switch — must stay untracked (#3039).
|