@sema-agent/core 7.50.1 → 7.51.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/CHANGELOG.md +275 -0
- package/dist/agents/child-failure.d.ts +5 -16
- package/dist/agents/child-failure.js +4 -24
- package/dist/agents/subagent-steps.js +2 -2
- package/dist/agents/subagent.d.ts +4 -13
- package/dist/agents/subagent.js +94 -204
- package/dist/agents/tool-filter.d.ts +2 -2
- package/dist/brain/anthropic.d.ts +1 -1
- package/dist/brain/anthropic.js +7 -5
- package/dist/brain/open-responses.d.ts +1 -1
- package/dist/brain/open-responses.js +3 -2
- package/dist/brain/openai.d.ts +1 -1
- package/dist/brain/openai.js +3 -2
- package/dist/brain/request-route.d.ts +2 -2
- package/dist/brain/route-adjudicator.d.ts +16 -7
- package/dist/brain/route-adjudicator.js +23 -7
- package/dist/brain/route-conformance.js +23 -5
- package/dist/brain/stream-engine.js +9 -3
- package/dist/core/a2a.js +6 -8
- package/dist/core/allow-entry.d.ts +45 -26
- package/dist/core/allow-entry.js +48 -24
- package/dist/core/arg-summary.d.ts +8 -85
- package/dist/core/arg-summary.js +4 -386
- package/dist/core/ask-origin.d.ts +35 -33
- package/dist/core/ask-origin.js +9 -11
- package/dist/core/checkpoint-requirements.d.ts +6 -0
- package/dist/core/checkpoint-requirements.js +1 -0
- package/dist/core/checkpoint-store.d.ts +15 -34
- package/dist/core/checkpoint-store.js +5 -4
- package/dist/core/classifier-unavailable-arm.d.ts +12 -8
- package/dist/core/classifier-unavailable-arm.js +7 -2
- package/dist/core/credential-vocabulary.d.ts +3 -2
- package/dist/core/credential-vocabulary.js +27 -18
- package/dist/core/delegation-frames.d.ts +40 -15
- package/dist/core/delegation-frames.js +34 -0
- package/dist/core/engine-notice.d.ts +35 -11
- package/dist/core/gate-fold.js +9 -7
- package/dist/core/gate-lanes.js +6 -4
- package/dist/core/gate-outcome.d.ts +87 -11
- package/dist/core/gate-outcome.js +171 -61
- package/dist/core/governance-codes.d.ts +7 -1
- package/dist/core/governance-codes.js +9 -0
- package/dist/core/hooks.d.ts +4 -4
- package/dist/core/hooks.js +4 -3
- package/dist/core/mcp-connection-pool.d.ts +2 -0
- package/dist/core/mcp-connection-pool.js +2 -1
- package/dist/core/mcp-failure.js +2 -1
- package/dist/core/mcp-server-spec.d.ts +27 -5
- package/dist/core/mcp.d.ts +13 -38
- package/dist/core/mcp.js +28 -23
- package/dist/core/media-byte-cap.d.ts +25 -0
- package/dist/core/media-byte-cap.js +18 -2
- package/dist/core/memory-engine/consolidation-driver.js +1 -1
- package/dist/core/mode-policy.d.ts +25 -1
- package/dist/core/mode-policy.js +28 -13
- package/dist/core/own-property-receipt.d.ts +18 -0
- package/dist/core/own-property-receipt.js +39 -0
- package/dist/core/permission-rule-model.d.ts +32 -11
- package/dist/core/permission-rule-model.js +12 -7
- package/dist/core/persisted-rule-arms.d.ts +3 -3
- package/dist/core/prompt-section-seat.d.ts +54 -0
- package/dist/core/prompt-section-seat.js +49 -0
- package/dist/core/protocol-http-auth.d.ts +44 -0
- package/dist/core/protocol-http-auth.js +45 -0
- package/dist/core/read-face-seats.d.ts +30 -0
- package/dist/core/read-face-seats.js +38 -0
- package/dist/core/redaction-passes.d.ts +82 -0
- package/dist/core/redaction-passes.js +378 -0
- package/dist/core/remote-env.d.ts +4 -3
- package/dist/core/resume-startup-cause.d.ts +56 -0
- package/dist/core/resume-startup-cause.js +43 -0
- package/dist/core/rule-denial-sentence.d.ts +2 -2
- package/dist/core/runner/announce-once-ledger.js +2 -2
- package/dist/core/runner/classifier-ladder.d.ts +17 -13
- package/dist/core/runner/classifier-ladder.js +12 -10
- package/dist/core/runner/construction-doors.js +9 -20
- package/dist/core/runner/contracts.d.ts +4 -4
- package/dist/core/runner/gate-exit.js +1 -1
- package/dist/core/runner/memory-consolidation-write-judge.d.ts +53 -9
- package/dist/core/runner/memory-consolidation-write-judge.js +39 -1
- package/dist/core/runner/permission-rule-lanes.d.ts +8 -13
- package/dist/core/runner/person-path-rows.d.ts +4 -3
- package/dist/core/runner/policy-throw.js +4 -4
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -3
- package/dist/core/runner/prepare-caps-and-workflow.js +8 -6
- package/dist/core/runner/prepare-gate-stations.js +3 -3
- package/dist/core/runner/prepare-hands-readface.js +1 -19
- package/dist/core/runner/prepare-inherited-gate.js +10 -9
- package/dist/core/runner/prepare-policy-chain.d.ts +3 -5
- package/dist/core/runner/prepare-policy-chain.js +10 -13
- package/dist/core/runner/prepare-project-context.d.ts +4 -4
- package/dist/core/runner/prepare-project-context.js +2 -1
- package/dist/core/runner/prepare-prompt-assembly.js +1 -0
- package/dist/core/runner/prepare-prompt-inputs.d.ts +1 -1
- package/dist/core/runner/prepare-prompt-inputs.js +4 -4
- package/dist/core/runner/prepare-protocol-tools.d.ts +4 -3
- package/dist/core/runner/prepare-protocol-tools.js +3 -2
- package/dist/core/runner/prepare-task.js +6 -4
- package/dist/core/runner/prepare-turn-wiring.d.ts +16 -13
- package/dist/core/runner/prepare-turn-wiring.js +8 -7
- package/dist/core/runner/run-harness-handlers.js +2 -2
- package/dist/core/runner/run-leg.js +10 -9
- package/dist/core/runner/run-settle-and-teardown.js +5 -5
- package/dist/core/runner/run-turn-boundary.js +3 -2
- package/dist/core/runner/runtask.d.ts +1 -2
- package/dist/core/runner/runtask.js +8 -12
- package/dist/core/runner/session-rule-policy.d.ts +15 -11
- package/dist/core/runner/session-rule-policy.js +43 -33
- package/dist/core/runner/stream-lifecycle-verbs.js +2 -2
- package/dist/core/runner/stream-settle-backstop.js +2 -1
- package/dist/core/runner/sub-agent-deny-lists.d.ts +12 -8
- package/dist/core/runner/sub-agent-deny-lists.js +23 -12
- package/dist/core/runner/terminal-account.js +3 -3
- package/dist/core/runner/tool-output-projection.js +3 -8
- package/dist/core/runner/tool-result-media-seat.d.ts +19 -0
- package/dist/core/runner/tool-result-media-seat.js +13 -0
- package/dist/core/runner/turn-attachments.d.ts +13 -12
- package/dist/core/runner/turn-attachments.js +11 -7
- package/dist/core/runner-deps.d.ts +4 -3
- package/dist/core/safety-merge-corpus.js +21 -21
- package/dist/core/secret-env.js +1 -1
- package/dist/core/session-policy-store.d.ts +89 -72
- package/dist/core/session-policy-store.js +100 -93
- package/dist/core/shell-read-silence.d.ts +38 -4
- package/dist/core/shell-read-silence.js +102 -0
- package/dist/core/side-query.d.ts +7 -8
- package/dist/core/skill-grant-binding.d.ts +32 -11
- package/dist/core/skill-grant-binding.js +11 -3
- package/dist/core/skill-grant.d.ts +4 -3
- package/dist/core/skill-grant.js +5 -4
- package/dist/core/skills-directory.d.ts +12 -1
- package/dist/core/skills-directory.js +17 -8
- package/dist/core/store-contracts/checkpoint-store-contract.d.ts +2 -0
- package/dist/core/store-contracts/checkpoint-store-contract.js +3 -0
- package/dist/core/swappable-deps.d.ts +15 -1
- package/dist/core/swappable-deps.js +25 -1
- package/dist/core/synthetic-read-verdict.d.ts +16 -14
- package/dist/core/synthetic-read-verdict.js +28 -8
- package/dist/core/task-notification.d.ts +13 -3
- package/dist/core/task-notification.js +12 -1
- package/dist/core/task-spec.d.ts +14 -15
- package/dist/core/tool-name-readings.d.ts +0 -4
- package/dist/core/tool-name-readings.js +0 -1
- package/dist/core/tool-policy.d.ts +40 -9
- package/dist/core/tool-policy.js +25 -7
- package/dist/core/types.d.ts +3 -3
- package/dist/core/types.js +1 -1
- package/dist/core/untrusted-egress.d.ts +60 -11
- package/dist/core/untrusted-egress.js +120 -9
- package/dist/core/untrusted-text.js +16 -0
- package/dist/core/wiring-manifest.d.ts +22 -8
- package/dist/core/wiring-manifest.js +12 -4
- package/dist/engine/harness/agent-harness.d.ts +2 -1
- package/dist/engine/harness/agent-harness.js +4 -1
- package/dist/engine/harness/types.d.ts +3 -0
- package/dist/engine/llm/types.d.ts +7 -9
- package/dist/engine/loop/agent-loop.d.ts +8 -3
- package/dist/engine/loop/agent-loop.js +26 -9
- package/dist/engine/loop/types.d.ts +10 -0
- package/dist/index.d.ts +17 -5
- package/dist/index.js +14 -5
- package/dist/orchestration/run-workflow-tool.js +8 -8
- package/dist/orchestration/workflow.js +2 -2
- package/dist/prompt-assembly/assemble.d.ts +3 -1
- package/dist/prompt-assembly/assemble.js +6 -0
- package/dist/prompts/cowork.d.ts +42 -0
- package/dist/prompts/cowork.js +529 -0
- package/dist/prompts/default.d.ts +14 -1
- package/dist/prompts/default.js +3 -0
- package/dist/stores/file/session-policy-store.d.ts +6 -3
- package/dist/stores/file/session-policy-store.js +5 -16
- package/dist/tools/artifact/artifact-tool.js +2 -0
- package/dist/tools/fs/image-admission.d.ts +57 -4
- package/dist/tools/fs/image-admission.js +85 -0
- package/dist/tools/fs/path-containment.d.ts +2 -0
- package/dist/tools/fs/path-containment.js +5 -0
- package/dist/tools/fs/shell-read-check.d.ts +31 -6
- package/dist/tools/fs/shell-read-check.js +2 -4
- package/dist/tools/fs/shell-read-environment.d.ts +10 -25
- package/dist/tools/fs/shell-read-environment.js +6 -18
- package/dist/tools/fs/shell-read-establish.d.ts +3 -2
- package/dist/tools/fs/shell-read-establish.js +5 -5
- package/dist/tools/fs/shell-read-judge.d.ts +38 -8
- package/dist/tools/fs/shell-read-judge.js +12 -10
- package/dist/tools/web.js +2 -2
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +94 -10
- package/wire-changes/core@7.50.2.json +42 -0
- package/wire-changes/core@7.51.0.json +2421 -0
|
@@ -1,29 +1,18 @@
|
|
|
1
1
|
import { checkedAgentConfigDir } from "../agent-config-dir.js";
|
|
2
2
|
import { checkedMediaByteCap } from "../media-byte-cap.js";
|
|
3
|
+
import { receiveOwnProperties, refuseProxy } from "../own-property-receipt.js";
|
|
3
4
|
import { assertNoRetiredRunnerDeps } from "./retired-runner-deps.js";
|
|
5
|
+
import { copyReadDenySeat, READ_DENY_DEPLOYMENT_SEATS } from "../read-face-seats.js";
|
|
4
6
|
export function retainRunnerDeps(deps) {
|
|
7
|
+
const words = { subject: "RunnerDeps", unit: "seat", moment: "at new Runner" };
|
|
8
|
+
refuseProxy(deps, words);
|
|
5
9
|
assertNoRetiredRunnerDeps(deps);
|
|
6
|
-
const
|
|
7
|
-
const e = new Error(message);
|
|
8
|
-
e.code = "config.invalid_argument";
|
|
9
|
-
return e;
|
|
10
|
-
};
|
|
11
|
-
const proto = Object.getPrototypeOf(deps);
|
|
12
|
-
if (proto !== Object.prototype && proto !== null) {
|
|
13
|
-
throw refusal("RunnerDeps must be a plain object (its prototype is neither Object.prototype nor null): every seat is read once as an own property, and a seat its prototype would supply is not read — refused rather than wired without it");
|
|
14
|
-
}
|
|
15
|
-
const retained = Object.create(Object.prototype);
|
|
16
|
-
for (const name of Object.getOwnPropertyNames(deps)) {
|
|
17
|
-
let value;
|
|
18
|
-
try {
|
|
19
|
-
value = Reflect.get(deps, name);
|
|
20
|
-
}
|
|
21
|
-
catch {
|
|
22
|
-
throw refusal(`RunnerDeps.${name} threw while it was read at new Runner — a seat is read once, here; refused rather than wired without it`);
|
|
23
|
-
}
|
|
24
|
-
Object.defineProperty(retained, name, { value, enumerable: true, writable: true, configurable: true });
|
|
25
|
-
}
|
|
10
|
+
const retained = receiveOwnProperties(deps, words);
|
|
26
11
|
checkedAgentConfigDir(retained.agentConfigDir, "RunnerDeps.agentConfigDir");
|
|
27
12
|
checkedMediaByteCap(retained.mediaByteCapBytes, "RunnerDeps.mediaByteCapBytes");
|
|
13
|
+
for (const seat of READ_DENY_DEPLOYMENT_SEATS) {
|
|
14
|
+
if (Object.hasOwn(retained, seat))
|
|
15
|
+
Object.defineProperty(retained, seat, { value: copyReadDenySeat(Reflect.get(retained, seat)), enumerable: true, writable: true, configurable: true });
|
|
16
|
+
}
|
|
28
17
|
return retained;
|
|
29
18
|
}
|
|
@@ -53,7 +53,7 @@ import type { OnAsk, PermissionResult, ResolvedAsk, ToolCallRequest, ToolPolicy
|
|
|
53
53
|
import type { RemoteExecutionEnv, SnapshotId, WorkspaceHandle } from "../remote-env.js";
|
|
54
54
|
import type { ToolDisclosureManifest } from "../trace.js";
|
|
55
55
|
import type { AgentDefinition, Brain, CompactOutcome, ModelRef, ModelRoles, NestedUsageAccum, PermissionMode, RunnerDeps, ShellGateDoctrine, TaskEvent, TaskEventIdentity, TaskResult, TaskSpec, TaskStream, ToolActivity, ToolEffect } from "../types.js";
|
|
56
|
-
import type { PermissionModeController } from "../mode-policy.js";
|
|
56
|
+
import type { InheritedAutoModeFace, PermissionModeController } from "../mode-policy.js";
|
|
57
57
|
import type { WiringManifest } from "../wiring-manifest.js";
|
|
58
58
|
import type { SkillGateSeats, SkillGrantLane, SkillGrantRecord, SkillGrantSource } from "../skill-grant.js";
|
|
59
59
|
import type { BudgetAxis } from "./assemble-result.js";
|
|
@@ -450,8 +450,8 @@ export interface Prepared {
|
|
|
450
450
|
};
|
|
451
451
|
/** The deployment's caller policy, re-checked on a durable resume when the bytes to execute are not the bytes the gate saw. */
|
|
452
452
|
basePolicyForResumeEdit?: ToolPolicy;
|
|
453
|
-
/** The
|
|
454
|
-
|
|
453
|
+
/** The leg's consolidation write judge (`createConsolidationWriteJudge`, the settle tail's background consolidation asks it). */
|
|
454
|
+
consolidationWriteJudge: import("../memory-engine/consolidation-driver.js").ConsolidationWriteJudge;
|
|
455
455
|
approvedCallScreen?: (call: {
|
|
456
456
|
toolCallId: string;
|
|
457
457
|
toolName: string;
|
|
@@ -1390,7 +1390,7 @@ export interface PrepareResume {
|
|
|
1390
1390
|
* hook, deduped by full installation so a deps-level hook is consulted once per call at any depth).
|
|
1391
1391
|
* Depth-N delegation is therefore a linear chain, each layer evaluated at most once per tool call.
|
|
1392
1392
|
*/
|
|
1393
|
-
export interface InheritedGate {
|
|
1393
|
+
export interface InheritedGate extends InheritedAutoModeFace {
|
|
1394
1394
|
/** Serializable ancestor session-rule snapshots (data half), ancestors first. */
|
|
1395
1395
|
ancestorRules?: ReadonlyArray<{
|
|
1396
1396
|
sessionId: string;
|
|
@@ -23,7 +23,7 @@ export function mintGateOutcome(facts) {
|
|
|
23
23
|
: { kind: "allowed", ...(attribution !== undefined ? { classifier: attribution } : {}), ...(facts.released !== undefined ? { released: Object.freeze({ ...facts.released, classes: Object.freeze([...facts.released.classes]) }) } : {}) }),
|
|
24
24
|
...(facts.settled !== undefined ? { settlement: settlement, origin: facts.settled.origin } : {}),
|
|
25
25
|
});
|
|
26
|
-
const defects = screenGateOutcome(outcome);
|
|
26
|
+
const defects = screenGateOutcome(outcome, { reading: "producer" });
|
|
27
27
|
if (defects.length > 0)
|
|
28
28
|
throw new Error(`the tool gate composed an outcome that violates its own record: ${defects.join("; ")}`);
|
|
29
29
|
return outcome;
|
|
@@ -1,17 +1,61 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* The consolidation driver's write judge — the seat `runMemoryConsolidationDriver` asks (for the library directory before it
|
|
3
|
+
* claims anything, then for each file a commit lands) — minted by ONE constructor, {@link createConsolidationWriteJudge}, for
|
|
4
|
+
* every caller: the Runner's auto lane (a leg, with every layer a model's own `Write` meets on it) and a host's own
|
|
5
|
+
* consolidation valve (no leg: its rule store, the person, the local-owner declaration, its caller policy). The judgment is
|
|
6
|
+
* `createSyntheticWriteJudge`'s over the person's and the org's rows read through the gate's own lanes; nothing here judges.
|
|
7
|
+
* Beside it, the refusal's notice dialect ({@link deliverWriteRefusal}).
|
|
6
8
|
*/
|
|
7
|
-
import type
|
|
9
|
+
import { type SyntheticReadLayers, type SyntheticWriteFacts } from "../synthetic-read-verdict.js";
|
|
8
10
|
import { type ConsolidationWriteJudge } from "../memory-engine/consolidation-driver.js";
|
|
9
11
|
import { type EngineNotice } from "../engine-notice.js";
|
|
12
|
+
import type { PermissionRuleStoreProvider } from "../permission-rule-provider.js";
|
|
13
|
+
import { type ToolPolicy } from "../tool-policy.js";
|
|
14
|
+
import type { ExecutionEnv } from "../../internal/harness-types.js";
|
|
15
|
+
import { createPermissionRuleLanes } from "./permission-rule-lanes.js";
|
|
16
|
+
/** What every caller states: the layers a host has. */
|
|
17
|
+
export interface ConsolidationWriteJudgeInput {
|
|
18
|
+
/** The deployment's permission-rule store (`RunnerDeps.permissionRuleStore`): the person's standing rows and the org's. */
|
|
19
|
+
ruleStoreProvider?: PermissionRuleStoreProvider;
|
|
20
|
+
/** Whose rows are read: the principal the library belongs to. Absent or empty ⇒ the anonymous floor (no personal row),
|
|
21
|
+
* or the local owner's bucket where `localOwnerDeclared`. */
|
|
22
|
+
principal?: string;
|
|
23
|
+
/** `RunnerDeps.localOwnerRules`: a declaration a store cannot honor is refused at construction, loudly. */
|
|
24
|
+
localOwnerDeclared?: boolean;
|
|
25
|
+
/** The deployment's caller policy (`RunnerDeps.toolPolicy`), asked with a live signal and a request that states nobody can
|
|
26
|
+
* be asked about it (`ToolCallRequest.approvalReach: "none"`) — never an approver. */
|
|
27
|
+
callerPolicy?: ToolPolicy;
|
|
28
|
+
/** The session the person's session-scoped rows are read under. Absent ⇒ the judgment is no session's: no session row applies. */
|
|
29
|
+
sessionId?: string;
|
|
30
|
+
/** Where the person's relative and `~/` rows anchor: the project root (also which project rows apply) and the home. Absent ⇒
|
|
31
|
+
* such a row cannot be anchored, and a deny or ask it holds is an OBJECTION (fail closed) — the judge never guesses where a
|
|
32
|
+
* row would have pointed. */
|
|
33
|
+
anchors?: {
|
|
34
|
+
root?: string;
|
|
35
|
+
home?: string;
|
|
36
|
+
};
|
|
37
|
+
/** The environment the library's paths and the rows' heads resolve in — the one a leg of this deployment judges in (links
|
|
38
|
+
* followed both ways: a row spelled through a link binds the target's real location, a target spelled through one is judged
|
|
39
|
+
* where it leads). Absent ⇒ the engine process's own filesystem, where an in-process file backend writes the library. */
|
|
40
|
+
executionEnv?: ExecutionEnv;
|
|
41
|
+
}
|
|
42
|
+
/** What a leg adds — the Runner's prepare passes it; a host has none of it. */
|
|
43
|
+
export interface ConsolidationWriteJudgeLeg {
|
|
44
|
+
/** The leg's reader of the person's rows, one the run's cut does not end (the judge is asked after the run). */
|
|
45
|
+
rows: Parameters<typeof createPermissionRuleLanes>[0]["rows"];
|
|
46
|
+
/** The leg's facts the lanes judge against: its session, root and anchors, its resolution of rule heads, its sinks. */
|
|
47
|
+
lanes: Omit<Parameters<typeof createPermissionRuleLanes>[0], "provider" | "localOwnerDeclared" | "principal" | "rows">;
|
|
48
|
+
/** The layers only a leg has: its skill rows, its narrowing fold, the live inherited policies, its target stamp. */
|
|
49
|
+
layers: Omit<SyntheticReadLayers, "callerPolicy" | "persistedRuleLane" | "orgRuleLane" | "signal">;
|
|
50
|
+
/** The facts a live write carries on the leg, read at each judgment. */
|
|
51
|
+
facts: () => SyntheticWriteFacts;
|
|
52
|
+
}
|
|
10
53
|
/**
|
|
11
|
-
* The
|
|
12
|
-
*
|
|
13
|
-
*
|
|
54
|
+
* The consolidation write judge: each target the run asks about is put, as one `Write` of that path under a deadline of its
|
|
55
|
+
* own, to the synthetic Write judge over the caller policy, the person's and the org's rows (the gate's own lanes over a
|
|
56
|
+
* reader of the store) and whatever layers `leg` adds. The answer is the judge's, unchanged. A host passes `input` alone; the
|
|
57
|
+
* engine's leg passes the same `input` and its `leg`, so the same rows give the same answer on both.
|
|
14
58
|
*/
|
|
15
|
-
export declare function
|
|
59
|
+
export declare function createConsolidationWriteJudge(input: ConsolidationWriteJudgeInput, leg?: ConsolidationWriteJudgeLeg): ConsolidationWriteJudge;
|
|
16
60
|
/** Deliver a write-judge refusal as the verb's refusal notice; false (nothing delivered) for any other error. */
|
|
17
61
|
export declare function deliverWriteRefusal(err: unknown, scope: string, onNotice: ((notice: EngineNotice) => void) | undefined): boolean;
|
|
@@ -1,11 +1,49 @@
|
|
|
1
1
|
import { ORG_ADJUDICATION_TIMEOUT_MS } from "../permission-rule-org.js";
|
|
2
|
+
import { createSyntheticWriteJudge } from "../synthetic-read-verdict.js";
|
|
2
3
|
import { CONSOLIDATION_WRITE_REFUSED_CODE } from "../memory-engine/consolidation-driver.js";
|
|
3
4
|
import { ConsolidationRefusedError } from "../memory-engine/consolidation.js";
|
|
4
5
|
import { memoryConsolidationRefusedNotice } from "../memory-engine/engine.js";
|
|
5
6
|
import { deliverEngineNotice } from "../engine-notice.js";
|
|
6
|
-
|
|
7
|
+
import { toolPolicyPathRules } from "../tool-policy.js";
|
|
8
|
+
import { RosterBuilder, toolCallFaceOf } from "../tool-roster.js";
|
|
9
|
+
import { createHeadLeads } from "../path-rule-binding.js";
|
|
10
|
+
import { legCallTargetStamp } from "../effective-path-target.js";
|
|
11
|
+
import { createWriteFileTool } from "../../tools/fs/fs-write.js";
|
|
12
|
+
import { whereItsAnsweredPrefixLeads } from "../../tools/fs/read-deny-home.js";
|
|
13
|
+
import { NodeExecutionEnv } from "../../engine/execution-env/node-execution-env.js";
|
|
14
|
+
import { ASK_USER_QUESTION_TOOL_NAME } from "../ask-question.js";
|
|
15
|
+
import { createPermissionRuleLanes } from "./permission-rule-lanes.js";
|
|
16
|
+
import { createPersonPathRows } from "./person-path-rows.js";
|
|
17
|
+
const noLine = () => undefined;
|
|
18
|
+
let engineWrite;
|
|
19
|
+
function engineWriteFace() {
|
|
20
|
+
if (engineWrite === undefined) {
|
|
21
|
+
const roster = new RosterBuilder(new Map());
|
|
22
|
+
roster.mount(createWriteFileTool(new NodeExecutionEnv({ cwd: "/" }), new Map(), "/"), { source: "builtin", mountedBy: "hands" });
|
|
23
|
+
engineWrite = toolCallFaceOf(roster.snapshot({ effects: new Map(), egress: new Set(), irreversibilityTier: new Map(), reversibilityProbes: new Map(), deferred: new Set(), trustedTools: new Set() }), "Write");
|
|
24
|
+
}
|
|
25
|
+
return engineWrite;
|
|
26
|
+
}
|
|
27
|
+
export function createConsolidationWriteJudge(input, leg) {
|
|
28
|
+
const owner = { provider: input.ruleStoreProvider, localOwnerDeclared: input.localOwnerDeclared === true, principal: input.principal };
|
|
29
|
+
const { rows, lanes, layers, facts } = leg ?? hostLeg(input, owner);
|
|
30
|
+
const { personal, org } = createPermissionRuleLanes({ ...owner, ...lanes, rows });
|
|
31
|
+
const judge = createSyntheticWriteJudge({ ...layers, ...(input.callerPolicy !== undefined ? { callerPolicy: input.callerPolicy } : {}), ...(personal !== undefined ? { persistedRuleLane: personal } : {}), ...(org !== undefined ? { orgRuleLane: org } : {}) }, facts);
|
|
7
32
|
return (target) => judge({ file_path: target.path }, "memory-consolidation", { deadlineAt: Date.now() + ORG_ADJUDICATION_TIMEOUT_MS });
|
|
8
33
|
}
|
|
34
|
+
function hostLeg(input, owner) {
|
|
35
|
+
const { root, home } = input.anchors ?? {};
|
|
36
|
+
const env = input.executionEnv ?? new NodeExecutionEnv({ cwd: root ?? "/" });
|
|
37
|
+
const leads = createHeadLeads((part) => whereItsAnsweredPrefixLeads(env, part));
|
|
38
|
+
const chainTop = { ...(root !== undefined ? { root } : {}), ...(home !== undefined ? { home } : {}) };
|
|
39
|
+
const sessionId = input.sessionId;
|
|
40
|
+
return {
|
|
41
|
+
rows: createPersonPathRows({ ...owner, sessionId, root, rootCanonical: undefined, leads, chainTop, onDisclosure: noLine, onUnread: noLine, onRowsDropped: noLine }),
|
|
42
|
+
lanes: { sessionId, root, rootCanonical: undefined, chainTop, leads, liveCwd: () => root, home, questionToolMounted: false, questionToolName: ASK_USER_QUESTION_TOOL_NAME, onRevisionDefect: noLine, onDisclosure: noLine },
|
|
43
|
+
layers: { stampCallTarget: legCallTargetStamp({ env, root: root ?? "/", cwd: () => root, judgesPaths: () => true, leads: () => leads.resolve(toolPolicyPathRules([input.callerPolicy], chainTop)) }) },
|
|
44
|
+
facts: () => ({ face: engineWriteFace(), ...(root !== undefined ? { root, cwd: root } : {}) }),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
9
47
|
export function deliverWriteRefusal(err, scope, onNotice) {
|
|
10
48
|
if (!(err instanceof ConsolidationRefusedError) || err.code !== CONSOLIDATION_WRITE_REFUSED_CODE)
|
|
11
49
|
return false;
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* silence the ungated-write warning for deployments that wired no policy at all.
|
|
25
25
|
*/
|
|
26
26
|
import type { AskRuleEvidence, ToolCallRequest } from "../tool-policy.js";
|
|
27
|
-
import { persistedRuleMandateOf, type RuleClearanceFacts } from "../ask-origin.js";
|
|
27
|
+
import { persistedRuleMandateOf, type RuleClearanceFacts, type RuleOffersAbsence } from "../ask-origin.js";
|
|
28
28
|
import { type OrgGateVerdict, type PersistedRuleAnswer, type PersistedRuleHit, type PersistedRuleUnreadable } from "../hooks.js";
|
|
29
29
|
import type { PersistedRule, PersistedRuleVerdict, RuleOffer, ScopeRootIdentity, SegmentCoverage } from "../permission-rule-model.js";
|
|
30
30
|
import { type PathRuleBases } from "../permission-rule-model.js";
|
|
@@ -146,10 +146,12 @@ export declare function createPermissionRuleLanes(cfg: {
|
|
|
146
146
|
provider: PermissionRuleStoreProvider | undefined;
|
|
147
147
|
localOwnerDeclared: boolean;
|
|
148
148
|
principal: string | undefined;
|
|
149
|
-
|
|
149
|
+
/** The session whose session-scoped rows apply; `undefined` (a judgment no session makes) ⇒ none does. */
|
|
150
|
+
sessionId: string | undefined;
|
|
150
151
|
/** The isolation-aware task root — the same value the file fence, the prompt cwd and the session rules
|
|
151
|
-
* use, so a project-scoped rule agrees with every other place that says "this project" (which project rows apply).
|
|
152
|
-
|
|
152
|
+
* use, so a project-scoped rule agrees with every other place that says "this project" (which project rows apply).
|
|
153
|
+
* `undefined` (a judgment outside any task) ⇒ no project row applies and a row anchored at the root cannot be anchored. */
|
|
154
|
+
root: string | undefined;
|
|
153
155
|
/** The same root's canonical spelling (`undefined`: none could be read): a project row applies when its scope root covers
|
|
154
156
|
* either spelling of it — the row's root resolved where it leads ({@link projectScopeIdentity}). */
|
|
155
157
|
rootCanonical: string | undefined;
|
|
@@ -180,12 +182,6 @@ export declare function createPermissionRuleLanes(cfg: {
|
|
|
180
182
|
/** The allow layer's auto strip over a stored ALLOW row (true ⇒ out of this call's table BEFORE the coverage is chosen). */
|
|
181
183
|
stripsAllow?: (rule: PersistedRule, req: ToolCallRequest) => boolean;
|
|
182
184
|
}): PermissionRuleLanes;
|
|
183
|
-
/** The closed reason set for the rule-offer factory's empty answer — the same three
|
|
184
|
-
* spellings the `AskRequest` and durable-row seats declare, kept at the one factory that fills both.
|
|
185
|
-
* Deliberately not exported: this is a wire vocabulary, and its two faces declare it literally (the
|
|
186
|
-
* `previewWithheld` precedent) so a consumer reads the closed set on the type it is holding rather
|
|
187
|
-
* than through an import. */
|
|
188
|
-
type RuleOffersAbsence = "mandated" | "lane_cannot_speak" | "shadowed";
|
|
189
185
|
/** The surviving-ask facts the rule-offer factory reads (see {@link createRuleOffersOf}): the
|
|
190
186
|
* synchronous mint sites spread the surviving decision, which carries them; the park leg threads
|
|
191
187
|
* each as its own parameter. The clearance half is {@link RuleClearanceFacts} — the SAME declaration
|
|
@@ -242,9 +238,8 @@ interface RuleOffersAskFacts extends RuleClearanceFacts {
|
|
|
242
238
|
* cannot disagree). The doctrine it serves is the loud-bad-value one, applied to an absence: a
|
|
243
239
|
* surface reading an empty card could not tell "there is nothing this lane could offer" from
|
|
244
240
|
* "offers were deliberately suppressed", and a person reading it could not tell "write the rule
|
|
245
|
-
* yourself" from "no rule can excuse this approval". The seat is CLOSED
|
|
246
|
-
*
|
|
247
|
-
* construction, and structural-door silent (see the first two guards).
|
|
241
|
+
* yourself" from "no rule can excuse this approval". The seat is CLOSED ({@link RuleOffersAbsence}),
|
|
242
|
+
* mutually exclusive with `ruleOffers` by construction, and structural-door silent (see the first two guards).
|
|
248
243
|
*/
|
|
249
244
|
export declare function createRuleOffersOf(cfg: {
|
|
250
245
|
/** `permissionRuleLane !== undefined` at wiring time — the armed-lane structural door. */
|
|
@@ -131,9 +131,10 @@ export interface PersonPathRowsConfig {
|
|
|
131
131
|
provider: PermissionRuleStoreProvider | undefined;
|
|
132
132
|
localOwnerDeclared: boolean;
|
|
133
133
|
principal: string | undefined;
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
root:
|
|
134
|
+
/** The session whose session-scoped rows are read; `undefined` ⇒ none. */
|
|
135
|
+
sessionId: string | undefined;
|
|
136
|
+
/** The leg's own root: which project rows apply (either spelling of it — {@link projectScopeIdentity}); `undefined` ⇒ none. */
|
|
137
|
+
root: string | undefined;
|
|
137
138
|
rootCanonical: string | undefined;
|
|
138
139
|
/** The leg's resolution of locations (a project row's scope root, where it leads). */
|
|
139
140
|
leads: HeadLeads;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { thrownLabel
|
|
2
|
-
import {
|
|
1
|
+
import { thrownLabel } from "../thrown-value.js";
|
|
2
|
+
import { egressText, egressThrownText } from "../untrusted-egress.js";
|
|
3
3
|
import { inlineUntrusted, PROBE_REASON_MAX } from "../untrusted-text.js";
|
|
4
4
|
export function policyThrowLine(err) {
|
|
5
|
-
const line = inlineUntrusted(
|
|
5
|
+
const line = inlineUntrusted(egressThrownText("same-principal", err), PROBE_REASON_MAX);
|
|
6
6
|
return line === "" ? "(no message)" : line;
|
|
7
7
|
}
|
|
8
8
|
export function policyCheckAbortedDeny() {
|
|
@@ -18,7 +18,7 @@ export function reportPolicyThrow(report, seat, call, err, signal) {
|
|
|
18
18
|
if (signal?.aborted === true)
|
|
19
19
|
return;
|
|
20
20
|
try {
|
|
21
|
-
report(new Error(`${seat} threw while judging "${call.toolName}" (toolCallId ${call.toolCallId}); the call was denied fail-closed: ${
|
|
21
|
+
report(new Error(`${seat} threw while judging "${call.toolName}" (toolCallId ${call.toolCallId}); the call was denied fail-closed: ${egressText("same-principal", thrownLabel(err))}`));
|
|
22
22
|
}
|
|
23
23
|
catch {
|
|
24
24
|
}
|
|
@@ -24,7 +24,7 @@ import { forkGovernanceDenial } from "../../agents/subagent.js";
|
|
|
24
24
|
import type { PromptEpochArtifact } from "../../prompt-assembly/artifact.js";
|
|
25
25
|
import { type WorkflowSizeGuideline } from "../../orchestration/workflow-size-guideline.js";
|
|
26
26
|
import { type AutoModeArmingRecipe } from "../auto-mode-arming.js";
|
|
27
|
-
import type
|
|
27
|
+
import { type PermissionModeController } from "../mode-policy.js";
|
|
28
28
|
import { type AutoModeDecider, type AutoModeDenialTracker } from "../auto-mode.js";
|
|
29
29
|
import { type CheckpointSeat } from "../checkpoint-seat.js";
|
|
30
30
|
import { type ComplianceCapability } from "../compliance.js";
|
|
@@ -55,8 +55,9 @@ export interface PrepareCapsAndWorkflowInput {
|
|
|
55
55
|
* config doors): the plan-pair face reads the store it names, the Workflow mount hands the seat itself to its children. */
|
|
56
56
|
checkpointSeat: CheckpointSeat | undefined;
|
|
57
57
|
/** borrowed-readonly — the trusted spawn-side channel; the Workflow mount forwards `rootSessionId`, `placementRoot`,
|
|
58
|
-
* `onTaskNotification`, `workflowDepth`,
|
|
59
|
-
|
|
58
|
+
* `onTaskNotification`, `workflowDepth`, the capture-floor getter reads `memoryCaptureAncestors`, and the arming reads
|
|
59
|
+
* the chain's auto-mode face (`inheritedGate.autoModeFace`). */
|
|
60
|
+
internals: Pick<RunInternals, "rootSessionId" | "placementRoot" | "onTaskNotification" | "workflowDepth" | "memoryCaptureAncestors" | "workflowParkedResume" | "questionFaceStripped" | "inheritedGate"> | undefined;
|
|
60
61
|
/** borrowed-readonly — the acquired session; the classifier leg rebuilds its transcript window from `buildContext`. */
|
|
61
62
|
session: Pick<StoredSession, "buildContext">;
|
|
62
63
|
/** borrowed-readonly — the acquired session id (operator-line context, the refusal codes' phase record). */
|
|
@@ -9,6 +9,7 @@ import { resolveWorkflowSizeGuideline } from "../../orchestration/workflow-size-
|
|
|
9
9
|
import { autoModeArmingRecipeOf } from "../auto-mode-arming.js";
|
|
10
10
|
import { AUTO_MODE_CLASSIFIER_MAX_RETRIES } from "../auto-mode-defaults.js";
|
|
11
11
|
import { buildAutoModePrompt, readDenyClassifierRules, renderAutoModeAction, renderAutoModeWindow } from "../auto-mode-prompt.js";
|
|
12
|
+
import { autoModeFaceOf } from "../mode-policy.js";
|
|
12
13
|
import { autoModeClassifierFallbackOf, createAutoModeDecider, createAutoModeDenialTracker, screenAutoModeKnobs } from "../auto-mode.js";
|
|
13
14
|
import { checkpointStoreOfSeat } from "../checkpoint-seat.js";
|
|
14
15
|
import { COMPLIANCE_CAPABILITIES, WEB_FETCH_TOOL_NAME, resolveComplianceDenies } from "../compliance.js";
|
|
@@ -210,15 +211,16 @@ export async function prepareCapsAndWorkflow(input) {
|
|
|
210
211
|
const autoModeDeciderRef = { current: undefined };
|
|
211
212
|
const autoModeDenialTrackingRef = { current: undefined };
|
|
212
213
|
const autoModeArmingRef = { current: undefined };
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
214
|
+
const autoModeFace = autoModeFaceOf(deps, internals?.inheritedGate);
|
|
215
|
+
const autoModeArmReason = () => autoModeArmReasonOf(permissionMode.declared === "auto", autoModeFace !== undefined, runtimeCaps, runtimeCapsFaulted);
|
|
216
|
+
if (autoModeFace !== undefined)
|
|
217
|
+
screenAutoModeKnobs(autoModeFace);
|
|
216
218
|
const armAutoMode = async () => {
|
|
217
219
|
if (autoModeDeciderRef.current !== undefined)
|
|
218
220
|
return;
|
|
219
|
-
if (permissionMode.declared !== "auto" ||
|
|
221
|
+
if (permissionMode.declared !== "auto" || autoModeFace === undefined || runtimeCaps?.autoMode === false)
|
|
220
222
|
return;
|
|
221
|
-
const am =
|
|
223
|
+
const am = autoModeFace;
|
|
222
224
|
const classifierSeat = classifierSeatModel({ deps, main: model });
|
|
223
225
|
let classifierModel = classifierSeat.model;
|
|
224
226
|
if (await derivedRouteFallsBack({ seat: "auto-mode-classifier", derived: classifierModel, primary: model, brain: deps.brain, getApiKeyAndHeaders: spec.getApiKeyAndHeaders, onNotice: deps.onNotice, sessionId, runId, onBrokenPairing: autoModeClassifierFallbackOf(am.classifierFallback) === "none" ? "refuse" : "fall_back" })) {
|
|
@@ -277,7 +279,7 @@ export async function prepareCapsAndWorkflow(input) {
|
|
|
277
279
|
autoModeDenialTrackingRef.current = denialTracking;
|
|
278
280
|
autoModeArmingRef.current = arming;
|
|
279
281
|
};
|
|
280
|
-
permissionMode.bindArming({ caps: runtimeCaps, autoFacePresent:
|
|
282
|
+
permissionMode.bindArming({ caps: runtimeCaps, autoFacePresent: autoModeFace !== undefined, armAuto: armAutoMode, onArmFault: (e) => deps.onError?.(asThrownError(e), { phase: "config", sessionId }) });
|
|
281
283
|
const deploymentWorkflowReady = runnerSelf !== undefined && isSelfOrchestrationActive(spec, deps);
|
|
282
284
|
const selfOrchestrationActive = deploymentWorkflowReady && runtimeCaps?.allowWorkflows !== false;
|
|
283
285
|
if (deploymentWorkflowReady && runtimeCaps?.allowWorkflows === false) {
|
|
@@ -7,7 +7,7 @@ import { directDeny, frozenInputSnapshot } from "./gate-exit.js";
|
|
|
7
7
|
import { emitTrace } from "../trace.js";
|
|
8
8
|
import { deliverEngineNotice } from "../engine-notice.js";
|
|
9
9
|
import { askUnresolvableNotice } from "../ask-unresolvable-notice.js";
|
|
10
|
-
import {
|
|
10
|
+
import { approvalRouteOf } from "../wiring-manifest.js";
|
|
11
11
|
import { classifierUnavailableSeat } from "./classifier-ladder.js";
|
|
12
12
|
import { PATH_CONFINABLE_WRITE_TOOLS } from "./session-rule-policy.js";
|
|
13
13
|
import { callFaceSeat, rosterToolName, survivorsByName, toolCallFaceOf } from "../tool-roster.js";
|
|
@@ -20,7 +20,7 @@ function screenGateResult(result) {
|
|
|
20
20
|
const gate = result.gate;
|
|
21
21
|
if (gate === undefined)
|
|
22
22
|
return { defects: ["a tool-gate result carried no outcome record on a terminal exit — every terminal exit mints one; the frame carries none"] };
|
|
23
|
-
const defects = screenGateOutcome(gate);
|
|
23
|
+
const defects = screenGateOutcome(gate, { reading: "producer" });
|
|
24
24
|
const blocked = result.block === true;
|
|
25
25
|
if ((gate.disposition.kind === "denied") !== blocked) {
|
|
26
26
|
defects.push(`a tool-gate result's outcome reads "${gate.disposition.kind}" on ${blocked ? "a blocked" : "an executing"} call — the two faces of one verdict disagree; the frame carries no outcome`);
|
|
@@ -140,7 +140,7 @@ export function prepareGateStations(input) {
|
|
|
140
140
|
...(notifyPermissionDenied ? { permissionDenied: (p) => notifyPermissionDenied({ ...p, permissionMode: permissionMode.observed }) } : {}),
|
|
141
141
|
onHookError: notifyHookError,
|
|
142
142
|
shellGated: tierSeat?.shellGated(shellGatedTools, toolMarkSources) === true,
|
|
143
|
-
...(autoModeDecider.current !== undefined ? { autoMode: { decider: autoModeDecider.current, ...(autoModeDenialTracking.current !== undefined ? { denialTracking: autoModeDenialTracking.current } : {}), unavailable: classifierUnavailableSeat({ station: "leg", ...(autoModeDecider.current.timeoutMs !== undefined ? { budgetMs: autoModeDecider.current.timeoutMs } : {}),
|
|
143
|
+
...(autoModeDecider.current !== undefined ? { autoMode: { decider: autoModeDecider.current, ...(autoModeDenialTracking.current !== undefined ? { denialTracking: autoModeDenialTracking.current } : {}), unavailable: classifierUnavailableSeat({ station: "leg", ...(autoModeDecider.current.timeoutMs !== undefined ? { budgetMs: autoModeDecider.current.timeoutMs } : {}), route: approvalRouteOf(askRoute), onNotice: deps.onNotice, sessionId, runId }) } } : {}),
|
|
144
144
|
permissionMode: () => permissionMode.current, askSeatForm: askRoute.form,
|
|
145
145
|
...(markSources.size > 0 ? { toolMarkSources: markSources } : {}),
|
|
146
146
|
...seatInputsFor(e.toolName, wireOf("gate.skillActivationSeat", call)),
|
|
@@ -19,6 +19,7 @@ import { sessionSeatAnchorHolds } from "./session-read-file-states.js";
|
|
|
19
19
|
import { rebaseWorkspacePath } from "./workspace-path.js";
|
|
20
20
|
import { RosterBuilder } from "../tool-roster.js";
|
|
21
21
|
import { unionAddOnly } from "../child-clamp-seats.js";
|
|
22
|
+
import { assertStringArraySeat } from "../read-face-seats.js";
|
|
22
23
|
import { modePolicyOf } from "../mode-policy.js";
|
|
23
24
|
const faceClampAnnouncedSinks = { read: new WeakSet(), write: new WeakSet() };
|
|
24
25
|
const faceClampConsoleAnnounced = { read: false, write: false };
|
|
@@ -39,25 +40,6 @@ export function __resetReadFaceClampAnnouncement() {
|
|
|
39
40
|
faceClampConsoleAnnounced.read = false;
|
|
40
41
|
faceClampConsoleAnnounced.write = false;
|
|
41
42
|
}
|
|
42
|
-
function assertStringArraySeat(value, seat, entryLaw) {
|
|
43
|
-
if (value === undefined)
|
|
44
|
-
return;
|
|
45
|
-
if (!Array.isArray(value)) {
|
|
46
|
-
const e = new Error(`${seat} must be an array or absent (got ${value === null ? "null" : typeof value}) — a non-array here would be iterated character by character, so it refuses loudly instead.`);
|
|
47
|
-
e.code = "config.read_face_seat";
|
|
48
|
-
throw e;
|
|
49
|
-
}
|
|
50
|
-
if (entryLaw !== "strings")
|
|
51
|
-
return;
|
|
52
|
-
const entries = value;
|
|
53
|
-
for (const entry of entries) {
|
|
54
|
-
if (typeof entry !== "string") {
|
|
55
|
-
const e = new Error(`${seat} entries must be strings (got ${entry === null ? "null" : typeof entry}).`);
|
|
56
|
-
e.code = "config.read_face_seat";
|
|
57
|
-
throw e;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
43
|
function writeFaceReader(input, onDeploymentClamp) {
|
|
62
44
|
const { spec, deps, resume, fullShellReachable, permissionMode } = input;
|
|
63
45
|
const seats = { kind: "write", readOnlyMount: spec.handsReadOnly === true, orgGoverned: deps.permissionRuleStore?.partitions.org === true, fullShellReachable };
|
|
@@ -8,7 +8,7 @@ import { StubExecutionEnv } from "../stub-env.js";
|
|
|
8
8
|
import { askApproverIdentity, durableMandateSourceOf } from "../tool-policy.js";
|
|
9
9
|
import { chainAnchorRecords } from "./child-tree.js";
|
|
10
10
|
import { deliverEngineNotice } from "../types.js";
|
|
11
|
-
import { PermissionModeController, modeRequestAfterResume } from "../mode-policy.js";
|
|
11
|
+
import { PermissionModeController, autoModeFaceOf, modeRequestAfterResume } from "../mode-policy.js";
|
|
12
12
|
import { SessionModeSeats } from "./session-mode-seats.js";
|
|
13
13
|
import { recordedModeSeed } from "../checkpoint-store.js";
|
|
14
14
|
import { frozenSkillGrants } from "../skill-grant.js";
|
|
@@ -42,22 +42,22 @@ export function prepareInheritedGate(input) {
|
|
|
42
42
|
const policy = pathRuleAnchors.onLeg(pc.policy, position);
|
|
43
43
|
return policy === pc.policy ? pc : { ...pc, policy };
|
|
44
44
|
});
|
|
45
|
-
const
|
|
45
|
+
const autoModeFace = autoModeFaceOf(deps, liveInheritedGate);
|
|
46
|
+
const inheritedParentConstraints = attachRebuiltDenialTrackers(chainView, autoModeFace?.denialLimit);
|
|
46
47
|
const parentSeat = liveInheritedGate?.permissionModeCeiling;
|
|
47
48
|
const ceiling = parentSeat ?? liveInheritedGate?.permissionMode;
|
|
48
|
-
const announceModeFold = (receipt) => {
|
|
49
|
+
const announceModeFold = (receipt, folded) => {
|
|
49
50
|
if (receipt.foldedBy === undefined)
|
|
50
51
|
return;
|
|
51
|
-
const requested = receipt.requested ?? "default";
|
|
52
52
|
const because = receipt.foldedBy === "operator_deny" ? "the deployment denies it for this principal" : receipt.foldedBy === "face_absent" ? "no auto-mode classifier face is wired on this deployment" : `the parent leg's mode is the ceiling a child's declaration is clamped under`;
|
|
53
|
-
const message = `permission mode "${
|
|
54
|
-
deliverEngineNotice(deps.onNotice, { code: "config.permission_mode_unavailable", message, detail: { requested, effective: receipt.effective, by: receipt.foldedBy, sessionId, runId } });
|
|
55
|
-
if (
|
|
56
|
-
deliverEngineNotice(deps.onNotice, { code: "config.permission_mode_unavailable", message: `${message} (a child leg, ${sessionId})`, detail: { requested, effective: receipt.effective, by: receipt.foldedBy, sessionId: parentSeat.sessionId, childSessionId: sessionId, runId } });
|
|
53
|
+
const message = `permission mode "${folded}"${receipt.requested === undefined ? " (inherited)" : ""} is not available on this leg (${because}) — it runs under "${receipt.effective}"`;
|
|
54
|
+
deliverEngineNotice(deps.onNotice, { code: "config.permission_mode_unavailable", message, detail: { requested: folded, effective: receipt.effective, by: receipt.foldedBy, sessionId, runId } });
|
|
55
|
+
if (parentSeat !== undefined) {
|
|
56
|
+
deliverEngineNotice(deps.onNotice, { code: "config.permission_mode_unavailable", message: `${message} (a child leg, ${sessionId})`, detail: { requested: folded, effective: receipt.effective, by: receipt.foldedBy, sessionId: parentSeat.sessionId, childSessionId: sessionId, runId } });
|
|
57
57
|
}
|
|
58
58
|
};
|
|
59
59
|
const permissionMode = new PermissionModeController(modeRequestAfterResume(permissionModeSeat, modeSeed, resume?.outcome), ceiling, { onFold: announceModeFold, ...(modeSeed.prePlanMode !== undefined ? { prePlanMode: modeSeed.prePlanMode } : {}) });
|
|
60
|
-
|
|
60
|
+
permissionMode.announceStart();
|
|
61
61
|
const { ceiling: legModeCeiling, commit: commitLegModeCeiling, end: endModeCeiling } = (internals?.sessionModeSeats ?? new SessionModeSeats()).legCeiling(sessionId, permissionMode);
|
|
62
62
|
const commitModeSeats = (legSignal) => {
|
|
63
63
|
commitLegModeCeiling();
|
|
@@ -186,6 +186,7 @@ export function prepareInheritedGate(input) {
|
|
|
186
186
|
...(effectiveShellGate !== undefined ? { shellGate: effectiveShellGate } : {}),
|
|
187
187
|
permissionMode: permissionMode.current,
|
|
188
188
|
permissionModeCeiling: legModeCeiling,
|
|
189
|
+
...(autoModeFace !== undefined ? { autoModeFace } : {}),
|
|
189
190
|
...(parentConstraints.length > 0 ? { parentConstraints } : {}),
|
|
190
191
|
...chainAnchorRecords(pathRuleAnchors.chainTop, parentConstraints),
|
|
191
192
|
admittedOrgScopes: memoryAdmittedOrgScopesRef.current,
|
|
@@ -107,8 +107,6 @@ export interface PreparePolicyChainInput {
|
|
|
107
107
|
/** borrowed-readonly — the run's one reader of the person's rules (`person-path-rows.ts`): the lanes take each call's
|
|
108
108
|
* pinned read from it. */
|
|
109
109
|
personRows: import("./person-path-rows.js").PersonPathRows;
|
|
110
|
-
/** borrowed-readonly — a reader of the same rows the run's cut does not end (the same notices), for the lane asked after the run. */
|
|
111
|
-
personRowsBeyondRun: import("./person-path-rows.js").PersonPathRows;
|
|
112
110
|
/** borrowed-readonly — whether the question tool mounted (the lanes' question-tool exclusion). */
|
|
113
111
|
questionToolMounted: boolean;
|
|
114
112
|
/** borrowed-readonly — the resolved per-principal entitlements; only `forceDurableGate` (the mandate-park facility and
|
|
@@ -241,9 +239,9 @@ export interface PreparePolicyChainResult {
|
|
|
241
239
|
grantBindingOf: GrantBindingOf;
|
|
242
240
|
/** owned — the personal permission-rule lane, or undefined. */
|
|
243
241
|
permissionRuleLane: PermissionRuleLanes["personal"];
|
|
244
|
-
/** owned — the
|
|
245
|
-
* run
|
|
246
|
-
|
|
242
|
+
/** owned — the leg's facts the two lanes judge against (session, root and anchors, head leads, sinks), for the consolidation
|
|
243
|
+
* write judge, which builds its own two lanes over the reader the run's cut does not end (it is asked after the run). */
|
|
244
|
+
ruleLaneFacts: import("./memory-consolidation-write-judge.js").ConsolidationWriteJudgeLeg["lanes"];
|
|
247
245
|
/** owned — the org permission-rule lane (`Prepared.permissionRuleOrg`), or undefined. */
|
|
248
246
|
permissionRuleOrgLane: PermissionRuleLanes["org"];
|
|
249
247
|
/** owned — whether the sandbox-admission mode armed (declared isolation with its park prerequisites). */
|
|
@@ -20,13 +20,14 @@ import { createModeGatePolicy, mountedToolDeclaresReadOnly } from "../mode-polic
|
|
|
20
20
|
const ancestorFacts = (ask) => ({ ...(ask ?? {}), ancestorResolved: true });
|
|
21
21
|
import { headlessDenyAtFold, headlessDenyAtRecheck, INHERITED_STATION_FACTS, inheritedAskCarry, inheritedAskFallbackMessage, judgeInheritedClassifier, lateAskSettlementObserver, resolveInheritedAsk, settleDenialLimitFallback } from "./denial-limit-arms.js";
|
|
22
22
|
import { settleReadRootGrant } from "./read-root-grant.js";
|
|
23
|
+
import { frozenApproverRoute } from "../wiring-manifest.js";
|
|
23
24
|
import { askGrantShapeOf } from "./inherited-ask-grants.js";
|
|
24
25
|
import { createPermissionRuleLanes, inheritedAskRuleEvidence, createRuleOffersOf } from "./permission-rule-lanes.js";
|
|
25
26
|
import { createLiveSessionRules, createSessionRulePolicy } from "./session-rule-policy.js";
|
|
26
27
|
import { policyThrowLine, reportPolicyThrow } from "./policy-throw.js";
|
|
27
28
|
import { heldBy, heldValues, seatOf, wireOf } from "../tool-name-readings.js";
|
|
28
29
|
export async function preparePolicyChain(input) {
|
|
29
|
-
const { spec, deps, internals, sessionId, runId, hostTaskId, taskRootFinal, additionalRootsCanonical, executionEnv, lockedPreflight, pathRuleAnchors, headLeads, tools, harnessTools, toolEffects, egressTools, irreversibilityTier, axisExplicitNegatives, shellGatedTools, toolMarkSources, envHandToolNames, handsCwdRef, readDenyMatcher, personRows,
|
|
30
|
+
const { spec, deps, internals, sessionId, runId, hostTaskId, taskRootFinal, additionalRootsCanonical, executionEnv, lockedPreflight, pathRuleAnchors, headLeads, tools, harnessTools, toolEffects, egressTools, irreversibilityTier, axisExplicitNegatives, shellGatedTools, toolMarkSources, envHandToolNames, handsCwdRef, readDenyMatcher, personRows, questionToolMounted, runtimeCaps, inheritedAncestorRules, ancestorSessionRulesRef, inheritedParentConstraints, seedInheritedGate, skillGrants, skillSpecs, allowedToolTables, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, autoModeDecider, readFace, permissionMode, scratchpadDir, toolRosterDeltas, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef } = input;
|
|
30
31
|
const ancestorArbitrations = new Map();
|
|
31
32
|
const arbitrateInherited = (ask, toolCallId, judged) => {
|
|
32
33
|
const verdict = arbitrateByMode(permissionMode.current, judged.classification, { origin: judged.origin, ...askMandateMember(ancestorFacts(judged.ask.action === "ask" ? judged.ask : undefined)) });
|
|
@@ -124,7 +125,7 @@ export async function preparePolicyChain(input) {
|
|
|
124
125
|
rules: row,
|
|
125
126
|
};
|
|
126
127
|
};
|
|
127
|
-
sessionRulePolicy = createSessionRulePolicy({ seed, read: createLiveSessionRules(store, { ...sessionRuleKey, seed }, { onUnreadable: announceSessionRulesUnreadable, onEnforced: publishOwnRules }) }, { env: executionEnv, rootPath: taskRootFinal, toolEffects });
|
|
128
|
+
sessionRulePolicy = createSessionRulePolicy({ seed, read: createLiveSessionRules(store, { ...sessionRuleKey, seed }, { onUnreadable: announceSessionRulesUnreadable, onEnforced: publishOwnRules }) }, { env: executionEnv, rootPath: taskRootFinal, toolEffects, anchors: pathRuleAnchors.leg });
|
|
128
129
|
if (rules)
|
|
129
130
|
publishOwnRules(rules);
|
|
130
131
|
}
|
|
@@ -145,7 +146,7 @@ export async function preparePolicyChain(input) {
|
|
|
145
146
|
...(deps.sessionPolicyStore
|
|
146
147
|
? { read: createLiveSessionRules(deps.sessionPolicyStore, { sessionId: snap.sessionId, ...(snap.principal !== undefined ? { principal: snap.principal } : {}), seed }, { onUnreadable: announceSessionRulesUnreadable, onEnforced: publishAncestorRules }) }
|
|
147
148
|
: {}),
|
|
148
|
-
}, { env: executionEnv, rootPath: taskRootFinal, toolEffects }));
|
|
149
|
+
}, { env: executionEnv, rootPath: taskRootFinal, toolEffects, anchors: pathRuleAnchors.leg }));
|
|
149
150
|
}
|
|
150
151
|
const frozenConstraintLayers = (seedInheritedGate?.constraintChain ?? [])
|
|
151
152
|
.filter((e) => !("opaque" in e))
|
|
@@ -321,10 +322,7 @@ export async function preparePolicyChain(input) {
|
|
|
321
322
|
const listFacts = { root: taskRootFinal, sessionId, liveCwd: () => handsCwdRef?.current, anchors: pathRuleAnchors.leg };
|
|
322
323
|
const skillGrantLane = skillGrants.lane(listFacts);
|
|
323
324
|
const allowEntryLanes = { request: allowedToolTables.request.lane(listFacts), deployment: allowedToolTables.deployment.lane(listFacts) };
|
|
324
|
-
const
|
|
325
|
-
provider: deps.permissionRuleStore,
|
|
326
|
-
localOwnerDeclared: deps.localOwnerRules === true,
|
|
327
|
-
principal: spec.principal,
|
|
325
|
+
const ruleLaneFacts = {
|
|
328
326
|
sessionId,
|
|
329
327
|
root: taskRootFinal,
|
|
330
328
|
rootCanonical: pathRuleAnchors.leg.root,
|
|
@@ -338,8 +336,7 @@ export async function preparePolicyChain(input) {
|
|
|
338
336
|
onDisclosure: (message) => emitTrace(deps.tracer, () => ({ kind: "permission.rule_store_unreadable", version: 1, taskId: hostTaskId, message, ts: Date.now() })),
|
|
339
337
|
stripsAllow: (rule, req) => permissionMode.current === "auto" && autoStrippedRule(rule, req),
|
|
340
338
|
};
|
|
341
|
-
const { personal: permissionRuleLane, org: permissionRuleOrgLane } = createPermissionRuleLanes({ ...
|
|
342
|
-
const ruleLanesBeyondRun = createPermissionRuleLanes({ ...ruleLaneConfig, rows: personRowsBeyondRun });
|
|
339
|
+
const { personal: permissionRuleLane, org: permissionRuleOrgLane } = createPermissionRuleLanes({ provider: deps.permissionRuleStore, localOwnerDeclared: deps.localOwnerRules === true, principal: spec.principal, ...ruleLaneFacts, rows: personRows });
|
|
343
340
|
const ruleOffersOf = createRuleOffersOf({
|
|
344
341
|
laneArmed: permissionRuleLane !== undefined,
|
|
345
342
|
principal: spec.principal,
|
|
@@ -386,7 +383,7 @@ export async function preparePolicyChain(input) {
|
|
|
386
383
|
}
|
|
387
384
|
if (re.updatedInput !== undefined)
|
|
388
385
|
editArgs = re.updatedInput;
|
|
389
|
-
const judged = await judgeInheritedClassifier({ liveMode: () => permissionMode.current, autoMode: ancestorAutoMode, ask: re, req: { ...creq, args: editArgs }, signal: csignal ?? abortController.signal, subject: "the approved edit", allowRewrite: editArgs, facts: inheritedStationFacts(creq), unavailableSeat: classifierUnavailableSeat({ station: "ancestor", ...(ancestorDecider?.timeoutMs !== undefined ? { budgetMs: ancestorDecider.timeoutMs } : {}),
|
|
386
|
+
const judged = await judgeInheritedClassifier({ liveMode: () => permissionMode.current, autoMode: ancestorAutoMode, ask: re, req: { ...creq, args: editArgs }, signal: csignal ?? abortController.signal, subject: "the approved edit", allowRewrite: editArgs, facts: inheritedStationFacts(creq), unavailableSeat: classifierUnavailableSeat({ station: "ancestor", ...(ancestorDecider?.timeoutMs !== undefined ? { budgetMs: ancestorDecider.timeoutMs } : {}), route: frozenApproverRoute(onAskOf), onNotice: deps.onNotice, sessionId, runId }) });
|
|
390
387
|
if (judged.kind === "allow") {
|
|
391
388
|
return onApproval(judged.result);
|
|
392
389
|
}
|
|
@@ -461,7 +458,7 @@ export async function preparePolicyChain(input) {
|
|
|
461
458
|
return first;
|
|
462
459
|
return mandateUnreconstructibleDeny(creq);
|
|
463
460
|
}
|
|
464
|
-
const judged = await judgeInheritedClassifier({ liveMode: () => permissionMode.current, autoMode: pc.autoMode, ask: first, req: creq, signal: csignal ?? abortController.signal, subject: "this call", facts: inheritedStationFacts(creq), unavailableSeat: classifierUnavailableSeat({ station: "ancestor", ...(pc.autoMode?.decider.timeoutMs !== undefined ? { budgetMs: pc.autoMode.decider.timeoutMs } : {}),
|
|
461
|
+
const judged = await judgeInheritedClassifier({ liveMode: () => permissionMode.current, autoMode: pc.autoMode, ask: first, req: creq, signal: csignal ?? abortController.signal, subject: "this call", facts: inheritedStationFacts(creq), unavailableSeat: classifierUnavailableSeat({ station: "ancestor", ...(pc.autoMode?.decider.timeoutMs !== undefined ? { budgetMs: pc.autoMode.decider.timeoutMs } : {}), route: frozenApproverRoute(pc.onAsk), onNotice: deps.onNotice, sessionId, runId }) });
|
|
465
462
|
if (judged.kind === "allow")
|
|
466
463
|
return judged.result;
|
|
467
464
|
if (judged.kind === "deny")
|
|
@@ -537,7 +534,7 @@ export async function preparePolicyChain(input) {
|
|
|
537
534
|
return mandateUnreconstructibleDeny(creq);
|
|
538
535
|
}
|
|
539
536
|
const presentedArgs = decision.updatedInput !== undefined ? decision.updatedInput : creq.args;
|
|
540
|
-
const judged = await judgeInheritedClassifier({ liveMode: () => permissionMode.current, autoMode: pc.autoMode, ask: decision, req: { ...creq, args: presentedArgs }, signal: csignal ?? abortController.signal, subject: "this call", allowRewrite: decision.updatedInput, facts: inheritedStationFacts(creq), unavailableSeat: classifierUnavailableSeat({ station: "ancestor", ...(pc.autoMode?.decider.timeoutMs !== undefined ? { budgetMs: pc.autoMode.decider.timeoutMs } : {}),
|
|
537
|
+
const judged = await judgeInheritedClassifier({ liveMode: () => permissionMode.current, autoMode: pc.autoMode, ask: decision, req: { ...creq, args: presentedArgs }, signal: csignal ?? abortController.signal, subject: "this call", allowRewrite: decision.updatedInput, facts: inheritedStationFacts(creq), unavailableSeat: classifierUnavailableSeat({ station: "ancestor", ...(pc.autoMode?.decider.timeoutMs !== undefined ? { budgetMs: pc.autoMode.decider.timeoutMs } : {}), route: frozenApproverRoute(pc.onAsk), onNotice: deps.onNotice, sessionId, runId }) });
|
|
541
538
|
if (judged.kind === "allow")
|
|
542
539
|
return judged.result;
|
|
543
540
|
if (judged.kind === "deny")
|
|
@@ -679,7 +676,7 @@ export async function preparePolicyChain(input) {
|
|
|
679
676
|
return decision;
|
|
680
677
|
})
|
|
681
678
|
: foldedPolicy;
|
|
682
|
-
return { hooks, hookTimeoutMs, preToolUseObservational, ownGatePreToolUse, basePolicyForResumeEdit, denyNarrowingPolicy, skillGrantLane, allowEntryLanes, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, grantBindingOf, permissionRuleLane,
|
|
679
|
+
return { hooks, hookTimeoutMs, preToolUseObservational, ownGatePreToolUse, basePolicyForResumeEdit, denyNarrowingPolicy, skillGrantLane, allowEntryLanes, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, grantBindingOf, permissionRuleLane, ruleLaneFacts, permissionRuleOrgLane, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, foldAskClasses, ancestorSandboxAdmissions, ancestorArbitrations };
|
|
683
680
|
}
|
|
684
681
|
const advisedPolicyNames = new WeakMap();
|
|
685
682
|
const ADVISED_KEYS_CAP = 64;
|