@deftai/directive-runtime 0.129.5 → 0.129.7
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/Taskfile.yml +316 -0
- package/UPGRADING.md +1 -0
- package/commands.md +5 -3
- package/contracts/design-critique.md +1 -1
- package/contracts/path-write-fence.md +6 -0
- package/dist/applying-host-release.d.ts +16 -0
- package/dist/applying-host-release.js +98 -0
- package/dist/authz.d.ts +1 -1
- package/dist/authz.js +1 -1
- package/dist/check.d.ts +1 -0
- package/dist/check.js +27 -4
- package/dist/design-critique-ensure-arc-dest.d.ts +16 -0
- package/dist/design-critique-ensure-arc-dest.js +168 -0
- package/dist/dispatch.d.ts +1 -1
- package/dist/dispatch.js +8 -0
- package/dist/hook-dispatch.js +3 -2
- package/dist/human-presence-mint.d.ts +6 -1
- package/dist/human-presence-mint.js +20 -6
- package/dist/session-start.d.ts +8 -2
- package/dist/session-start.js +70 -15
- package/dist/setup-wiring.d.ts +36 -0
- package/dist/setup-wiring.js +169 -14
- package/dist/vbrief-preflight.d.ts +4 -0
- package/dist/vbrief-preflight.js +34 -0
- package/dist/verify-scope-provenance.d.ts +13 -1
- package/dist/verify-scope-provenance.js +44 -1
- package/dist/verify-source-cli/verify-deposit-closure.js +5 -5
- package/dist/windows-bin-ps1.d.ts +2 -2
- package/dist/windows-bin-ps1.js +5 -11
- package/docs/deft-directive-disable.md +3 -3
- package/docs/getting-started.md +2 -0
- package/docs/scope-provenance.md +15 -1
- package/package.json +2 -3
- package/packs/lessons/lessons-pack-0.1.json +15 -0
- package/packs/skills/skills-pack-0.1.json +3 -3
- package/skills/deft-directive-design-critique/SKILL.md +1 -1
- package/skills/deft-directive-release/SKILL.md +31 -1
- package/skills/deft-directive-review-cycle/SKILL.md +15 -6
- package/skills/deft-directive-swarm/references/host-grok-build.md +3 -2
- package/vendor/directive-content/Taskfile.yml +316 -0
- package/vendor/directive-content/UPGRADING.md +1 -0
- package/vendor/directive-content/commands.md +5 -3
- package/vendor/directive-content/contracts/design-critique.md +1 -1
- package/vendor/directive-content/contracts/path-write-fence.md +6 -0
- package/vendor/directive-content/docs/deft-directive-disable.md +3 -3
- package/vendor/directive-content/docs/getting-started.md +2 -0
- package/vendor/directive-content/docs/scope-provenance.md +15 -1
- package/vendor/directive-content/packs/lessons/lessons-pack-0.1.json +15 -0
- package/vendor/directive-content/packs/skills/skills-pack-0.1.json +3 -3
- package/vendor/directive-content/skills/deft-directive-design-critique/SKILL.md +1 -1
- package/vendor/directive-content/skills/deft-directive-release/SKILL.md +31 -1
- package/vendor/directive-content/skills/deft-directive-review-cycle/SKILL.md +15 -6
- package/vendor/directive-content/skills/deft-directive-swarm/references/host-grok-build.md +3 -2
- package/vendor/directive-core/dist/.tsbuildinfo +1 -1
- package/vendor/directive-core/dist/authz/classify.d.ts +12 -0
- package/vendor/directive-core/dist/authz/classify.d.ts.map +1 -1
- package/vendor/directive-core/dist/authz/classify.js +40 -12
- package/vendor/directive-core/dist/authz/classify.js.map +1 -1
- package/vendor/directive-core/dist/authz/templates.d.ts +2 -2
- package/vendor/directive-core/dist/authz/templates.d.ts.map +1 -1
- package/vendor/directive-core/dist/authz/templates.js +1 -0
- package/vendor/directive-core/dist/authz/templates.js.map +1 -1
- package/vendor/directive-core/dist/authz/types.d.ts +1 -1
- package/vendor/directive-core/dist/authz/types.d.ts.map +1 -1
- package/vendor/directive-core/dist/authz/types.js +2 -0
- package/vendor/directive-core/dist/authz/types.js.map +1 -1
- package/vendor/directive-core/dist/authz/verb-classification.d.ts.map +1 -1
- package/vendor/directive-core/dist/authz/verb-classification.js +30 -3
- package/vendor/directive-core/dist/authz/verb-classification.js.map +1 -1
- package/vendor/directive-core/dist/cache/fetch.d.ts.map +1 -1
- package/vendor/directive-core/dist/cache/fetch.js +50 -4
- package/vendor/directive-core/dist/cache/fetch.js.map +1 -1
- package/vendor/directive-core/dist/design-critique/arc-dest.d.ts +22 -5
- package/vendor/directive-core/dist/design-critique/arc-dest.d.ts.map +1 -1
- package/vendor/directive-core/dist/design-critique/arc-dest.js +61 -0
- package/vendor/directive-core/dist/design-critique/arc-dest.js.map +1 -1
- package/vendor/directive-core/dist/design-critique/run-posture.d.ts +7 -2
- package/vendor/directive-core/dist/design-critique/run-posture.d.ts.map +1 -1
- package/vendor/directive-core/dist/design-critique/run-posture.js +6 -1
- package/vendor/directive-core/dist/design-critique/run-posture.js.map +1 -1
- package/vendor/directive-core/dist/fs/contained-write.d.ts +8 -2
- package/vendor/directive-core/dist/fs/contained-write.d.ts.map +1 -1
- package/vendor/directive-core/dist/fs/contained-write.js +22 -6
- package/vendor/directive-core/dist/fs/contained-write.js.map +1 -1
- package/vendor/directive-core/dist/hooks/dispatcher.d.ts +1 -1
- package/vendor/directive-core/dist/hooks/dispatcher.d.ts.map +1 -1
- package/vendor/directive-core/dist/hooks/dispatcher.js +290 -16
- package/vendor/directive-core/dist/hooks/dispatcher.js.map +1 -1
- package/vendor/directive-core/dist/hooks/shell-write-targets.d.ts +5 -0
- package/vendor/directive-core/dist/hooks/shell-write-targets.d.ts.map +1 -1
- package/vendor/directive-core/dist/hooks/shell-write-targets.js +18 -1
- package/vendor/directive-core/dist/hooks/shell-write-targets.js.map +1 -1
- package/vendor/directive-core/dist/init-deposit/agent-hooks.d.ts +26 -1
- package/vendor/directive-core/dist/init-deposit/agent-hooks.d.ts.map +1 -1
- package/vendor/directive-core/dist/init-deposit/agent-hooks.js +52 -3
- package/vendor/directive-core/dist/init-deposit/agent-hooks.js.map +1 -1
- package/vendor/directive-core/dist/init-deposit/host-hook-outer.d.ts +48 -0
- package/vendor/directive-core/dist/init-deposit/host-hook-outer.d.ts.map +1 -1
- package/vendor/directive-core/dist/init-deposit/host-hook-outer.js +170 -9
- package/vendor/directive-core/dist/init-deposit/host-hook-outer.js.map +1 -1
- package/vendor/directive-core/dist/init-deposit/scaffold.d.ts +8 -1
- package/vendor/directive-core/dist/init-deposit/scaffold.d.ts.map +1 -1
- package/vendor/directive-core/dist/init-deposit/scaffold.js +38 -4
- package/vendor/directive-core/dist/init-deposit/scaffold.js.map +1 -1
- package/vendor/directive-core/dist/install-health/cheap.d.ts +2 -1
- package/vendor/directive-core/dist/install-health/cheap.d.ts.map +1 -1
- package/vendor/directive-core/dist/install-health/cheap.js +4 -3
- package/vendor/directive-core/dist/install-health/cheap.js.map +1 -1
- package/vendor/directive-core/dist/install-health/constants.d.ts +18 -2
- package/vendor/directive-core/dist/install-health/constants.d.ts.map +1 -1
- package/vendor/directive-core/dist/install-health/constants.js +18 -2
- package/vendor/directive-core/dist/install-health/constants.js.map +1 -1
- package/vendor/directive-core/dist/policy/deft-directive-disable.d.ts +42 -5
- package/vendor/directive-core/dist/policy/deft-directive-disable.d.ts.map +1 -1
- package/vendor/directive-core/dist/policy/deft-directive-disable.js +71 -41
- package/vendor/directive-core/dist/policy/deft-directive-disable.js.map +1 -1
- package/vendor/directive-core/dist/pr-closeout-attestable/evaluate.d.ts +6 -1
- package/vendor/directive-core/dist/pr-closeout-attestable/evaluate.d.ts.map +1 -1
- package/vendor/directive-core/dist/pr-closeout-attestable/evaluate.js +24 -12
- package/vendor/directive-core/dist/pr-closeout-attestable/evaluate.js.map +1 -1
- package/vendor/directive-core/dist/pr-closeout-attestable/pr-head-assert.d.ts +68 -14
- package/vendor/directive-core/dist/pr-closeout-attestable/pr-head-assert.d.ts.map +1 -1
- package/vendor/directive-core/dist/pr-closeout-attestable/pr-head-assert.js +278 -47
- package/vendor/directive-core/dist/pr-closeout-attestable/pr-head-assert.js.map +1 -1
- package/vendor/directive-core/dist/pr-merge-readiness/slizard-gate.d.ts +10 -5
- package/vendor/directive-core/dist/pr-merge-readiness/slizard-gate.d.ts.map +1 -1
- package/vendor/directive-core/dist/pr-merge-readiness/slizard-gate.js +41 -18
- package/vendor/directive-core/dist/pr-merge-readiness/slizard-gate.js.map +1 -1
- package/vendor/directive-core/dist/preflight-gh/pre-push.d.ts +3 -2
- package/vendor/directive-core/dist/preflight-gh/pre-push.d.ts.map +1 -1
- package/vendor/directive-core/dist/preflight-gh/pre-push.js +19 -18
- package/vendor/directive-core/dist/preflight-gh/pre-push.js.map +1 -1
- package/vendor/directive-core/dist/release/gh.d.ts.map +1 -1
- package/vendor/directive-core/dist/release/gh.js +2 -1
- package/vendor/directive-core/dist/release/gh.js.map +1 -1
- package/vendor/directive-core/dist/release/version.d.ts +4 -2
- package/vendor/directive-core/dist/release/version.d.ts.map +1 -1
- package/vendor/directive-core/dist/release/version.js +4 -2
- package/vendor/directive-core/dist/release/version.js.map +1 -1
- package/vendor/directive-core/dist/release-publish/gh-api.d.ts.map +1 -1
- package/vendor/directive-core/dist/release-publish/gh-api.js +4 -2
- package/vendor/directive-core/dist/release-publish/gh-api.js.map +1 -1
- package/vendor/directive-core/dist/release-publish/main.d.ts.map +1 -1
- package/vendor/directive-core/dist/release-publish/main.js +15 -4
- package/vendor/directive-core/dist/release-publish/main.js.map +1 -1
- package/vendor/directive-core/dist/release-publish/pipeline.d.ts +11 -0
- package/vendor/directive-core/dist/release-publish/pipeline.d.ts.map +1 -1
- package/vendor/directive-core/dist/release-publish/pipeline.js +143 -2
- package/vendor/directive-core/dist/release-publish/pipeline.js.map +1 -1
- package/vendor/directive-core/dist/release-rollback/gh.d.ts.map +1 -1
- package/vendor/directive-core/dist/release-rollback/gh.js +2 -1
- package/vendor/directive-core/dist/release-rollback/gh.js.map +1 -1
- package/vendor/directive-core/dist/scope/delivery-evidence.d.ts +202 -19
- package/vendor/directive-core/dist/scope/delivery-evidence.d.ts.map +1 -1
- package/vendor/directive-core/dist/scope/delivery-evidence.js +948 -107
- package/vendor/directive-core/dist/scope/delivery-evidence.js.map +1 -1
- package/vendor/directive-core/dist/scope/transition.d.ts +4 -1
- package/vendor/directive-core/dist/scope/transition.d.ts.map +1 -1
- package/vendor/directive-core/dist/scope/transition.js +2 -2
- package/vendor/directive-core/dist/scope/transition.js.map +1 -1
- package/vendor/directive-core/dist/scope-provenance/base-fence.d.ts +11 -2
- package/vendor/directive-core/dist/scope-provenance/base-fence.d.ts.map +1 -1
- package/vendor/directive-core/dist/scope-provenance/base-fence.js +16 -1
- package/vendor/directive-core/dist/scope-provenance/base-fence.js.map +1 -1
- package/vendor/directive-core/dist/scope-provenance/evaluate.d.ts +12 -0
- package/vendor/directive-core/dist/scope-provenance/evaluate.d.ts.map +1 -1
- package/vendor/directive-core/dist/scope-provenance/evaluate.js +41 -5
- package/vendor/directive-core/dist/scope-provenance/evaluate.js.map +1 -1
- package/vendor/directive-core/dist/scope-provenance/forge-approval.d.ts +106 -0
- package/vendor/directive-core/dist/scope-provenance/forge-approval.d.ts.map +1 -0
- package/vendor/directive-core/dist/scope-provenance/forge-approval.js +382 -0
- package/vendor/directive-core/dist/scope-provenance/forge-approval.js.map +1 -0
- package/vendor/directive-core/dist/session/git.d.ts +21 -2
- package/vendor/directive-core/dist/session/git.d.ts.map +1 -1
- package/vendor/directive-core/dist/session/git.js +21 -4
- package/vendor/directive-core/dist/session/git.js.map +1 -1
- package/vendor/directive-core/dist/session/occupancy.d.ts +93 -6
- package/vendor/directive-core/dist/session/occupancy.d.ts.map +1 -1
- package/vendor/directive-core/dist/session/occupancy.js +215 -52
- package/vendor/directive-core/dist/session/occupancy.js.map +1 -1
- package/vendor/directive-core/dist/session/orientation-compression.d.ts +18 -2
- package/vendor/directive-core/dist/session/orientation-compression.d.ts.map +1 -1
- package/vendor/directive-core/dist/session/orientation-compression.js +38 -5
- package/vendor/directive-core/dist/session/orientation-compression.js.map +1 -1
- package/vendor/directive-core/dist/session/session-start.d.ts +47 -2
- package/vendor/directive-core/dist/session/session-start.d.ts.map +1 -1
- package/vendor/directive-core/dist/session/session-start.js +154 -3
- package/vendor/directive-core/dist/session/session-start.js.map +1 -1
- package/vendor/directive-core/dist/swarm/approach1-babysitter.d.ts +18 -4
- package/vendor/directive-core/dist/swarm/approach1-babysitter.d.ts.map +1 -1
- package/vendor/directive-core/dist/swarm/approach1-babysitter.js +28 -4
- package/vendor/directive-core/dist/swarm/approach1-babysitter.js.map +1 -1
- package/vendor/directive-core/dist/swarm/dest-place.d.ts +1 -1
- package/vendor/directive-core/dist/swarm/dest-place.d.ts.map +1 -1
- package/vendor/directive-core/dist/swarm/dest-place.js +36 -41
- package/vendor/directive-core/dist/swarm/dest-place.js.map +1 -1
- package/vendor/directive-core/dist/swarm/finalize-cohort.d.ts +29 -0
- package/vendor/directive-core/dist/swarm/finalize-cohort.d.ts.map +1 -1
- package/vendor/directive-core/dist/swarm/finalize-cohort.js +122 -11
- package/vendor/directive-core/dist/swarm/finalize-cohort.js.map +1 -1
- package/vendor/directive-core/dist/swarm/finalize-owed.d.ts +14 -0
- package/vendor/directive-core/dist/swarm/finalize-owed.d.ts.map +1 -1
- package/vendor/directive-core/dist/swarm/finalize-owed.js +214 -48
- package/vendor/directive-core/dist/swarm/finalize-owed.js.map +1 -1
- package/vendor/directive-core/dist/swarm/launch.d.ts.map +1 -1
- package/vendor/directive-core/dist/swarm/launch.js +15 -4
- package/vendor/directive-core/dist/swarm/launch.js.map +1 -1
- package/vendor/directive-core/dist/swarm/worktree-pm-install.d.ts +49 -2
- package/vendor/directive-core/dist/swarm/worktree-pm-install.d.ts.map +1 -1
- package/vendor/directive-core/dist/swarm/worktree-pm-install.js +207 -12
- package/vendor/directive-core/dist/swarm/worktree-pm-install.js.map +1 -1
- package/vendor/directive-core/dist/swarm/worktrees-cli.d.ts +6 -0
- package/vendor/directive-core/dist/swarm/worktrees-cli.d.ts.map +1 -1
- package/vendor/directive-core/dist/swarm/worktrees-cli.js +79 -2
- package/vendor/directive-core/dist/swarm/worktrees-cli.js.map +1 -1
- package/vendor/directive-core/dist/swarm/worktrees.d.ts +12 -1
- package/vendor/directive-core/dist/swarm/worktrees.d.ts.map +1 -1
- package/vendor/directive-core/dist/swarm/worktrees.js +34 -26
- package/vendor/directive-core/dist/swarm/worktrees.js.map +1 -1
- package/vendor/directive-core/dist/triage/evaluate/worktrees.d.ts.map +1 -1
- package/vendor/directive-core/dist/triage/evaluate/worktrees.js +219 -60
- package/vendor/directive-core/dist/triage/evaluate/worktrees.js.map +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
|
-
import { existsSync, readdirSync, realpathSync } from "node:fs";
|
|
3
|
-
import { basename, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
4
|
-
import { appendAuthzAudit, classifyHookAuthzOps, evaluateAuthzMutation, evidenceSatisfiesImplementationApproval, listActiveHumanGrants, loadAuthzStateResult, markGrantUsed, shouldConsumeSingleUseGrant, utcIso, } from "../authz/index.js";
|
|
2
|
+
import { existsSync, lstatSync, readdirSync, readlinkSync, realpathSync } from "node:fs";
|
|
3
|
+
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
4
|
+
import { appendAuthzAudit, classifyHookAuthzOps, evaluateAuthzMutation, evidenceSatisfiesImplementationApproval, hasKillSwitchShellWrite, isKillSwitchPlantPath, listActiveHumanGrants, loadAuthzStateResult, markGrantUsed, shouldConsumeSingleUseGrant, utcIso, } from "../authz/index.js";
|
|
5
5
|
import { shellCommandHasPayloadRootProtectedDestAfterRealpath } from "../authz/protected-dest-realpath.js";
|
|
6
6
|
import { prepareGithubOnlyDest } from "../design-critique/run-posture.js";
|
|
7
7
|
import { runningInsideDeftRepo } from "../doctor/paths.js";
|
|
@@ -29,6 +29,7 @@ import { inspectSessionRitual, verifySessionRitual, WRITE_GATED_REQUIRED_STEPS,
|
|
|
29
29
|
import { countModelFlagsInLauncherArgv, evaluateSpawnRoutingHonor, extractModelFromLauncherArgv, extractRequestedModelFromPayload, extractStructuralWorkerRole, } from "../swarm/routing-honor.js";
|
|
30
30
|
import { formatLauncherCorrectLifecycleRecovery, UNRESOLVED_HOST_OWNER, uninspectableLifecycleDenyMessage, } from "./classify/host-session-identity.js";
|
|
31
31
|
import { applyPatchHarvestedInputUnclassified, fieldString, firstString, hintUninspectableLifecycleCommand, hookApplyPatchBodyPaths, hookApplyPatchBodyText, hookMcpArgsText, hookMutationTargetPaths, hookShellCommand, hookToolName, hookWriteTargetPath, hostIdentityFallsBackToExplicitOwner, inspectExactLifecycleCommand, inspectHintedLifecycleSessionId, landProcessOnlyFlagOnToolInput, missingToolNameMessage, normalizeMutationTargetPaths, record, resolveHookHostIdentity, rewriteExactLifecycleCommand, toolInputRecord, } from "./classify/index.js";
|
|
32
|
+
import { GROK_SPAWN_WRITING_SKIP_CLASS_FIELD, PROCESS_ONLY_FLAG_KEYS } from "./classify/payload.js";
|
|
32
33
|
import { defaultCursorPlanChoiceDeps, isCursorPlanChoiceManagedPath, storeDenyMessage, } from "./cursor-plan-choice/index.js";
|
|
33
34
|
import { classifyGitDestructive, classifyProductDestForms, payloadWithInjectedWriteTarget, } from "./dest-form.js";
|
|
34
35
|
import { decidePlanChoiceWithHatch, decideQuestionHatchGate, decideQuestionHatchPauseGate, decideSpendRecommendGate, } from "./dispatcher-plan-choice.js";
|
|
@@ -38,7 +39,7 @@ import { isLexicalOutsideProjectRoot, isOutsideProjectRootWrite } from "./outsid
|
|
|
38
39
|
import { restampOwnerLivenessOnHookEvent, } from "./owner-liveness.js";
|
|
39
40
|
import { appliesGrokSpawnDestContract, isAssistPosture, isEphemeralSpawn, isExploreSpawn, isProcessOnlyCriticSpawn, isReadOnlyHookContext, processOnlyCriticRequiresDest, SPAWN_CLASS_RECOVERY, SPAWN_READ_ONLY_RECOVERY, } from "./readonly.js";
|
|
40
41
|
import { inspectActiveScope, POSITIVE_GOVERNING_ALLOW_REQUIRED, } from "./scope.js";
|
|
41
|
-
import { classifyShellWriteTargets, isInRepoShellWritePath } from "./shell-write-targets.js";
|
|
42
|
+
import { classifyShellWriteTargets, isInRepoShellWritePath, isKillSwitchShellWriteBasename, } from "./shell-write-targets.js";
|
|
42
43
|
import { effectiveHookArgumentView, effectiveHookToolName, expectsLocalMutationDest, isApplyPatchTool, isDirectWriteTool, isKillTool, isMcpProxyWrapper, isMcpTool, isMcpWriteShaped, isShellTool, isSpawnTool, } from "./tools.js";
|
|
43
44
|
// Pure parse/classify helpers are defined in ./classify/ and re-exported from
|
|
44
45
|
// ./index.ts (#2950). Dispatcher is orchestration: classify → policy → decision.
|
|
@@ -100,7 +101,117 @@ function isLauncherFamilySpawnNotReady(input, toolName) {
|
|
|
100
101
|
});
|
|
101
102
|
return launcher.kind === "launcher" || launcher.kind === "compound";
|
|
102
103
|
}
|
|
104
|
+
function recordPayload4781(value) {
|
|
105
|
+
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
106
|
+
? value
|
|
107
|
+
: null;
|
|
108
|
+
}
|
|
109
|
+
function fieldString4781(input, key) {
|
|
110
|
+
const value = input[key];
|
|
111
|
+
if (typeof value === "string" && value.trim().length > 0)
|
|
112
|
+
return value.trim();
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
function toolInput4781(payload) {
|
|
116
|
+
return (recordPayload4781(payload.tool_input) ??
|
|
117
|
+
recordPayload4781(payload.toolInput) ??
|
|
118
|
+
recordPayload4781(payload.input) ??
|
|
119
|
+
recordPayload4781(payload.arguments) ??
|
|
120
|
+
payload);
|
|
121
|
+
}
|
|
122
|
+
function fieldTruthy4781(input, key) {
|
|
123
|
+
const value = input[key];
|
|
124
|
+
if (value === true)
|
|
125
|
+
return true;
|
|
126
|
+
if (typeof value === "number")
|
|
127
|
+
return value === 1;
|
|
128
|
+
if (typeof value === "string") {
|
|
129
|
+
const t = value.trim().toLowerCase();
|
|
130
|
+
return t === "1" || t === "true" || t === "yes" || t === "on";
|
|
131
|
+
}
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
/** Prefer-A #4781: process_only/plan marker present before implement-conflict gate. */
|
|
135
|
+
function hasProcessOnlySkipMarker4781(payload) {
|
|
136
|
+
const input = recordPayload4781(payload);
|
|
137
|
+
if (input === null)
|
|
138
|
+
return false;
|
|
139
|
+
const toolInput = toolInput4781(input);
|
|
140
|
+
const subagentType = fieldString4781(toolInput, "subagent_type") ??
|
|
141
|
+
fieldString4781(toolInput, "subagentType") ??
|
|
142
|
+
fieldString4781(input, "subagent_type") ??
|
|
143
|
+
fieldString4781(input, "subagentType");
|
|
144
|
+
if (subagentType?.toLowerCase() === "plan")
|
|
145
|
+
return true;
|
|
146
|
+
if (GROK_SPAWN_WRITING_SKIP_CLASS_FIELD !== "process_only")
|
|
147
|
+
return false;
|
|
148
|
+
return PROCESS_ONLY_FLAG_KEYS.some((key) => fieldTruthy4781(toolInput, key) || fieldTruthy4781(input, key));
|
|
149
|
+
}
|
|
150
|
+
/** Prefer-A #4781: name suppressing implement field when present. */
|
|
151
|
+
function namedImplementConflictSuppressor4781(payload) {
|
|
152
|
+
const input = recordPayload4781(payload);
|
|
153
|
+
if (input === null)
|
|
154
|
+
return null;
|
|
155
|
+
const toolInput = toolInput4781(input);
|
|
156
|
+
const driveTo = fieldString4781(toolInput, "drive_to") ??
|
|
157
|
+
fieldString4781(toolInput, "driveTo") ??
|
|
158
|
+
fieldString4781(toolInput, "drive-to") ??
|
|
159
|
+
fieldString4781(input, "drive_to") ??
|
|
160
|
+
fieldString4781(input, "driveTo") ??
|
|
161
|
+
fieldString4781(input, "drive-to");
|
|
162
|
+
if (driveTo !== null) {
|
|
163
|
+
const normalized = driveTo.toLowerCase().replace(/[_\s]/g, "-");
|
|
164
|
+
if (normalized === "merge-ready" ||
|
|
165
|
+
normalized === "merge" ||
|
|
166
|
+
normalized.startsWith("merge-") ||
|
|
167
|
+
normalized.includes("implement")) {
|
|
168
|
+
return "drive_to";
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const workerRole = fieldString4781(toolInput, "worker_role") ??
|
|
172
|
+
fieldString4781(toolInput, "workerRole") ??
|
|
173
|
+
fieldString4781(input, "worker_role") ??
|
|
174
|
+
fieldString4781(input, "workerRole");
|
|
175
|
+
if (workerRole !== null) {
|
|
176
|
+
const role = workerRole.toLowerCase().replace(/[_\s]/g, "-");
|
|
177
|
+
if (role === "leaf-implementation" ||
|
|
178
|
+
role === "implementation" ||
|
|
179
|
+
role === "implement" ||
|
|
180
|
+
role.includes("implement")) {
|
|
181
|
+
return "worker_role";
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const dispatchKind = fieldString4781(toolInput, "dispatch_kind") ??
|
|
185
|
+
fieldString4781(toolInput, "dispatchKind") ??
|
|
186
|
+
fieldString4781(input, "dispatch_kind") ??
|
|
187
|
+
fieldString4781(input, "dispatchKind");
|
|
188
|
+
if (dispatchKind !== null) {
|
|
189
|
+
const kind = dispatchKind.toLowerCase().replace(/[_\s]/g, "-");
|
|
190
|
+
if (kind === "swarm-cohort" || kind === "swarm-leaf" || kind.includes("implement")) {
|
|
191
|
+
return "dispatch_kind";
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
function processOnlyImplementConflictSuppressor4781(payload) {
|
|
197
|
+
if (!hasProcessOnlySkipMarker4781(payload))
|
|
198
|
+
return null;
|
|
199
|
+
return namedImplementConflictSuppressor4781(payload);
|
|
200
|
+
}
|
|
201
|
+
/** Prefer-A #4781: name implement-conflict suppressor when process_only is present but blocked. */
|
|
202
|
+
function overlayProcessOnlyImplementConflictSuppressor(input, decision) {
|
|
203
|
+
if (decision.verdict !== "deny")
|
|
204
|
+
return decision;
|
|
205
|
+
const field = processOnlyImplementConflictSuppressor4781(input.payload);
|
|
206
|
+
if (field === null)
|
|
207
|
+
return decision;
|
|
208
|
+
const note = `process_only was suppressed by ${field} (implement conflict wins; not bare #2885).`;
|
|
209
|
+
if (decision.message.includes(note))
|
|
210
|
+
return decision;
|
|
211
|
+
return { ...decision, message: `${note} ${decision.message}` };
|
|
212
|
+
}
|
|
103
213
|
function overlayGrokCriticSpawnNotReadyRecovery(input, toolName, decision) {
|
|
214
|
+
decision = overlayProcessOnlyImplementConflictSuppressor(input, decision);
|
|
104
215
|
if (decision.verdict !== "deny" || decision.code !== "spawn-not-ready")
|
|
105
216
|
return decision;
|
|
106
217
|
if (!appliesGrokSpawnDestContract({
|
|
@@ -827,6 +938,65 @@ function recordAuthzAudit(projectRoot, decision, state, seams) {
|
|
|
827
938
|
// Audit write must not crash the host tool gate.
|
|
828
939
|
}
|
|
829
940
|
}
|
|
941
|
+
/**
|
|
942
|
+
* Resolve as far as the filesystem allows: realpath existing prefixes even when
|
|
943
|
+
* the leaf is missing (dangling multi-hop symlink parents).
|
|
944
|
+
*/
|
|
945
|
+
function realpathExistingParents(absPath) {
|
|
946
|
+
try {
|
|
947
|
+
return realpathSync(absPath);
|
|
948
|
+
}
|
|
949
|
+
catch {
|
|
950
|
+
const parent = dirname(absPath);
|
|
951
|
+
if (parent === absPath)
|
|
952
|
+
return absPath;
|
|
953
|
+
return join(realpathExistingParents(parent), basename(absPath));
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
/**
|
|
957
|
+
* True when a kill-switch plant path realpath-resolves under `.deft/authz/` or
|
|
958
|
+
* `.deft/approved-scope/` (symlink alias). Does not treat the flag basename
|
|
959
|
+
* itself as an inventoried-store hit (#6136 Greptile).
|
|
960
|
+
* Dangling symlinks: resolve link text, then realpath existing parent dirs so a
|
|
961
|
+
* directory alias into the store is not missed (#6158 Greptile P1).
|
|
962
|
+
*/
|
|
963
|
+
function killSwitchPlantResolvesToInventoriedAuthzStore(projectRoot, relOrAbsPath) {
|
|
964
|
+
const root = resolve(projectRoot);
|
|
965
|
+
const target = isAbsolute(relOrAbsPath)
|
|
966
|
+
? resolve(relOrAbsPath)
|
|
967
|
+
: resolve(root, relOrAbsPath.replace(/\\/g, "/"));
|
|
968
|
+
let resolved;
|
|
969
|
+
try {
|
|
970
|
+
resolved = realpathSync(target);
|
|
971
|
+
}
|
|
972
|
+
catch {
|
|
973
|
+
try {
|
|
974
|
+
const st = lstatSync(target);
|
|
975
|
+
if (!st.isSymbolicLink())
|
|
976
|
+
return false;
|
|
977
|
+
const link = readlinkSync(target);
|
|
978
|
+
const candidate = isAbsolute(link) ? resolve(link) : resolve(dirname(target), link);
|
|
979
|
+
resolved = realpathExistingParents(candidate);
|
|
980
|
+
}
|
|
981
|
+
catch {
|
|
982
|
+
return false;
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
let rootReal;
|
|
986
|
+
try {
|
|
987
|
+
rootReal = realpathSync(root);
|
|
988
|
+
}
|
|
989
|
+
catch {
|
|
990
|
+
return false;
|
|
991
|
+
}
|
|
992
|
+
const rel = relative(rootReal, resolved).split(sep).join("/").replace(/\\/g, "/").toLowerCase();
|
|
993
|
+
if (rel.length === 0 || rel.startsWith(".."))
|
|
994
|
+
return false;
|
|
995
|
+
return (rel === ".deft/authz" ||
|
|
996
|
+
rel.startsWith(".deft/authz/") ||
|
|
997
|
+
rel === ".deft/approved-scope" ||
|
|
998
|
+
rel.startsWith(".deft/approved-scope/"));
|
|
999
|
+
}
|
|
830
1000
|
/**
|
|
831
1001
|
* UAT lease + human-origin grant gate (#2944). Returns deny decision or null when allowed.
|
|
832
1002
|
* Composes before runtimeAuthority path/scope checks for direct writes and shell/MCP.
|
|
@@ -853,6 +1023,7 @@ function authzForMutation(input, toolName, seams, options) {
|
|
|
853
1023
|
shellCommand,
|
|
854
1024
|
isDirectWrite: options.isDirectWrite,
|
|
855
1025
|
mcpArgsText: options.isDirectWrite ? null : hookMcpArgsText(input.payload),
|
|
1026
|
+
writePath: options.isDirectWrite ? options.relPath : null,
|
|
856
1027
|
});
|
|
857
1028
|
// #4188: realpath recovered dest-of-write against payload root. Lexical
|
|
858
1029
|
// classify stays I/O-free; a non-shell symlink dest is grant-immune unknown.
|
|
@@ -881,9 +1052,24 @@ function authzForMutation(input, toolName, seams, options) {
|
|
|
881
1052
|
branch = null;
|
|
882
1053
|
}
|
|
883
1054
|
const repo = (process.env.DEFT_AUTHZ_REPO ?? process.env.GITHUB_REPOSITORY ?? "").trim() || null;
|
|
1055
|
+
// #6136: kill-switch / permanent opt-out plant is always-on grant-gated (not UAT-only).
|
|
1056
|
+
const killSwitchPlant = (shellCommand !== null && hasKillSwitchShellWrite(shellCommand)) ||
|
|
1057
|
+
(options.isDirectWrite && options.relPath !== null && isKillSwitchPlantPath(options.relPath));
|
|
1058
|
+
// Symlink plant of a kill-switch basename into `.deft/authz/` / approved-scope
|
|
1059
|
+
// must not ride a settings grant (settings op skips isProtectedStoreEditDest).
|
|
1060
|
+
// Plain flag basenames are themselves "protected" in relIsProtectedDirectiveDest;
|
|
1061
|
+
// only deny when realpath lands under the inventoried store dirs (#6136 Greptile).
|
|
1062
|
+
if (killSwitchPlant &&
|
|
1063
|
+
options.isDirectWrite &&
|
|
1064
|
+
options.relPath !== null &&
|
|
1065
|
+
killSwitchPlantResolvesToInventoriedAuthzStore(projectRoot, options.relPath)) {
|
|
1066
|
+
return deny(input, "authz-uat-deny", toolName, "Directive denied kill-switch plant: path resolves into the inventoried authz " +
|
|
1067
|
+
"store (`.deft/authz/` or `.deft/approved-scope/`). A settings grant does not " +
|
|
1068
|
+
"authorize rewriting approval state through a flag symlink (#6136).", options.scopePath);
|
|
1069
|
+
}
|
|
884
1070
|
// Evaluate each op; first deny wins (compound shell must not short-circuit).
|
|
885
1071
|
for (const op of ops) {
|
|
886
|
-
|
|
1072
|
+
let decision = evaluateAuthzMutation({
|
|
887
1073
|
state,
|
|
888
1074
|
grants,
|
|
889
1075
|
op,
|
|
@@ -892,6 +1078,48 @@ function authzForMutation(input, toolName, seams, options) {
|
|
|
892
1078
|
repo,
|
|
893
1079
|
worktree: projectRoot,
|
|
894
1080
|
});
|
|
1081
|
+
// Outside UAT, settings (and kill-switch Write classified as settings) would
|
|
1082
|
+
// authz-inactive allow. Re-evaluate under a synthetic human-origin UAT so the
|
|
1083
|
+
// existing grant gate applies without widening evaluate.ts (#6136).
|
|
1084
|
+
if (killSwitchPlant &&
|
|
1085
|
+
decision.allowed &&
|
|
1086
|
+
decision.code === "authz-inactive" &&
|
|
1087
|
+
(op === "settings" || op === "edit")) {
|
|
1088
|
+
decision = evaluateAuthzMutation({
|
|
1089
|
+
state: {
|
|
1090
|
+
...state,
|
|
1091
|
+
uat: {
|
|
1092
|
+
active: true,
|
|
1093
|
+
campaignId: "always-on-kill-switch-plant",
|
|
1094
|
+
startedAt: "1970-01-01T00:00:00.000Z",
|
|
1095
|
+
startedBy: {
|
|
1096
|
+
kind: "operator-cli",
|
|
1097
|
+
actor: "directive-always-on-kill-switch",
|
|
1098
|
+
mintedAt: "1970-01-01T00:00:00.000Z",
|
|
1099
|
+
mintedVia: "cli",
|
|
1100
|
+
eventRef: null,
|
|
1101
|
+
},
|
|
1102
|
+
suspendedAt: null,
|
|
1103
|
+
note: "synthetic lease for always-on kill-switch plant grant gate (#6136)",
|
|
1104
|
+
},
|
|
1105
|
+
},
|
|
1106
|
+
grants,
|
|
1107
|
+
op: "settings",
|
|
1108
|
+
path: options.relPath,
|
|
1109
|
+
branch,
|
|
1110
|
+
repo,
|
|
1111
|
+
worktree: projectRoot,
|
|
1112
|
+
});
|
|
1113
|
+
if (!decision.allowed) {
|
|
1114
|
+
decision = {
|
|
1115
|
+
...decision,
|
|
1116
|
+
reason: "Directive denied kill-switch / permanent opt-out plant without a human-origin " +
|
|
1117
|
+
"settings grant (#6136). Agents must not self-serve `.deft-directive-disable` or " +
|
|
1118
|
+
"`.no-deft-directive`. Human action required: plant outside an agent session, or " +
|
|
1119
|
+
"run `deft authz:grant` covering settings for this cohort.",
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
895
1123
|
recordAuthzAudit(projectRoot, decision, state, seams);
|
|
896
1124
|
if (!decision.allowed) {
|
|
897
1125
|
return deny(input, authzCodeToHook(decision.code), toolName, decision.reason, options.scopePath);
|
|
@@ -1083,6 +1311,8 @@ function inspectMutationGates(input, toolName, seams, options) {
|
|
|
1083
1311
|
scopePath: null,
|
|
1084
1312
|
runGit: dispatchGit,
|
|
1085
1313
|
projectRoot,
|
|
1314
|
+
deferGrantConsume: options.deferGrantConsume === true,
|
|
1315
|
+
pendingConsumeOut: options.pendingConsumeOut,
|
|
1086
1316
|
});
|
|
1087
1317
|
if (authzDeny !== null)
|
|
1088
1318
|
return authzDeny;
|
|
@@ -1194,6 +1424,8 @@ function inspectMutationGates(input, toolName, seams, options) {
|
|
|
1194
1424
|
scopePath: null,
|
|
1195
1425
|
runGit: dispatchGit,
|
|
1196
1426
|
projectRoot,
|
|
1427
|
+
deferGrantConsume: options.deferGrantConsume === true,
|
|
1428
|
+
pendingConsumeOut: options.pendingConsumeOut,
|
|
1197
1429
|
});
|
|
1198
1430
|
if (authzDeny !== null)
|
|
1199
1431
|
return authzDeny;
|
|
@@ -1453,10 +1685,11 @@ function inspectMutationGates(input, toolName, seams, options) {
|
|
|
1453
1685
|
"`worker_role`/`subagent_type` ∈ {ephemeral, docs, assist} (hosts that support them), " +
|
|
1454
1686
|
"or set session assist (`DEFT_SESSION_POSTURE=assist` or `DEFT_HOOK_ASSIST=1`), " +
|
|
1455
1687
|
"or run local-dev Shell (`docker compose` / `pnpm dev`) in the parent without a " +
|
|
1456
|
-
"lifecycle story. (4) Process-only critic — spawn with
|
|
1457
|
-
"plan or `process_only` (Grok PreToolUse stdin)
|
|
1458
|
-
"
|
|
1459
|
-
"
|
|
1688
|
+
"lifecycle story. (4) Process-only critic / review-monitor / validation seat — spawn with " +
|
|
1689
|
+
"structural `subagent_type` plan or `process_only` (Grok PreToolUse stdin) plus dest cwd " +
|
|
1690
|
+
"for watch/report seats. Dest-path is not that class. Free-text markers such as " +
|
|
1691
|
+
"`[worker_role: ephemeral]` or naming critic in the prompt are NOT sufficient. Do not " +
|
|
1692
|
+
"invent a fake scope only to satisfy this gate.";
|
|
1460
1693
|
}
|
|
1461
1694
|
else if (options.proposedLifecycleExempt &&
|
|
1462
1695
|
relTarget !== null &&
|
|
@@ -1539,7 +1772,7 @@ function inspectMutationGates(input, toolName, seams, options) {
|
|
|
1539
1772
|
};
|
|
1540
1773
|
if (!isSpawnTool(toolName)) {
|
|
1541
1774
|
// Wave 1 authz (UAT lease + human-origin grant) before runtimeAuthority (#2944 / #2948 L1–L2).
|
|
1542
|
-
const pendingGrantConsume = [];
|
|
1775
|
+
const pendingGrantConsume = options.pendingConsumeOut ?? [];
|
|
1543
1776
|
const authzDeny = authzForMutationTargets(input, toolName, seams, {
|
|
1544
1777
|
isDirectWrite: true,
|
|
1545
1778
|
scopePath: scope.path,
|
|
@@ -1556,7 +1789,12 @@ function inspectMutationGates(input, toolName, seams, options) {
|
|
|
1556
1789
|
const runtimeDeny = runtimeAuthorityForDirectWrite(input, toolName, seams, scope.path, effectiveRoot);
|
|
1557
1790
|
if (runtimeDeny !== null)
|
|
1558
1791
|
return runtimeDeny;
|
|
1559
|
-
|
|
1792
|
+
// Shell write-reissue may defer spend so decideShellOrMcpRuntimeAuthority can
|
|
1793
|
+
// reuse the same single-use grant (#6136 Greptile P1). When pendingConsumeOut
|
|
1794
|
+
// is the same bag, authz already recorded refs — do not push twice.
|
|
1795
|
+
if (options.deferGrantConsume !== true) {
|
|
1796
|
+
consumePendingSingleUseGrants(projectRoot, pendingGrantConsume);
|
|
1797
|
+
}
|
|
1560
1798
|
// Intentional product-write allow: Prefer-A durable marker (#5176 / #4544).
|
|
1561
1799
|
const occupancyDeny = recheckOccupancyBeforeWriteAllow(true);
|
|
1562
1800
|
if (occupancyDeny !== null)
|
|
@@ -1812,29 +2050,37 @@ function decideGitDestructive(input, toolName) {
|
|
|
1812
2050
|
/**
|
|
1813
2051
|
* Authorize recognized in-repo Shell file-write dests through inspectMutationGates (#3983 / #3987).
|
|
1814
2052
|
* Deny is returned; allow falls through so dest-forms and push/merge still run.
|
|
2053
|
+
* Kill-switch basenames are checked before the in-repo skip so out-of-tree plants
|
|
2054
|
+
* cannot fail-open (#6136 Prefer-A Bound limb 2).
|
|
1815
2055
|
*/
|
|
1816
|
-
function decideShellWriteReissue(input, toolName, seams, observation) {
|
|
2056
|
+
function decideShellWriteReissue(input, toolName, seams, observation, pendingConsumeOut) {
|
|
1817
2057
|
const command = hookShellCommand(input.payload);
|
|
1818
2058
|
if (command === null)
|
|
1819
2059
|
return null;
|
|
1820
2060
|
const projectRoot = resolve(input.projectRoot);
|
|
1821
2061
|
for (const dest of classifyShellWriteTargets(command)) {
|
|
2062
|
+
const killSwitchDest = isKillSwitchShellWriteBasename(dest.path);
|
|
1822
2063
|
if (dest.unprovable === true) {
|
|
1823
|
-
if (!isInRepoShellWritePath(projectRoot, dest.path))
|
|
2064
|
+
if (!killSwitchDest && !isInRepoShellWritePath(projectRoot, dest.path))
|
|
1824
2065
|
continue;
|
|
1825
2066
|
return deny(input, "scope-not-ready", toolName, "Directive denied " +
|
|
1826
2067
|
toolName +
|
|
1827
2068
|
": Shell write dest is not reconstructable (compound command). Use one simple command or Edit/Write.");
|
|
1828
2069
|
}
|
|
1829
|
-
|
|
2070
|
+
// #6136: protected basename before isInRepoShellWritePath skip.
|
|
2071
|
+
if (!killSwitchDest && !isInRepoShellWritePath(projectRoot, dest.path))
|
|
1830
2072
|
continue;
|
|
1831
2073
|
const destInput = {
|
|
1832
2074
|
...input,
|
|
1833
2075
|
payload: payloadWithInjectedWriteTarget(input.payload, dest.path),
|
|
1834
2076
|
};
|
|
2077
|
+
// Defer single-use spend into pendingConsumeOut; caller spends after the whole
|
|
2078
|
+
// shell call allows so ordinary edit grants are not reusable (#6136 Greptile).
|
|
1835
2079
|
const destDecision = inspectMutationGates(destInput, toolName, seams, {
|
|
1836
2080
|
proposedLifecycleExempt: true,
|
|
1837
2081
|
observation,
|
|
2082
|
+
deferGrantConsume: true,
|
|
2083
|
+
pendingConsumeOut,
|
|
1838
2084
|
});
|
|
1839
2085
|
if (destDecision.verdict === "deny")
|
|
1840
2086
|
return destDecision;
|
|
@@ -2287,12 +2533,15 @@ function tryPublishApplyingHostFromSessionStart(input, projectRoot) {
|
|
|
2287
2533
|
const transport = identity.provider === "grok" && environ.GROK_HOOK_EVENT?.trim()
|
|
2288
2534
|
? "grok-hook-event"
|
|
2289
2535
|
: "native";
|
|
2536
|
+
// SessionStart soft claim may take over a no-lease different-provider record
|
|
2537
|
+
// (#6143 P1/P4); RO CLI path must omit allowForeignTakeover.
|
|
2290
2538
|
// Native Cursor SessionStart must stay cursor even when GROK_SESSION_ID lingers.
|
|
2291
2539
|
if (input.host === "cursor" && transport === "native") {
|
|
2292
2540
|
publishApplyingHost(projectRoot, {
|
|
2293
2541
|
provider: "cursor",
|
|
2294
2542
|
rawSessionId: identity.rawSessionId,
|
|
2295
2543
|
transport: "native",
|
|
2544
|
+
allowForeignTakeover: true,
|
|
2296
2545
|
});
|
|
2297
2546
|
return;
|
|
2298
2547
|
}
|
|
@@ -2300,6 +2549,7 @@ function tryPublishApplyingHostFromSessionStart(input, projectRoot) {
|
|
|
2300
2549
|
provider: identity.provider,
|
|
2301
2550
|
rawSessionId: identity.rawSessionId,
|
|
2302
2551
|
transport,
|
|
2552
|
+
allowForeignTakeover: true,
|
|
2303
2553
|
});
|
|
2304
2554
|
}
|
|
2305
2555
|
catch {
|
|
@@ -2386,6 +2636,8 @@ function attachLifecycleIdentityRewrite(input, toolName, decision, seams) {
|
|
|
2386
2636
|
: "native";
|
|
2387
2637
|
// Prefer deposit identity when it matches the named canonical owner.
|
|
2388
2638
|
const identity = resolveHookHostIdentity(input.host, input.payload, environ);
|
|
2639
|
+
// #6143 P4: RO SessionStart must not displace a different-provider fresh
|
|
2640
|
+
// record (omit allowForeignTakeover; publish defers foreign-fresh-claim).
|
|
2389
2641
|
if (identity.status === "ok" &&
|
|
2390
2642
|
identity.sessionId === lifecycle.sessionId &&
|
|
2391
2643
|
// Leftover GROK_SESSION_ID alone must not publish Cursor as Claude/grok.
|
|
@@ -2447,7 +2699,17 @@ function attachLifecycleIdentityRewrite(input, toolName, decision, seams) {
|
|
|
2447
2699
|
return denyIdentity("occupancy-identity-conflict", applyingAdmission.message);
|
|
2448
2700
|
}
|
|
2449
2701
|
let liveOwnerBypass = false;
|
|
2450
|
-
if (applyingAdmission.kind === "
|
|
2702
|
+
if (applyingAdmission.kind === "live-owner-cleanup") {
|
|
2703
|
+
// Deposit equals live lease holder (#6101 Prefer-A): effectiveOwner is the
|
|
2704
|
+
// live deposit identity; bare stays on the rewrite path (not soft-pass).
|
|
2705
|
+
liveOwnerBypass = true;
|
|
2706
|
+
}
|
|
2707
|
+
else if (applyingAdmission.kind === "advisory-takeover") {
|
|
2708
|
+
// #6143 P1: no-lease fresh applying-host is advisory; caller keeps identity
|
|
2709
|
+
// and may republish after lifecycle succeeds.
|
|
2710
|
+
liveOwnerBypass = true;
|
|
2711
|
+
}
|
|
2712
|
+
else if (applyingAdmission.kind === "foreign-owner") {
|
|
2451
2713
|
const live = liveOccupant(resolve(input.projectRoot));
|
|
2452
2714
|
if (live !== null && live.sessionId === identity.sessionId) {
|
|
2453
2715
|
// Applying-host was replaced by another SessionStart; keep live lease owner
|
|
@@ -2568,6 +2830,14 @@ function prepareProcessOnlyDestPath(destPath, projectRoot, seams, payload) {
|
|
|
2568
2830
|
destPath,
|
|
2569
2831
|
againstImplementationSha: against,
|
|
2570
2832
|
});
|
|
2833
|
+
// Strict false only: legacy success mocks may omit `ok` and still carry `record` (#6100).
|
|
2834
|
+
if (prepared.ok === false) {
|
|
2835
|
+
return {
|
|
2836
|
+
ok: false,
|
|
2837
|
+
message: `Directive denied process-only critic spawn: dest prepare failed: ${prepared.code}: ${prepared.message}. ` +
|
|
2838
|
+
"Parent must fetch origin and create or verify the dest at origin/<default> before spawn.",
|
|
2839
|
+
};
|
|
2840
|
+
}
|
|
2571
2841
|
return { ok: true, record: prepared.record };
|
|
2572
2842
|
}
|
|
2573
2843
|
catch (cause) {
|
|
@@ -3008,11 +3278,15 @@ function routeHookDecision(input, seams, observation) {
|
|
|
3008
3278
|
if (prospective !== null) {
|
|
3009
3279
|
return remapProxyShellUpdatedInput(input.payload, toolName, shellProxyUnwrap, attachLifecycleIdentityRewrite(shellInput, shellToolName, prospective, seams));
|
|
3010
3280
|
}
|
|
3011
|
-
const
|
|
3281
|
+
const pendingShellGrantConsume = [];
|
|
3282
|
+
const writeReissue = decideShellWriteReissue(shellInput, shellToolName, seams, observation, pendingShellGrantConsume);
|
|
3012
3283
|
if (writeReissue !== null) {
|
|
3013
3284
|
return remapProxyShellUpdatedInput(input.payload, toolName, shellProxyUnwrap, attachLifecycleIdentityRewrite(shellInput, shellToolName, writeReissue, seams));
|
|
3014
3285
|
}
|
|
3015
3286
|
const decision = decideShellDestFormsThenRuntimeAuthority(shellInput, shellToolName, seams, observation);
|
|
3287
|
+
if (decision.verdict === "allow") {
|
|
3288
|
+
consumePendingSingleUseGrants(resolve(shellInput.projectRoot), pendingShellGrantConsume);
|
|
3289
|
+
}
|
|
3016
3290
|
return remapProxyShellUpdatedInput(input.payload, toolName, shellProxyUnwrap, attachLifecycleIdentityRewrite(shellInput, shellToolName, decision, seams));
|
|
3017
3291
|
}
|
|
3018
3292
|
// Host kill deny-class / attestation gate (#5281 Prefer-A Bound).
|