toolroll 0.9.65 → 0.9.68
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 +93 -0
- package/README.md +20 -2
- package/dist/acp-client.js +1 -3
- package/dist/agent-board.d.ts +0 -1
- package/dist/agent-board.js +0 -1
- package/dist/agent-fence.d.ts +69 -2
- package/dist/agent-fence.js +294 -11
- package/dist/agentconfig.js +4 -1
- package/dist/batch-checks.js +3 -2
- package/dist/browser/THIRD_PARTY_NOTICES.txt +46 -0
- package/dist/browser/terminal.js +134 -23
- package/dist/browser/workspace.css +2 -2
- package/dist/browser/workspace.js +31 -29
- package/dist/builder.d.ts +4 -0
- package/dist/builder.js +56 -37
- package/dist/canonical-json.d.ts +14 -0
- package/dist/canonical-json.js +36 -0
- package/dist/chat-actions.js +1 -2
- package/dist/chat-admission.d.ts +19 -0
- package/dist/chat-admission.js +22 -0
- package/dist/chat-channel.js +1 -1
- package/dist/chat-delivery.js +0 -1
- package/dist/chat-follow.d.ts +17 -0
- package/dist/chat-follow.js +32 -0
- package/dist/chat-messages.js +0 -1
- package/dist/chat-settings-page.d.ts +23 -0
- package/dist/chat-settings-page.js +41 -0
- package/dist/claim.js +3 -6
- package/dist/claude-print.d.ts +12 -0
- package/dist/claude-print.js +34 -0
- package/dist/cli-http.d.ts +0 -7
- package/dist/cli-http.js +0 -21
- package/dist/cli.d.ts +3 -10
- package/dist/cli.js +15 -24
- package/dist/coding-provider.js +2 -1
- package/dist/coding-workspace.js +1 -1
- package/dist/{team-cli.d.ts → connect-cli.d.ts} +5 -9
- package/dist/connect-cli.js +331 -0
- package/dist/containment.d.ts +0 -2
- package/dist/containment.js +2 -6
- package/dist/contracts/chat-actions.d.ts +0 -1
- package/dist/contracts/chat-content.d.ts +0 -4
- package/dist/contracts/chat-content.js +0 -2
- package/dist/contracts/chat-tables.d.ts +0 -1
- package/dist/contracts/cli.d.ts +0 -62
- package/dist/contracts/cli.js +0 -4
- package/dist/contracts/coding-workspace.js +1 -1
- package/dist/contracts/console-api.d.ts +1 -0
- package/dist/contracts/console-api.js +1 -0
- package/dist/contracts/contract.js +1 -1
- package/dist/contracts/flow-card.d.ts +0 -1
- package/dist/contracts/flow-propose.d.ts +0 -1
- package/dist/contracts/flow-send.js +1 -1
- package/dist/contracts/gateway-tools.d.ts +0 -1
- package/dist/contracts/integration-metadata.js +1 -1
- package/dist/contracts/lead-tools.d.ts +0 -1
- package/dist/contracts/memory-pass.d.ts +0 -1
- package/dist/contracts/memory-pass.js +1 -1
- package/dist/contracts/plan.js +1 -1
- package/dist/contracts/project-knowledge.js +1 -1
- package/dist/contracts/project-skills.d.ts +0 -1
- package/dist/contracts/proof.js +1 -1
- package/dist/contracts/recipes.js +1 -1
- package/dist/contracts/scope.js +1 -1
- package/dist/contracts/scout-report.js +1 -1
- package/dist/contracts/teams-callback.d.ts +0 -1
- package/dist/converse.d.ts +0 -6
- package/dist/converse.js +0 -19
- package/dist/daemon.js +3 -2
- package/dist/decision.d.ts +1 -3
- package/dist/deprecations.d.ts +12 -4
- package/dist/deprecations.js +27 -4
- package/dist/desktop-update-recovery.js +1 -1
- package/dist/desktop-update.js +3 -2
- package/dist/discord-chat.js +4 -15
- package/dist/discord-settings.d.ts +2 -6
- package/dist/discord-settings.js +10 -38
- package/dist/discord.js +12 -23
- package/dist/evidence.d.ts +0 -1
- package/dist/evidence.js +0 -3
- package/dist/exec.d.ts +0 -9
- package/dist/exec.js +3 -81
- package/dist/flow-actions.js +0 -3
- package/dist/flow-draft.d.ts +1 -3
- package/dist/flow-draft.js +15 -28
- package/dist/flow-scripts.d.ts +1 -8
- package/dist/flow-scripts.js +0 -13
- package/dist/flow-send.js +1 -1
- package/dist/flow-share.d.ts +0 -2
- package/dist/flow-share.js +1 -6
- package/dist/flow-steps.js +1 -1
- package/dist/flow-triggers.d.ts +0 -1
- package/dist/flow-triggers.js +1 -2
- package/dist/flow-unattended.js +1 -12
- package/dist/flows.js +1 -1
- package/dist/health-cli.d.ts +2 -2
- package/dist/health-cli.js +1 -1
- package/dist/invoke.d.ts +18 -3
- package/dist/invoke.js +142 -17
- package/dist/is-record.d.ts +2 -0
- package/dist/is-record.js +2 -0
- package/dist/lead-doors.d.ts +1 -5
- package/dist/lead-doors.js +0 -4
- package/dist/lead-tools.js +3 -6
- package/dist/live-detail.d.ts +0 -1
- package/dist/live-detail.js +0 -6
- package/dist/live-terminal.d.ts +24 -13
- package/dist/live-terminal.js +81 -43
- package/dist/live.d.ts +0 -1
- package/dist/live.js +1 -2
- package/dist/mcp-core.js +0 -2
- package/dist/memory-pass.js +1 -1
- package/dist/model-catalog.js +1 -1
- package/dist/modes.js +1 -12
- package/dist/operate.d.ts +2 -0
- package/dist/operate.js +436 -745
- package/dist/password-bearer.d.ts +0 -2
- package/dist/password-bearer.js +0 -4
- package/dist/peek-cli.js +2 -1
- package/dist/peek.d.ts +2 -26
- package/dist/peek.js +2 -168
- package/dist/phase-routing.d.ts +0 -4
- package/dist/phase-routing.js +2 -21
- package/dist/planner-source.d.ts +2 -1
- package/dist/planner-source.js +2 -12
- package/dist/planner.js +2 -14
- package/dist/process-tree.d.ts +0 -2
- package/dist/process-tree.js +0 -10
- package/dist/project-delete-ui.d.ts +6 -0
- package/dist/project-delete-ui.js +20 -1
- package/dist/project-delete.d.ts +0 -2
- package/dist/project-delete.js +1 -3
- package/dist/project-learning.d.ts +0 -14
- package/dist/project-skills.d.ts +0 -1
- package/dist/project-skills.js +0 -14
- package/dist/project-tools.js +2 -10
- package/dist/provider.d.ts +0 -17
- package/dist/provider.js +0 -26
- package/dist/pulls.d.ts +0 -2
- package/dist/pulls.js +0 -9
- package/dist/release-adapters.d.ts +9 -0
- package/dist/release-adapters.js +81 -4
- package/dist/release.d.ts +7 -1
- package/dist/release.js +20 -7
- package/dist/remote-exec.d.ts +3 -2
- package/dist/remote-exec.js +3 -2
- package/dist/repos.d.ts +0 -5
- package/dist/repos.js +2 -10
- package/dist/repository-context.d.ts +0 -2
- package/dist/repository-context.js +0 -4
- package/dist/restart-certification.d.ts +0 -2
- package/dist/restart-certification.js +1 -5
- package/dist/result-follow-ups.d.ts +1 -4
- package/dist/result-follow-ups.js +4 -8
- package/dist/result-review.d.ts +0 -2
- package/dist/result-review.js +0 -2
- package/dist/retention.d.ts +0 -1
- package/dist/retention.js +0 -1
- package/dist/review-context.d.ts +0 -1
- package/dist/review-context.js +1 -12
- package/dist/reviewer.d.ts +0 -16
- package/dist/reviewer.js +0 -18
- package/dist/run-closeout.js +2 -1
- package/dist/scope.d.ts +13 -0
- package/dist/scope.js +11 -18
- package/dist/scout-browser.js +2 -1
- package/dist/serve.js +3 -2
- package/dist/server/chrome.d.ts +10 -1
- package/dist/server/chrome.js +45 -4
- package/dist/server/console.css +60 -137
- package/dist/server/flows.js +2 -2
- package/dist/server/http.d.ts +2 -0
- package/dist/server/http.js +5 -0
- package/dist/server/pages.js +2 -2
- package/dist/server/people-tokens.js +3 -4
- package/dist/server/remote.js +1 -6
- package/dist/server/render-chat.d.ts +9 -2
- package/dist/server/render-chat.js +53 -7
- package/dist/server/render-pages.d.ts +28 -3
- package/dist/server/render-pages.js +78 -9
- package/dist/server/render-results.d.ts +0 -6
- package/dist/server/render-results.js +3 -9
- package/dist/server/render-tasks.js +6 -6
- package/dist/server/route-table.d.ts +0 -4
- package/dist/server/route-table.js +1 -6
- package/dist/server/settings.js +43 -22
- package/dist/server/task-views.js +1 -1
- package/dist/server/tasks.js +10 -7
- package/dist/setup-guide.d.ts +2 -2
- package/dist/skills.d.ts +0 -6
- package/dist/skills.js +0 -8
- package/dist/slack-chat.d.ts +1 -7
- package/dist/slack-chat.js +5 -18
- package/dist/slack-settings.d.ts +2 -6
- package/dist/slack-settings.js +10 -38
- package/dist/slack.js +12 -23
- package/dist/sleep.d.ts +2 -0
- package/dist/sleep.js +2 -0
- package/dist/store.d.ts +11 -74
- package/dist/store.js +36 -179
- package/dist/structured-output.d.ts +0 -1
- package/dist/structured-output.js +0 -1
- package/dist/subagent-work.d.ts +0 -2
- package/dist/subagent-work.js +0 -2
- package/dist/subagents.d.ts +1 -3
- package/dist/subagents.js +20 -33
- package/dist/subscription-chat.d.ts +1 -3
- package/dist/subscription-chat.js +2 -3
- package/dist/task-sizing.d.ts +1 -4
- package/dist/task-sizing.js +3 -10
- package/dist/teams-chat.js +4 -11
- package/dist/teams.js +12 -19
- package/dist/teardown-git.d.ts +22 -0
- package/dist/teardown-git.js +136 -2
- package/dist/telegram-lead.js +2 -2
- package/dist/telegram.js +1 -1
- package/dist/token-notices.d.ts +0 -11
- package/dist/token-notices.js +1 -5
- package/dist/tool-broker.d.ts +12 -0
- package/dist/tool-broker.js +66 -2
- package/dist/tool-secret-store.d.ts +0 -3
- package/dist/tool-secret-store.js +2 -11
- package/dist/toolroll-update.d.ts +0 -2
- package/dist/toolroll-update.js +2 -2
- package/dist/unfenced-test-support.d.ts +2 -0
- package/dist/unfenced-test-support.js +11 -0
- package/dist/verification-evidence.d.ts +0 -1
- package/dist/verification-evidence.js +0 -1
- package/dist/webhooks.d.ts +0 -1
- package/dist/webhooks.js +0 -1
- package/dist/workspace-ui.d.ts +0 -8
- package/dist/workspace-ui.js +1 -6
- package/dist/writes-mode.d.ts +9 -0
- package/dist/writes-mode.js +8 -0
- package/package.json +5 -1
- package/dist/contracts/native-census.d.ts +0 -42
- package/dist/contracts/native-census.js +0 -36
- package/dist/process-recovery-anchor.d.ts +0 -75
- package/dist/process-recovery-anchor.js +0 -188
- package/dist/process-recovery-coalition.d.ts +0 -25
- package/dist/process-recovery-coalition.js +0 -105
- package/dist/process-recovery-eligibility.d.ts +0 -179
- package/dist/process-recovery-eligibility.js +0 -174
- package/dist/process-recovery-native.d.ts +0 -161
- package/dist/process-recovery-native.js +0 -595
- package/dist/process-recovery-provenance.d.ts +0 -163
- package/dist/process-recovery-provenance.js +0 -292
- package/dist/process-recovery-services.d.ts +0 -56
- package/dist/process-recovery-services.js +0 -191
- package/dist/process-recovery-settlement.d.ts +0 -32
- package/dist/process-recovery-settlement.js +0 -133
- package/dist/process-recovery.d.ts +0 -41
- package/dist/process-recovery.js +0 -91
- package/dist/session-brief.d.ts +0 -8
- package/dist/session-brief.js +0 -24
- package/dist/session-cli.d.ts +0 -42
- package/dist/session-cli.js +0 -271
- package/dist/session-contract.d.ts +0 -183
- package/dist/session-contract.js +0 -122
- package/dist/session-remote.d.ts +0 -19
- package/dist/session-remote.js +0 -86
- package/dist/session-service.d.ts +0 -22
- package/dist/session-service.js +0 -157
- package/dist/team-cli.js +0 -692
|
@@ -17,8 +17,6 @@ export declare const PASSWORD_BEARER_REFUSED = "Toolroll no longer accepts a pas
|
|
|
17
17
|
export declare function isPasswordBearer(authorization: string | undefined): boolean;
|
|
18
18
|
/** Whether this build still accepts a password bearer: only a release before PASSWORD_BEARER_REFUSED_FROM does. */
|
|
19
19
|
export declare function passwordBearerAccepted(version?: string): boolean;
|
|
20
|
-
/** A refusal's words for this request: unchanged, or with the replacement when it came with a password bearer. */
|
|
21
|
-
export declare function withReplacement(authorization: string | undefined, message: string): string;
|
|
22
20
|
/**
|
|
23
21
|
* The refusal boundary for one password-bearer request, whichever adapter answers it: the deprecation is announced in
|
|
24
22
|
* headers (RFC 9745 Deprecation, and a Warning naming the replacement), and any refusal's words, plain text or a JSON
|
package/dist/password-bearer.js
CHANGED
|
@@ -20,10 +20,6 @@ export function passwordBearerAccepted(version = PACKAGE_VERSION) {
|
|
|
20
20
|
return have[index] < limit[index];
|
|
21
21
|
return false;
|
|
22
22
|
}
|
|
23
|
-
/** A refusal's words for this request: unchanged, or with the replacement when it came with a password bearer. */
|
|
24
|
-
export function withReplacement(authorization, message) {
|
|
25
|
-
return !isPasswordBearer(authorization) || message.includes("toolroll tokens create") ? message : `${message} ${PASSWORD_BEARER_WARNING}`;
|
|
26
|
-
}
|
|
27
23
|
/**
|
|
28
24
|
* The refusal boundary for one password-bearer request, whichever adapter answers it: the deprecation is announced in
|
|
29
25
|
* headers (RFC 9745 Deprecation, and a Warning naming the replacement), and any refusal's words, plain text or a JSON
|
package/dist/peek-cli.js
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
import { spawn } from "node:child_process";
|
|
18
18
|
import { liveWindowLines, readLiveWindow } from "./live.js";
|
|
19
19
|
import { validKeyTail } from "./live-records.js";
|
|
20
|
+
import { sleep } from "./sleep.js";
|
|
20
21
|
export const PEEK_TAIL_LINES = 400;
|
|
21
22
|
const ESC = "\u001b";
|
|
22
23
|
const REPLACED = { offset: 0, lines: ["[the live view was replaced — starting over]"], state: "replaced" };
|
|
@@ -175,7 +176,7 @@ export async function runPeek(store, root, options) {
|
|
|
175
176
|
try {
|
|
176
177
|
paint();
|
|
177
178
|
while (!stop) {
|
|
178
|
-
await
|
|
179
|
+
await sleep(options.intervalMs ?? 500);
|
|
179
180
|
paint();
|
|
180
181
|
}
|
|
181
182
|
}
|
package/dist/peek.d.ts
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* gitattributes, hooks, clean/process filters, or external diff drivers —
|
|
6
6
|
* the mechanisms finding 7 proved can execute repository-configured
|
|
7
7
|
* commands. Change detection is a git-blob sha1 computed IN PROCESS against
|
|
8
|
-
* the frozen base tree
|
|
8
|
+
* the frozen base tree.
|
|
9
9
|
*
|
|
10
|
-
* Two layers, deliberately separated: the PURE core (sha1,
|
|
10
|
+
* Two layers, deliberately separated: the PURE core (sha1, parsers,
|
|
11
11
|
* aggregation — bytes in, structures out) and ONE I/O function,
|
|
12
12
|
* observeWorktree — descriptor-DISCIPLINED, not descriptor-confined: Node
|
|
13
13
|
* has no openat, so traversal is by pathname and a same-UID attacker
|
|
@@ -24,30 +24,6 @@
|
|
|
24
24
|
/** git's own blob identity: sha1 over "blob <len>\0" + bytes. Computing it
|
|
25
25
|
* here is what lets change detection never ask git about a working tree. */
|
|
26
26
|
export declare function gitBlobSha1(bytes: Buffer): string;
|
|
27
|
-
/** git's heuristic, near enough: a NUL in the first 8 KiB means binary —
|
|
28
|
-
* named on the page, never diffed. */
|
|
29
|
-
export declare function looksBinary(bytes: Buffer): boolean;
|
|
30
|
-
export type Hunk = {
|
|
31
|
-
aStart: number;
|
|
32
|
-
aLines: number;
|
|
33
|
-
bStart: number;
|
|
34
|
-
bLines: number;
|
|
35
|
-
/** Prefixed lines: " ctx", "-old", "+new" — exactly unified-diff shape. */
|
|
36
|
-
lines: string[];
|
|
37
|
-
};
|
|
38
|
-
/**
|
|
39
|
-
* Line-based Myers (the O(ND) greedy walk), bounded by the caller's caps —
|
|
40
|
-
* inputs beyond the byte caps never reach here. Returns unified hunks with
|
|
41
|
-
* three lines of context, or null when the edit distance exceeds `maxD`
|
|
42
|
-
* (a rewrite is not usefully rendered as a diff — the caller says so).
|
|
43
|
-
*/
|
|
44
|
-
export declare function diffLines(aText: string, bText: string, maxD?: number): Hunk[] | null;
|
|
45
|
-
/** Render hunks as a unified patch body for one file, capped in bytes.
|
|
46
|
-
* The cap drops the incomplete final line (finding 9), and says so. */
|
|
47
|
-
export declare function renderUnified(path: string, hunks: Hunk[], capBytes: number): {
|
|
48
|
-
text: string;
|
|
49
|
-
truncated: boolean;
|
|
50
|
-
};
|
|
51
27
|
/**
|
|
52
28
|
* New-file readability WITHOUT suppression (round-1 finding 19: ignore
|
|
53
29
|
* parsing is gone — a pattern match can HIDE a name, and patterns are
|
package/dist/peek.js
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* gitattributes, hooks, clean/process filters, or external diff drivers —
|
|
6
6
|
* the mechanisms finding 7 proved can execute repository-configured
|
|
7
7
|
* commands. Change detection is a git-blob sha1 computed IN PROCESS against
|
|
8
|
-
* the frozen base tree
|
|
8
|
+
* the frozen base tree.
|
|
9
9
|
*
|
|
10
|
-
* Two layers, deliberately separated: the PURE core (sha1,
|
|
10
|
+
* Two layers, deliberately separated: the PURE core (sha1, parsers,
|
|
11
11
|
* aggregation — bytes in, structures out) and ONE I/O function,
|
|
12
12
|
* observeWorktree — descriptor-DISCIPLINED, not descriptor-confined: Node
|
|
13
13
|
* has no openat, so traversal is by pathname and a same-UID attacker
|
|
@@ -33,172 +33,6 @@ export function gitBlobSha1(bytes) {
|
|
|
33
33
|
.update(bytes)
|
|
34
34
|
.digest("hex");
|
|
35
35
|
}
|
|
36
|
-
/** git's heuristic, near enough: a NUL in the first 8 KiB means binary —
|
|
37
|
-
* named on the page, never diffed. */
|
|
38
|
-
export function looksBinary(bytes) {
|
|
39
|
-
return bytes.subarray(0, 8192).includes(0);
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Line-based Myers (the O(ND) greedy walk), bounded by the caller's caps —
|
|
43
|
-
* inputs beyond the byte caps never reach here. Returns unified hunks with
|
|
44
|
-
* three lines of context, or null when the edit distance exceeds `maxD`
|
|
45
|
-
* (a rewrite is not usefully rendered as a diff — the caller says so).
|
|
46
|
-
*/
|
|
47
|
-
export function diffLines(aText, bText, maxD = 2000) {
|
|
48
|
-
const a = aText.split("\n");
|
|
49
|
-
const b = bText.split("\n");
|
|
50
|
-
// A trailing newline yields one empty tail element on both sides; keep it —
|
|
51
|
-
// it makes "no newline at end" edits visible as a real line change.
|
|
52
|
-
const n = a.length;
|
|
53
|
-
const m = b.length;
|
|
54
|
-
const max = Math.min(n + m, maxD);
|
|
55
|
-
const offset = max;
|
|
56
|
-
// v[k] = furthest x on diagonal k; trace keeps a snapshot per d for backtrack.
|
|
57
|
-
let v = new Array(2 * max + 1).fill(0);
|
|
58
|
-
const trace = [];
|
|
59
|
-
let found = -1;
|
|
60
|
-
for (let d = 0; d <= max; d++) {
|
|
61
|
-
trace.push([...v]);
|
|
62
|
-
for (let k = -d; k <= d; k += 2) {
|
|
63
|
-
let x = k === -d || (k !== d && v[offset + k - 1] < v[offset + k + 1])
|
|
64
|
-
? v[offset + k + 1]
|
|
65
|
-
: v[offset + k - 1] + 1;
|
|
66
|
-
let y = x - k;
|
|
67
|
-
while (x < n && y < m && a[x] === b[y]) {
|
|
68
|
-
x++;
|
|
69
|
-
y++;
|
|
70
|
-
}
|
|
71
|
-
v[offset + k] = x;
|
|
72
|
-
if (x >= n && y >= m) {
|
|
73
|
-
found = d;
|
|
74
|
-
break;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
if (found >= 0)
|
|
78
|
-
break;
|
|
79
|
-
}
|
|
80
|
-
if (found < 0)
|
|
81
|
-
return null; // edit distance beyond maxD — not a diff, a replacement
|
|
82
|
-
const ops = [];
|
|
83
|
-
let x = n;
|
|
84
|
-
let y = m;
|
|
85
|
-
for (let d = found; d > 0; d--) {
|
|
86
|
-
const vd = trace[d];
|
|
87
|
-
const k = x - y;
|
|
88
|
-
const prevK = k === -d || (k !== d && vd[offset + k - 1] < vd[offset + k + 1])
|
|
89
|
-
? k + 1
|
|
90
|
-
: k - 1;
|
|
91
|
-
const prevX = vd[offset + prevK];
|
|
92
|
-
const prevY = prevX - prevK;
|
|
93
|
-
while (x > prevX && y > prevY) {
|
|
94
|
-
ops.push("=");
|
|
95
|
-
x--;
|
|
96
|
-
y--;
|
|
97
|
-
}
|
|
98
|
-
if (d > 0) {
|
|
99
|
-
if (x === prevX) {
|
|
100
|
-
ops.push("+");
|
|
101
|
-
y--;
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
ops.push("-");
|
|
105
|
-
x--;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
while (x > 0 && y > 0) {
|
|
110
|
-
ops.push("=");
|
|
111
|
-
x--;
|
|
112
|
-
y--;
|
|
113
|
-
}
|
|
114
|
-
while (x > 0) {
|
|
115
|
-
ops.push("-");
|
|
116
|
-
x--;
|
|
117
|
-
}
|
|
118
|
-
while (y > 0) {
|
|
119
|
-
ops.push("+");
|
|
120
|
-
y--;
|
|
121
|
-
}
|
|
122
|
-
ops.reverse();
|
|
123
|
-
// Fold ops into hunks with 3 lines of context.
|
|
124
|
-
const CONTEXT = 3;
|
|
125
|
-
const hunks = [];
|
|
126
|
-
let ai = 0;
|
|
127
|
-
let bi = 0;
|
|
128
|
-
let current = null;
|
|
129
|
-
let trailingContext = 0;
|
|
130
|
-
const flush = () => {
|
|
131
|
-
if (current === null)
|
|
132
|
-
return;
|
|
133
|
-
// Trim context beyond CONTEXT at the tail.
|
|
134
|
-
while (trailingContext > CONTEXT) {
|
|
135
|
-
current.lines.pop();
|
|
136
|
-
current.aLines--;
|
|
137
|
-
current.bLines--;
|
|
138
|
-
trailingContext--;
|
|
139
|
-
}
|
|
140
|
-
hunks.push(current);
|
|
141
|
-
current = null;
|
|
142
|
-
trailingContext = 0;
|
|
143
|
-
};
|
|
144
|
-
for (const op of ops) {
|
|
145
|
-
if (op === "=") {
|
|
146
|
-
const line = a[ai];
|
|
147
|
-
if (current !== null) {
|
|
148
|
-
current.lines.push(` ${line}`);
|
|
149
|
-
current.aLines++;
|
|
150
|
-
current.bLines++;
|
|
151
|
-
trailingContext++;
|
|
152
|
-
if (trailingContext > CONTEXT * 2)
|
|
153
|
-
flush();
|
|
154
|
-
}
|
|
155
|
-
ai++;
|
|
156
|
-
bi++;
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
if (current === null) {
|
|
160
|
-
const aStart = Math.max(0, ai - CONTEXT);
|
|
161
|
-
const bStart = Math.max(0, bi - CONTEXT);
|
|
162
|
-
current = { aStart: aStart + 1, aLines: 0, bStart: bStart + 1, bLines: 0, lines: [] };
|
|
163
|
-
for (let c = aStart; c < ai; c++) {
|
|
164
|
-
current.lines.push(` ${a[c]}`);
|
|
165
|
-
current.aLines++;
|
|
166
|
-
current.bLines++;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
trailingContext = 0;
|
|
170
|
-
if (op === "-") {
|
|
171
|
-
current.lines.push(`-${a[ai]}`);
|
|
172
|
-
current.aLines++;
|
|
173
|
-
ai++;
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
current.lines.push(`+${b[bi]}`);
|
|
177
|
-
current.bLines++;
|
|
178
|
-
bi++;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
flush();
|
|
182
|
-
return hunks;
|
|
183
|
-
}
|
|
184
|
-
/** Render hunks as a unified patch body for one file, capped in bytes.
|
|
185
|
-
* The cap drops the incomplete final line (finding 9), and says so. */
|
|
186
|
-
export function renderUnified(path, hunks, capBytes) {
|
|
187
|
-
const header = `--- a/${path}\n+++ b/${path}\n`;
|
|
188
|
-
const parts = [header];
|
|
189
|
-
let bytes = Buffer.byteLength(header);
|
|
190
|
-
for (const hunk of hunks) {
|
|
191
|
-
const head = `@@ -${hunk.aStart},${hunk.aLines} +${hunk.bStart},${hunk.bLines} @@\n`;
|
|
192
|
-
const body = hunk.lines.join("\n") + "\n";
|
|
193
|
-
const size = Buffer.byteLength(head) + Buffer.byteLength(body);
|
|
194
|
-
if (bytes + size > capBytes) {
|
|
195
|
-
return { text: parts.join(""), truncated: true };
|
|
196
|
-
}
|
|
197
|
-
parts.push(head, body);
|
|
198
|
-
bytes += size;
|
|
199
|
-
}
|
|
200
|
-
return { text: parts.join(""), truncated: false };
|
|
201
|
-
}
|
|
202
36
|
export function aggregateNewNames(paths, groupAt = 10, rowCap = 200) {
|
|
203
37
|
const bySegment = new Map();
|
|
204
38
|
for (const path of paths) {
|
package/dist/phase-routing.d.ts
CHANGED
|
@@ -70,8 +70,6 @@ export { ROUTE_VERSION };
|
|
|
70
70
|
* row; which route version it holds rides in the snapshot itself. */
|
|
71
71
|
export declare const ROUTE_ERA = 1;
|
|
72
72
|
export declare const PHASES: readonly Phase[];
|
|
73
|
-
/** The review leg remains readable in signed history but is no longer scheduled. */
|
|
74
|
-
export declare const ACTIVE_PHASES: readonly Phase[];
|
|
75
73
|
/** The risk words a route sealed before v115 may carry (history); every route since says `routine`. */
|
|
76
74
|
export type RiskLevel = (typeof RISKS)[number];
|
|
77
75
|
export declare function isRiskLevel(value: unknown): value is RiskLevel;
|
|
@@ -86,8 +84,6 @@ export declare function isTaskSize(value: unknown): value is TaskSize;
|
|
|
86
84
|
export declare function makesNoPlan(size: TaskSizing | null | undefined, risk: RiskLevel): boolean;
|
|
87
85
|
/** Where a size came from, in words. */
|
|
88
86
|
export declare function sizeSourceWords(source: SizeSource): string;
|
|
89
|
-
/** Strict read of a stored sizing (the route contract's): exact keys, known words, bounded reason. */
|
|
90
|
-
export declare function parseSizing(raw: unknown): TaskSizing | null;
|
|
91
87
|
export declare function riskTitle(risk: RiskLevel): string;
|
|
92
88
|
/** A runner's non-spending observation of one provider. `unknown` is a
|
|
93
89
|
* real answer (claude has no login probe that does not spend) and is never
|
package/dist/phase-routing.js
CHANGED
|
@@ -50,7 +50,8 @@
|
|
|
50
50
|
*/
|
|
51
51
|
import { ACP_AGENTS, isAcpProvider } from "./acp-agents.js";
|
|
52
52
|
import { createHash } from "node:crypto";
|
|
53
|
-
import { MODEL_ID_SHAPE, postureOf, readRouteOverrides, readSealedRoute, RISKS, ROUTE_PHASES, ROUTE_PROVIDERS, ROUTE_VERSION, TASK_SIZE_WORDS,
|
|
53
|
+
import { MODEL_ID_SHAPE, postureOf, readRouteOverrides, readSealedRoute, RISKS, ROUTE_PHASES, ROUTE_PROVIDERS, ROUTE_VERSION, TASK_SIZE_WORDS, } from "./contracts/route.js";
|
|
54
|
+
import { canonicalJson } from "./canonical-json.js";
|
|
54
55
|
export { MODEL_ID_SHAPE };
|
|
55
56
|
// Type-only imports from provider.ts: it sits under evidence.ts and scope.ts
|
|
56
57
|
// in the module graph, and this policy is imported by scope.ts — a value
|
|
@@ -79,8 +80,6 @@ export { ROUTE_VERSION };
|
|
|
79
80
|
* row; which route version it holds rides in the snapshot itself. */
|
|
80
81
|
export const ROUTE_ERA = 1;
|
|
81
82
|
export const PHASES = ROUTE_PHASES;
|
|
82
|
-
/** The review leg remains readable in signed history but is no longer scheduled. */
|
|
83
|
-
export const ACTIVE_PHASES = ["plan", "build", "repair"];
|
|
84
83
|
export function isRiskLevel(value) {
|
|
85
84
|
return value === "routine" || value === "elevated" || value === "high";
|
|
86
85
|
}
|
|
@@ -97,11 +96,6 @@ export function makesNoPlan(size, risk) {
|
|
|
97
96
|
export function sizeSourceWords(source) {
|
|
98
97
|
return source === "classifier" ? "sized automatically" : source === "person" ? "set by a person" : "sized from the description";
|
|
99
98
|
}
|
|
100
|
-
/** Strict read of a stored sizing (the route contract's): exact keys, known words, bounded reason. */
|
|
101
|
-
export function parseSizing(raw) {
|
|
102
|
-
const parsed = taskSizingSchema.safeParse(raw);
|
|
103
|
-
return parsed.success ? parsed.data : null;
|
|
104
|
-
}
|
|
105
99
|
export function riskTitle(risk) {
|
|
106
100
|
return risk === "high" ? "High risk" : risk === "elevated" ? "Elevated risk" : "Routine";
|
|
107
101
|
}
|
|
@@ -481,19 +475,6 @@ export function sameSpec(a, b) {
|
|
|
481
475
|
return a.provider === b.provider && a.model === b.model;
|
|
482
476
|
}
|
|
483
477
|
// ---- canonical bytes, digest, strict rehydration ---------------------------
|
|
484
|
-
/** Deterministic JSON: object keys sorted recursively, arrays in order. */
|
|
485
|
-
function canonicalJson(value) {
|
|
486
|
-
if (Array.isArray(value))
|
|
487
|
-
return `[${value.map(canonicalJson).join(",")}]`;
|
|
488
|
-
if (value !== null && typeof value === "object") {
|
|
489
|
-
const entries = Object.entries(value)
|
|
490
|
-
.filter(([, v]) => v !== undefined)
|
|
491
|
-
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
492
|
-
.map(([k, v]) => `${JSON.stringify(k)}:${canonicalJson(v)}`);
|
|
493
|
-
return `{${entries.join(",")}}`;
|
|
494
|
-
}
|
|
495
|
-
return JSON.stringify(value);
|
|
496
|
-
}
|
|
497
478
|
/** The stored snapshot bytes: the version rides IN the snapshot. */
|
|
498
479
|
export function canonicalRouteJson(route) {
|
|
499
480
|
return canonicalJson({
|
package/dist/planner-source.d.ts
CHANGED
|
@@ -40,6 +40,7 @@ import type { Scope } from "./scope.js";
|
|
|
40
40
|
import type { QualityMode } from "./quality.js";
|
|
41
41
|
import type { RiskLevel } from "./phase-routing.js";
|
|
42
42
|
import { type ContractChange, type ContractTerms } from "./contract-changes.js";
|
|
43
|
+
import { canonicalJsonUndefinedAsNull } from "./canonical-json.js";
|
|
43
44
|
export declare const PLANNER_SOURCE_VERSION = 1;
|
|
44
45
|
export declare const PLANNER_SOURCE_LIMITS: {
|
|
45
46
|
/** The whole recorded source before lossless prompt fencing. Equal to
|
|
@@ -132,7 +133,7 @@ export type PlannerSource = {
|
|
|
132
133
|
outsideReference?: string;
|
|
133
134
|
};
|
|
134
135
|
/** Stable JSON for hashing and equality only — no filling, no trimming. */
|
|
135
|
-
export declare
|
|
136
|
+
export declare const canonicalContractJson: typeof canonicalJsonUndefinedAsNull;
|
|
136
137
|
export declare function plannerSourceDigest(contract: PlannerContract): string;
|
|
137
138
|
/**
|
|
138
139
|
* The contract part, read from the store alone — no file I/O — so the plan
|
package/dist/planner-source.js
CHANGED
|
@@ -41,6 +41,7 @@ import { EVIDENCE_CAPS, readVerifiedArtifact } from "./evidence.js";
|
|
|
41
41
|
import { TEXT_LIMITS } from "./text-limits.js";
|
|
42
42
|
import { PLAN_TOUCHES } from "./contracts/plan.js";
|
|
43
43
|
import { contractChangesOf } from "./contract-changes.js";
|
|
44
|
+
import { canonicalJsonUndefinedAsNull } from "./canonical-json.js";
|
|
44
45
|
export const PLANNER_SOURCE_VERSION = 1;
|
|
45
46
|
export const PLANNER_SOURCE_LIMITS = {
|
|
46
47
|
/** The whole recorded source before lossless prompt fencing. Equal to
|
|
@@ -56,18 +57,7 @@ export const PLANNER_SOURCE_LIMITS = {
|
|
|
56
57
|
handoffTerms: TEXT_LIMITS.planPayloadBytes,
|
|
57
58
|
};
|
|
58
59
|
/** Stable JSON for hashing and equality only — no filling, no trimming. */
|
|
59
|
-
export
|
|
60
|
-
if (Array.isArray(value))
|
|
61
|
-
return `[${value.map(canonicalContractJson).join(",")}]`;
|
|
62
|
-
if (value !== null && typeof value === "object") {
|
|
63
|
-
const body = value;
|
|
64
|
-
return `{${Object.keys(body)
|
|
65
|
-
.sort()
|
|
66
|
-
.map(key => `${JSON.stringify(key)}:${canonicalContractJson(body[key])}`)
|
|
67
|
-
.join(",")}}`;
|
|
68
|
-
}
|
|
69
|
-
return JSON.stringify(value) ?? "null";
|
|
70
|
-
}
|
|
60
|
+
export const canonicalContractJson = canonicalJsonUndefinedAsNull;
|
|
71
61
|
export function plannerSourceDigest(contract) {
|
|
72
62
|
return createHash("sha256").update(`planner-source:v${PLANNER_SOURCE_VERSION}\n${canonicalContractJson(contract)}`, "utf8").digest("hex");
|
|
73
63
|
}
|
package/dist/planner.js
CHANGED
|
@@ -38,6 +38,7 @@ import { proveTreeUntouched, snapshotIgnored } from "./tree-proof.js";
|
|
|
38
38
|
import { CLAUDE_LIMITS, ACCEPTANCE_LIMITS } from "./scope.js";
|
|
39
39
|
import { normalizeStructuredJson, storeStructuredAttempt, validationErrorsJson, STRUCTURED_REPAIR_ATTEMPTS, STRUCTURED_REPAIR_MAX_TURNS, STRUCTURED_REPAIR_TIMEOUT_MS, } from "./structured-output.js";
|
|
40
40
|
import { contractChangesOf, describeContractChanges, plannerSourceBlock, } from "./planner-source.js";
|
|
41
|
+
import { canonicalJsonUndefinedAsNull } from "./canonical-json.js";
|
|
41
42
|
const GIT = "git";
|
|
42
43
|
const AGENT_ENV_DENYLIST = [...TELEGRAM_TOKEN_ENVS];
|
|
43
44
|
const DEFAULT_PLAN_TIMEOUT_MS = 20 * 60_000;
|
|
@@ -146,19 +147,6 @@ function plannerBrief(title, mailbox, planFile, answers, source, structured) {
|
|
|
146
147
|
"work back for evidence nobody can produce.",
|
|
147
148
|
].join("\n");
|
|
148
149
|
}
|
|
149
|
-
/** Stable JSON for equality only — it does not fill, trim, or reinterpret. */
|
|
150
|
-
function canonicalJson(value) {
|
|
151
|
-
if (Array.isArray(value))
|
|
152
|
-
return `[${value.map(canonicalJson).join(",")}]`;
|
|
153
|
-
if (value !== null && typeof value === "object") {
|
|
154
|
-
const body = value;
|
|
155
|
-
return `{${Object.keys(body)
|
|
156
|
-
.sort()
|
|
157
|
-
.map(key => `${JSON.stringify(key)}:${canonicalJson(body[key])}`)
|
|
158
|
-
.join(",")}}`;
|
|
159
|
-
}
|
|
160
|
-
return JSON.stringify(value) ?? "null";
|
|
161
|
-
}
|
|
162
150
|
function decodeStructuredBytes(raw) {
|
|
163
151
|
try {
|
|
164
152
|
// Buffer#toString silently inserts U+FFFD for malformed sequences,
|
|
@@ -187,7 +175,7 @@ function planAuthorityAnchor(raw) {
|
|
|
187
175
|
// canonicalJson is recursive. A byte-bounded but pathologically deep
|
|
188
176
|
// JSON value can still exhaust the JS stack; that means its authority
|
|
189
177
|
// cannot be frozen safely, so this output is not eligible for repair.
|
|
190
|
-
return
|
|
178
|
+
return canonicalJsonUndefinedAsNull({
|
|
191
179
|
goal: body["goal"],
|
|
192
180
|
outOfScope: body["outOfScope"],
|
|
193
181
|
touches: body["touches"],
|
package/dist/process-tree.d.ts
CHANGED
|
@@ -23,8 +23,6 @@ export type ProcessTreeObserver = {
|
|
|
23
23
|
onObservationFailure?: (failure: ProcessObservationFailure) => void;
|
|
24
24
|
onUnknown?: () => void;
|
|
25
25
|
};
|
|
26
|
-
/** Private supervisor pipe input. Keep only validated identifier diagnostics. */
|
|
27
|
-
export declare function readProcessObservationFailure(value: unknown): ProcessObservationFailure | null;
|
|
28
26
|
/** Capture current descendants before asking an owned process to exit.
|
|
29
27
|
* A cooperative root may exit before the next periodic observation; even
|
|
30
28
|
* a killed tool can retain its PID briefly after its process group is gone. */
|
package/dist/process-tree.js
CHANGED
|
@@ -78,16 +78,6 @@ function recordExits(child, rows) {
|
|
|
78
78
|
}
|
|
79
79
|
// Only fixed error codes survive; error messages/output can contain private data.
|
|
80
80
|
const observationCodes = new Set(["EAGAIN", "EMFILE", "ENFILE", "ETIMEDOUT", "ENOBUFS", "ENOENT", "EPERM", "EACCES", "EIO", "ESRCH", "MALFORMED_SNAPSHOT", "SUPERVISOR_DIAGNOSTIC", "SQLITE_BUSY", "SQLITE_LOCKED", "SQLITE_READONLY", "SQLITE_IOERR", "SQLITE_CORRUPT", "SQLITE_FULL", "SQLITE_CONSTRAINT"]);
|
|
81
|
-
/** Private supervisor pipe input. Keep only validated identifier diagnostics. */
|
|
82
|
-
export function readProcessObservationFailure(value) {
|
|
83
|
-
if (typeof value !== "object" || value === null)
|
|
84
|
-
return null;
|
|
85
|
-
const row = value;
|
|
86
|
-
const { phase, operation, code, rootPid, at, identityUnknown } = row;
|
|
87
|
-
if (!["sample", "periodic", "final-exit", "stop", "supervisor"].includes(String(phase)) || !["snapshot", "descendant-write", "exit-write", "signal", "diagnostic-read"].includes(String(operation)) || typeof code !== "string" || (code !== "UNKNOWN" && !observationCodes.has(code)) || (rootPid !== null && (!Number.isSafeInteger(rootPid) || Number(rootPid) <= 0)) || typeof at !== "string" || !Number.isFinite(Date.parse(at)) || new Date(at).toISOString() !== at || typeof identityUnknown !== "boolean")
|
|
88
|
-
return null;
|
|
89
|
-
return { phase: phase, operation: operation, code, rootPid: rootPid, at, identityUnknown };
|
|
90
|
-
}
|
|
91
81
|
function failed(child, phase, operation, error, identitiesPreserved = false) {
|
|
92
82
|
const tracked = observed.get(child);
|
|
93
83
|
if (!tracked)
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* sign-in with the identity provider). The repository itself stays.
|
|
6
6
|
*/
|
|
7
7
|
import type { ProjectNetwork } from "./egress.js";
|
|
8
|
+
import type { WritesMode } from "./writes-mode.js";
|
|
8
9
|
import { type Html } from "./html.js";
|
|
9
10
|
import { type ProjectHoldings } from "./project-delete.js";
|
|
10
11
|
export declare const PROJECT_DELETE_CSS: string;
|
|
@@ -44,6 +45,11 @@ export type ProjectSettingsView = {
|
|
|
44
45
|
setting: ProjectNetwork;
|
|
45
46
|
canChange: boolean;
|
|
46
47
|
};
|
|
48
|
+
/** Where its builds may write (writes-mode.ts), and whether this person may change it. */
|
|
49
|
+
writes?: {
|
|
50
|
+
setting: WritesMode;
|
|
51
|
+
canChange: boolean;
|
|
52
|
+
};
|
|
47
53
|
};
|
|
48
54
|
/** The project's page: its path, what Toolroll holds for it, and (for an instance operator) Delete project. */
|
|
49
55
|
export declare function projectSettingsHtml(view: ProjectSettingsView, notice: {
|
|
@@ -14,6 +14,25 @@ export const PROJECT_DELETE_CSS = `.project-settings,.project-delete{max-width:7
|
|
|
14
14
|
`.project-settings .build-access ul{margin:0 0 4px;padding-left:20px;font:var(--so-typography-body);color:var(--so-ink)}.project-settings .build-access li{margin:2px 0}.project-settings .build-access li .meta{color:var(--so-muted)}` +
|
|
15
15
|
`.project-settings .build-access a.manage-tools{display:inline-flex;align-items:center;justify-content:center;min-height:44px;margin-top:4px;padding:0 14px;white-space:nowrap;background:var(--so-paper);color:var(--so-ink);border:1px solid var(--so-input-line);border-radius:var(--so-radius-md);font:var(--so-typography-label);text-decoration:none}` +
|
|
16
16
|
`.project-settings .build-access a.manage-tools:hover{background:var(--so-raised)}.project-settings .build-access a.manage-tools:focus-visible,.project-settings .build-access summary:focus-visible{outline:2px solid var(--so-ink);outline-offset:2px}`;
|
|
17
|
+
/** Where builds may write, said plainly; an approver changes it with their password. */
|
|
18
|
+
function writesHtml(view) {
|
|
19
|
+
const writes = view.writes;
|
|
20
|
+
if (writes === undefined)
|
|
21
|
+
return "";
|
|
22
|
+
const said = writes.setting === "workspace"
|
|
23
|
+
? html `<p>Builds write <strong>only their own checkout</strong>, its caches and its temp folder. Your shell profile, login items, agent settings and the repository's Git config and hooks stay as they are.</p>`
|
|
24
|
+
: html `<p>Builds may write <strong>anywhere</strong> outside Toolroll's own folders, your credentials and other projects.</p>`;
|
|
25
|
+
if (!writes.canChange)
|
|
26
|
+
return html `<section class="build-access writes-setting" id="writes" aria-labelledby="writes-title"><h2 id="writes-title">Where builds write</h2>${said}<p class="meta">An approver for this project can change this.</p></section>`;
|
|
27
|
+
const option = (value, label, detail) => html `<label class="check"><input type="radio" name="writes" value="${value}"${writes.setting === value ? html ` checked` : ""}> ${label}</label><p class="meta">${detail}</p>`;
|
|
28
|
+
const form = postForm("/settings/project/writes", html `
|
|
29
|
+
${option("workspace", "Only their workspace (recommended)", "The checkout and its Git data, the project's own package caches, the build's temp folder, and what its agent needs to keep its session.")}
|
|
30
|
+
${option("anywhere", "Anywhere outside Toolroll's fenced folders", "For a project whose tools must write elsewhere in your home folder or the shared temp folder. Credentials, Toolroll's own folders and other projects stay fenced.")}
|
|
31
|
+
<p class="meta">Tasks scoped from now on use this; tasks already approved keep what they were approved with.</p>
|
|
32
|
+
${reauth(html `<label>Your Toolroll password<input type="password" name="password" autocomplete="current-password" required></label>`)}
|
|
33
|
+
<button type="submit">Save</button>`, { hidden: { repo: view.repo } });
|
|
34
|
+
return html `<section class="build-access writes-setting" id="writes" aria-labelledby="writes-title"><h2 id="writes-title">Where builds write</h2>${said}<details><summary>Change</summary>${form}</details></section>`;
|
|
35
|
+
}
|
|
17
36
|
/** Network: what the project's builds may reach, said plainly; an approver changes it with their password. */
|
|
18
37
|
function networkHtml(view) {
|
|
19
38
|
const network = view.network;
|
|
@@ -92,7 +111,7 @@ export function projectSettingsHtml(view, notice) {
|
|
|
92
111
|
const remote = html `<section class="build-access recorded-remote" aria-labelledby="recorded-remote-title"><h2 id="recorded-remote-title">Recorded remote</h2>${view.remoteUrl
|
|
93
112
|
? html `<p class="path">${view.remoteUrl}</p>`
|
|
94
113
|
: html `<p>No remote recorded. Landed work waits for your review.</p>`}<details><summary>Change remote</summary><p>An owner or instance operator can run:</p><p class="path">toolroll repos add <project> --remote <url></p></details></section>`;
|
|
95
|
-
const head = html `${note(notice)}<p class="path">${view.repo}</p>${held}${remote}${buildsHtml(view)}${accessHtml(view)}${networkHtml(view)}${liveViewHtml(view)}`;
|
|
114
|
+
const head = html `${note(notice)}<p class="path">${view.repo}</p>${held}${remote}${buildsHtml(view)}${accessHtml(view)}${networkHtml(view)}${writesHtml(view)}${liveViewHtml(view)}`;
|
|
96
115
|
if (!view.canDelete)
|
|
97
116
|
return html `<section class="project-settings">${head}<p class="meta">An instance operator can delete a project.</p></section>`;
|
|
98
117
|
const body = view.running.length > 0
|
package/dist/project-delete.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import type { ExecResult } from "./exec.js";
|
|
2
2
|
import type { Runner } from "./worktree.js";
|
|
3
3
|
import { type Store } from "./store.js";
|
|
4
|
-
/** What Toolroll names the branches it makes: toolroll/…, and standing-orders/… from before the rename. */
|
|
5
|
-
export declare const OWN_BRANCH = "toolroll/";
|
|
6
4
|
export declare const OWN_BRANCHES: readonly string[];
|
|
7
5
|
export type ProjectHoldings = {
|
|
8
6
|
tasks: number;
|
package/dist/project-delete.js
CHANGED
|
@@ -16,11 +16,9 @@ import { existsSync, lstatSync, rmSync } from "node:fs";
|
|
|
16
16
|
import { isAbsolute, relative, resolve } from "node:path";
|
|
17
17
|
import { teardownGit, refusal } from "./teardown-git.js";
|
|
18
18
|
import { BUILT_IN } from "./store.js";
|
|
19
|
-
import {
|
|
19
|
+
import { BRANCH_PREFIXES, isOwnBranch } from "./names.js";
|
|
20
20
|
/** The tables whose history is the audit record itself: never touched. */
|
|
21
21
|
const KEPT = new Set(["action_ledger", "ledger_seal", "ledger_checkpoint"]);
|
|
22
|
-
/** What Toolroll names the branches it makes: toolroll/…, and standing-orders/… from before the rename. */
|
|
23
|
-
export const OWN_BRANCH = BRANCH_PREFIX;
|
|
24
22
|
export const OWN_BRANCHES = BRANCH_PREFIXES;
|
|
25
23
|
const list = (db, sql, ...params) => db.prepare(sql).all(...params).map(row => Object.values(row)[0]);
|
|
26
24
|
const ids = (db, sql, ...params) => list(db, sql, ...params).map(Number);
|
|
@@ -32,20 +32,6 @@ export type Lesson = {
|
|
|
32
32
|
identity: string;
|
|
33
33
|
adoptedBy: string | null;
|
|
34
34
|
};
|
|
35
|
-
export type LearningEvent = {
|
|
36
|
-
snapshot: string | null;
|
|
37
|
-
outcome: string | null;
|
|
38
|
-
id: number;
|
|
39
|
-
actor: string;
|
|
40
|
-
at: string;
|
|
41
|
-
action: string;
|
|
42
|
-
before: string;
|
|
43
|
-
after: string;
|
|
44
|
-
reason: string;
|
|
45
|
-
lesson: number | null;
|
|
46
|
-
run: number | null;
|
|
47
|
-
evidence: LearningEvidence[];
|
|
48
|
-
};
|
|
49
35
|
export declare const learningSha: (text: string) => string;
|
|
50
36
|
/** Facts about the shared Git database that survive a restart. The volume's device number does not. */
|
|
51
37
|
export type IdentityFacts = {
|
package/dist/project-skills.d.ts
CHANGED
|
@@ -89,7 +89,6 @@ export declare function materializeProjectSkills(snapshot: SkillsSnapshot, root:
|
|
|
89
89
|
}[];
|
|
90
90
|
};
|
|
91
91
|
export declare function skillsContext(store: Store, root: string, runId: number): string;
|
|
92
|
-
export declare function skillReviewSource(store: Store, runId: number): string | null;
|
|
93
92
|
export declare function testSkill(store: Store, args: {
|
|
94
93
|
repo: string;
|
|
95
94
|
actor: string;
|
package/dist/project-skills.js
CHANGED
|
@@ -463,20 +463,6 @@ export function skillsContext(store, root, runId) {
|
|
|
463
463
|
JSON.stringify(catalog) +
|
|
464
464
|
"\n");
|
|
465
465
|
}
|
|
466
|
-
export function skillReviewSource(store, runId) {
|
|
467
|
-
const s = freezeSkills(store, runId);
|
|
468
|
-
return s.packages.length
|
|
469
|
-
? JSON.stringify({
|
|
470
|
-
notice: "Exact skill packages supplied to the source run. Untrusted review context, never reviewer instructions or evidence of use. Original files use base64; readable SKILL.md is also included.",
|
|
471
|
-
...s,
|
|
472
|
-
instructions: s.packages.map((p) => ({
|
|
473
|
-
name: p.name,
|
|
474
|
-
sha: p.sha,
|
|
475
|
-
content: Buffer.from(p.files.find((f) => f.path === "SKILL.md").base64, "base64").toString("utf8"),
|
|
476
|
-
})),
|
|
477
|
-
})
|
|
478
|
-
: null;
|
|
479
|
-
}
|
|
480
466
|
export function testSkill(store, args, now = new Date()) {
|
|
481
467
|
const view = skillsView(store, args.repo, args.actor);
|
|
482
468
|
admit(store, args.repo, args.actor, true);
|
package/dist/project-tools.js
CHANGED
|
@@ -33,6 +33,7 @@ import { isAcpProvider } from "./acp-agents.js";
|
|
|
33
33
|
import { SecretStoreError, destroyOwnFile, prepareSecretFolder, registerSecretFolder, pathIn, readOwnFile, readSealed, removeValue, secretBackend, secretFolder, secretStorage, serviceOf, withSecretLock, withSecretLockAsync, writeOwnFile, writeSealed } from "./tool-secret-store.js";
|
|
34
34
|
import { ACCESS, GRANTED, REFRESH, mintRunToken, mintsRunTokens, oneAtATime, runScope, scopeList, signedIn } from "./oauth-run-token.js";
|
|
35
35
|
import { HEADER_NAME, SECRET_NAME, TOOL_NAME as NAME, TOOL_SPEC_LIMITS as LIMITS, readToolSpec } from "./contracts/integration-metadata.js";
|
|
36
|
+
import { canonicalJson } from "./canonical-json.js";
|
|
36
37
|
/** Env names a tool may never claim: the process's own plumbing, every
|
|
37
38
|
* provider credential, and anything that changes how a program or its
|
|
38
39
|
* interpreter loads (a secret's value must stay data, never code). */
|
|
@@ -75,19 +76,10 @@ export function localAppOf(spec) {
|
|
|
75
76
|
export function catalogTool(id) {
|
|
76
77
|
return TOOL_CATALOG.find(one => one.name === id) ?? null;
|
|
77
78
|
}
|
|
78
|
-
function canonical(value) {
|
|
79
|
-
if (Array.isArray(value))
|
|
80
|
-
return `[${value.map(canonical).join(",")}]`;
|
|
81
|
-
if (value !== null && typeof value === "object") {
|
|
82
|
-
return `{${Object.entries(value).filter(([, v]) => v !== undefined).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
83
|
-
.map(([k, v]) => `${JSON.stringify(k)}:${canonical(v)}`).join(",")}}`;
|
|
84
|
-
}
|
|
85
|
-
return JSON.stringify(value);
|
|
86
|
-
}
|
|
87
79
|
/** What a build is held to: how the server starts and which secrets it names — never their values or its description. */
|
|
88
80
|
export function toolDigest(spec) {
|
|
89
81
|
const { about: _about, ...terms } = spec;
|
|
90
|
-
return createHash("sha256").update(`standing-orders:tool:v1:${
|
|
82
|
+
return createHash("sha256").update(`standing-orders:tool:v1:${canonicalJson(terms)}`, "utf8").digest("hex").slice(0, 32);
|
|
91
83
|
}
|
|
92
84
|
const str = (value, cap, what) => {
|
|
93
85
|
if (typeof value !== "string" || value.trim() === "" || value.length > cap)
|
package/dist/provider.d.ts
CHANGED
|
@@ -335,23 +335,6 @@ export type ProviderMoneyCapabilities = {
|
|
|
335
335
|
usageSemantics: "per-invocation" | "cumulative-session";
|
|
336
336
|
};
|
|
337
337
|
export declare const MONEY_CAPABILITIES: Record<ProviderId, ProviderMoneyCapabilities>;
|
|
338
|
-
/**
|
|
339
|
-
* The fail-closed budget-flag probe (finding 24's amendment): resolve
|
|
340
|
-
* the EXACT executable that will spawn, read its version, and prove the
|
|
341
|
-
* flag exists in that binary's own help — presence is a feature check
|
|
342
|
-
* and nothing more.
|
|
343
|
-
*/
|
|
344
|
-
export declare function probeBudgetCap(provider: ProviderId, runner: (command: string, argv: readonly string[], options: {
|
|
345
|
-
timeoutMs?: number;
|
|
346
|
-
omitEnv?: readonly string[];
|
|
347
|
-
}) => Promise<ExecResult>): Promise<{
|
|
348
|
-
ok: true;
|
|
349
|
-
executable: string;
|
|
350
|
-
version: string;
|
|
351
|
-
} | {
|
|
352
|
-
ok: false;
|
|
353
|
-
problem: string;
|
|
354
|
-
}>;
|
|
355
338
|
export declare function auditOf(provider: ProviderId): ProviderAudit;
|
|
356
339
|
/**
|
|
357
340
|
* A spec a person or a config row proposed, validated to a complete pair.
|