toolroll 0.9.36 → 0.9.37
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 +58 -0
- package/dist/assignment-adapters.d.ts +12 -48
- package/dist/assignment-adapters.js +33 -43
- package/dist/build-review.d.ts +1 -1
- package/dist/build-review.js +2 -1
- package/dist/chat-acceptance.d.ts +1 -1
- package/dist/chat-actions.d.ts +18 -12
- package/dist/chat-actions.js +15 -65
- package/dist/chat-ask.js +5 -5
- package/dist/chat-decide.d.ts +14 -1
- package/dist/chat-decide.js +12 -6
- package/dist/chat-delivery-state.d.ts +12 -70
- package/dist/chat-delivery-state.js +17 -135
- package/dist/chat-delivery.js +58 -30
- package/dist/chat-flow.js +8 -6
- package/dist/chat-inbox.js +1 -1
- package/dist/coding-context.d.ts +2 -39
- package/dist/coding-context.js +2 -1
- package/dist/coding-handoff.d.ts +6 -25
- package/dist/coding-handoff.js +11 -5
- package/dist/coding-types.d.ts +2 -26
- package/dist/coding-workspace.d.ts +2 -0
- package/dist/coding-workspace.js +50 -14
- package/dist/contracts/acceptance-terms.d.ts +14 -0
- package/dist/contracts/acceptance-terms.js +16 -0
- package/dist/contracts/chat-actions.d.ts +328 -0
- package/dist/contracts/chat-actions.js +133 -0
- package/dist/contracts/chat-callback-rows.d.ts +59 -0
- package/dist/contracts/chat-callback-rows.js +46 -0
- package/dist/contracts/chat-content.d.ts +276 -0
- package/dist/contracts/chat-content.js +127 -0
- package/dist/contracts/chat-tables.d.ts +6 -0
- package/dist/contracts/chat-tables.js +136 -0
- package/dist/contracts/coding-context.d.ts +97 -0
- package/dist/contracts/coding-context.js +60 -0
- package/dist/contracts/coding-handoff.d.ts +44 -0
- package/dist/contracts/coding-handoff.js +47 -0
- package/dist/contracts/coding-workspace.d.ts +165 -0
- package/dist/contracts/coding-workspace.js +71 -0
- package/dist/contracts/contract.d.ts +7 -2
- package/dist/contracts/contract.js +21 -12
- package/dist/contracts/decision.d.ts +45 -0
- package/dist/contracts/decision.js +45 -0
- package/dist/contracts/discord-callback.d.ts +45 -0
- package/dist/contracts/discord-callback.js +34 -0
- package/dist/contracts/flow-card.d.ts +50 -0
- package/dist/contracts/flow-card.js +46 -0
- package/dist/contracts/flow-send.d.ts +119 -0
- package/dist/contracts/flow-send.js +112 -0
- package/dist/contracts/flow.d.ts +5 -0
- package/dist/contracts/flow.js +5 -0
- package/dist/contracts/gateway-tools.d.ts +374 -0
- package/dist/contracts/gateway-tools.js +94 -0
- package/dist/contracts/lead-context.d.ts +165 -0
- package/dist/contracts/lead-context.js +73 -0
- package/dist/contracts/lead-tools.d.ts +1905 -0
- package/dist/contracts/lead-tools.js +265 -0
- package/dist/contracts/memory-pass.d.ts +158 -0
- package/dist/contracts/memory-pass.js +102 -0
- package/dist/contracts/project-knowledge.d.ts +126 -0
- package/dist/contracts/project-knowledge.js +93 -0
- package/dist/contracts/project-memory.d.ts +117 -0
- package/dist/contracts/project-memory.js +51 -0
- package/dist/contracts/project-skills.d.ts +121 -0
- package/dist/contracts/project-skills.js +76 -0
- package/dist/contracts/review-findings.d.ts +46 -0
- package/dist/contracts/review-findings.js +48 -0
- package/dist/contracts/route.d.ts +484 -0
- package/dist/contracts/route.js +128 -0
- package/dist/contracts/scope.d.ts +105 -0
- package/dist/contracts/scope.js +114 -0
- package/dist/contracts/scout-report.d.ts +234 -0
- package/dist/contracts/scout-report.js +141 -0
- package/dist/contracts/slack-callback.d.ts +43 -0
- package/dist/contracts/slack-callback.js +35 -0
- package/dist/contracts/sort-answer.d.ts +83 -0
- package/dist/contracts/sort-answer.js +77 -0
- package/dist/contracts/stage-output.d.ts +127 -0
- package/dist/contracts/stage-output.js +166 -0
- package/dist/contracts/task-sizing.d.ts +24 -0
- package/dist/contracts/task-sizing.js +28 -0
- package/dist/contracts/teammate-turn.d.ts +43 -0
- package/dist/contracts/teammate-turn.js +51 -0
- package/dist/contracts/teams-callback.d.ts +14 -0
- package/dist/contracts/teams-callback.js +14 -0
- package/dist/contracts/telegram-callback.d.ts +120 -0
- package/dist/contracts/telegram-callback.js +97 -0
- package/dist/decision.d.ts +11 -20
- package/dist/decision.js +86 -167
- package/dist/desktop-update.d.ts +2 -2
- package/dist/discord-chat.js +31 -20
- package/dist/flow-engine.js +14 -17
- package/dist/flow-items.d.ts +4 -13
- package/dist/flow-items.js +1 -15
- package/dist/flow-send.d.ts +6 -37
- package/dist/flow-send.js +18 -14
- package/dist/flow-share.js +7 -1
- package/dist/flow-sort.d.ts +7 -26
- package/dist/flow-sort.js +25 -20
- package/dist/flow-steps.js +3 -2
- package/dist/flows.d.ts +2 -4
- package/dist/flows.js +9 -5
- package/dist/invoke.js +4 -4
- package/dist/lead-context.d.ts +4 -2
- package/dist/lead-context.js +24 -17
- package/dist/mate-tools.d.ts +4 -0
- package/dist/mate-tools.js +108 -275
- package/dist/mcp-connect.d.ts +24 -4
- package/dist/mcp-connect.js +78 -15
- package/dist/mcp.js +84 -216
- package/dist/memory-pass.d.ts +17 -42
- package/dist/memory-pass.js +54 -26
- package/dist/phase-routing.d.ts +19 -72
- package/dist/phase-routing.js +34 -164
- package/dist/project-knowledge.d.ts +16 -35
- package/dist/project-knowledge.js +42 -21
- package/dist/project-memory.d.ts +2 -28
- package/dist/project-memory.js +28 -13
- package/dist/project-skills.d.ts +16 -38
- package/dist/project-skills.js +41 -32
- package/dist/project-tools.d.ts +1 -0
- package/dist/project-tools.js +4 -4
- package/dist/provider.d.ts +2 -0
- package/dist/provider.js +4 -16
- package/dist/result-shots.d.ts +1 -1
- package/dist/result-shots.js +2 -1
- package/dist/review-switch.d.ts +3 -8
- package/dist/reviewer.d.ts +8 -12
- package/dist/reviewer.js +11 -35
- package/dist/scope.d.ts +21 -43
- package/dist/scope.js +42 -128
- package/dist/scout-report.d.ts +9 -194
- package/dist/scout-report.js +113 -264
- package/dist/scout.js +15 -11
- package/dist/serve.js +9 -2
- package/dist/setup-guide.d.ts +2 -2
- package/dist/slack-chat.js +26 -20
- package/dist/slack-state.js +2 -1
- package/dist/store.d.ts +9 -32
- package/dist/store.js +18 -15
- package/dist/structured-output.js +2 -1
- package/dist/subscription-chat.d.ts +4 -0
- package/dist/subscription-chat.js +4 -1
- package/dist/task-review-brief.d.ts +1 -7
- package/dist/task-review-brief.js +6 -6
- package/dist/task-sizing.d.ts +3 -27
- package/dist/task-sizing.js +11 -26
- package/dist/task-text.d.ts +0 -5
- package/dist/task-text.js +1 -3
- package/dist/teammate-question.js +7 -5
- package/dist/teammate-work.js +9 -5
- package/dist/teammates.d.ts +13 -64
- package/dist/teammates.js +32 -33
- package/dist/teams-chat.js +20 -11
- package/dist/telegram-flow.js +4 -3
- package/dist/telegram-mate.d.ts +4 -14
- package/dist/telegram-mate.js +8 -7
- package/dist/telegram-team.d.ts +2 -19
- package/dist/telegram.d.ts +1 -1
- package/dist/telegram.js +52 -42
- package/dist/text-limits.d.ts +142 -1
- package/dist/text-limits.js +144 -1
- package/dist/tools-ui.d.ts +2 -1
- package/dist/tools-ui.js +7 -4
- package/package.json +1 -1
package/dist/coding-context.d.ts
CHANGED
|
@@ -1,43 +1,6 @@
|
|
|
1
1
|
import type { Store } from './store.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
repo: string;
|
|
5
|
-
identity: string;
|
|
6
|
-
baseRevision: string;
|
|
7
|
-
knowledge: {
|
|
8
|
-
revision: number;
|
|
9
|
-
selectionSha256: string;
|
|
10
|
-
references: {
|
|
11
|
-
id: string;
|
|
12
|
-
title: string;
|
|
13
|
-
path: string | null;
|
|
14
|
-
sourceSha: string | null;
|
|
15
|
-
sourceRevision: string | null;
|
|
16
|
-
}[];
|
|
17
|
-
omitted: {
|
|
18
|
-
title: string;
|
|
19
|
-
reason: string;
|
|
20
|
-
}[];
|
|
21
|
-
};
|
|
22
|
-
skills: {
|
|
23
|
-
revision: number;
|
|
24
|
-
packages: {
|
|
25
|
-
name: string;
|
|
26
|
-
sha256: string;
|
|
27
|
-
skillFile: string;
|
|
28
|
-
}[];
|
|
29
|
-
};
|
|
30
|
-
directory: string | null;
|
|
31
|
-
files: {
|
|
32
|
-
path: string;
|
|
33
|
-
sha256: string;
|
|
34
|
-
}[];
|
|
35
|
-
};
|
|
36
|
-
export type CodingContext = {
|
|
37
|
-
text: string;
|
|
38
|
-
metadata: CodingContextMetadata;
|
|
39
|
-
sha256: string;
|
|
40
|
-
};
|
|
2
|
+
import { type CodingContext } from './contracts/coding-context.js';
|
|
3
|
+
export type { CodingContext, CodingContextMetadata } from './contracts/coding-context.js';
|
|
41
4
|
/**
|
|
42
5
|
* Call before thread/start with the canonical project and the exact worktree
|
|
43
6
|
* base. Persist the returned object with the coding session and reuse it on
|
package/dist/coding-context.js
CHANGED
|
@@ -5,6 +5,7 @@ import { basename, dirname, join, resolve, relative, isAbsolute, sep } from 'nod
|
|
|
5
5
|
import { KNOWLEDGE_GUIDANCE, selectProjectKnowledge } from './project-knowledge.js';
|
|
6
6
|
import { materializeProjectSkills, PROJECT_SKILLS_GUIDANCE, selectProjectSkills } from './project-skills.js';
|
|
7
7
|
import { identityMatches, learningIdentity, learningSha } from './project-learning.js';
|
|
8
|
+
import { CODING_CONTEXT_VERSION } from './contracts/coding-context.js';
|
|
8
9
|
function freeze(value) {
|
|
9
10
|
if (value !== null && typeof value === 'object' && !Object.isFrozen(value)) {
|
|
10
11
|
for (const child of Object.values(value))
|
|
@@ -70,7 +71,7 @@ export function prepareCodingContext(store, args) {
|
|
|
70
71
|
directory,
|
|
71
72
|
files: captured.skills.packages.flatMap(skill => skill.files.map(file => ({ path: `${skill.name}/${file.path}`, sha256: fileDigest(Buffer.from(file.base64, 'base64')) }))),
|
|
72
73
|
};
|
|
73
|
-
return freeze({ text, metadata, sha256: digest(text, metadata) });
|
|
74
|
+
return freeze({ version: CODING_CONTEXT_VERSION, text, metadata, sha256: digest(text, metadata) });
|
|
74
75
|
}
|
|
75
76
|
/** Integrity check for a persisted capture. The caller must separately recheck current account access. */
|
|
76
77
|
export function verifyCodingContext(context, repo, baseRevision) {
|
package/dist/coding-handoff.d.ts
CHANGED
|
@@ -1,28 +1,7 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type CodingHandoffReceipt } from './contracts/coding-handoff.js';
|
|
2
2
|
import type { Store } from './store.js';
|
|
3
|
-
export type
|
|
4
|
-
|
|
5
|
-
repo: string;
|
|
6
|
-
base: string;
|
|
7
|
-
candidate: string;
|
|
8
|
-
title: string;
|
|
9
|
-
originalPrompt: string;
|
|
10
|
-
changedPaths: string[];
|
|
11
|
-
};
|
|
12
|
-
type ReceiptTerms = CodingHandoffPreview & {
|
|
13
|
-
version: 1;
|
|
14
|
-
identity: string;
|
|
15
|
-
actor: string;
|
|
16
|
-
generation: number;
|
|
17
|
-
goal: string;
|
|
18
|
-
acceptance: AcceptanceCriterion[];
|
|
19
|
-
outOfScope: string;
|
|
20
|
-
};
|
|
21
|
-
export type CodingHandoffReceipt = ReceiptTerms & {
|
|
22
|
-
id: string;
|
|
23
|
-
taskId: string;
|
|
24
|
-
branch: string;
|
|
25
|
-
};
|
|
3
|
+
export type { CodingHandoffReceipt } from './contracts/coding-handoff.js';
|
|
4
|
+
export type CodingHandoffPreview = Pick<CodingHandoffReceipt, 'sessionId' | 'repo' | 'base' | 'candidate' | 'title' | 'originalPrompt' | 'changedPaths'>;
|
|
26
5
|
export type CodingHandoffInput = {
|
|
27
6
|
sessionId: string;
|
|
28
7
|
repo: string;
|
|
@@ -42,6 +21,9 @@ export declare function codingHandoffPreview(store: Store, input: {
|
|
|
42
21
|
sessionId: string;
|
|
43
22
|
actor: string;
|
|
44
23
|
}): CodingHandoffPreview;
|
|
24
|
+
/** The saved bytes are verified before they are parsed; identity and branch are checked on the parsed terms. */
|
|
25
|
+
export declare function parseReceipt(row: Record<string, unknown>): CodingHandoffReceipt;
|
|
26
|
+
export declare function sealPayload(receipt: CodingHandoffReceipt, scopeDigest: string): string;
|
|
45
27
|
/** Returns null only for ordinary tasks. A coding marker always requires its receipt. */
|
|
46
28
|
export declare function readCodingHandoff(store: Store, taskId: string): Handoff | null;
|
|
47
29
|
/** No agent dispatch, approval, push, or modification of an existing Git ref. */
|
|
@@ -54,4 +36,3 @@ export declare function verifyCodingHandoffBase(store: Store, input: {
|
|
|
54
36
|
branch: string;
|
|
55
37
|
head: string;
|
|
56
38
|
}): void;
|
|
57
|
-
export {};
|
package/dist/coding-handoff.js
CHANGED
|
@@ -10,6 +10,8 @@ import { parseAcceptanceCriteria, proposeGuarded } from './scope.js';
|
|
|
10
10
|
import { validateTaskText } from './task-text.js';
|
|
11
11
|
import { PROOF_LIMITS } from './proof.js';
|
|
12
12
|
import { readPreparedEvidence } from './prepared-evidence.js';
|
|
13
|
+
import { parseCodingHandoffReceipt } from './contracts/coding-handoff.js';
|
|
14
|
+
import { parseCodingSessionDocument } from './contracts/coding-workspace.js';
|
|
13
15
|
import { BRANCH_PREFIXES, taskBranch } from './names.js';
|
|
14
16
|
const PREFIX = 'coding:';
|
|
15
17
|
const SHA = /^[a-f0-9]{40}$/;
|
|
@@ -84,7 +86,7 @@ function sessionFor(db, store, sessionId, actor) {
|
|
|
84
86
|
const row = db.prepare('SELECT owner,generation,repo,document FROM coding_session WHERE id=?').get(sessionId);
|
|
85
87
|
if (!row || row['owner'] !== actor)
|
|
86
88
|
throw Error('This coding session is not available to your account.');
|
|
87
|
-
const session =
|
|
89
|
+
const session = parseCodingSessionDocument(String(row['document']));
|
|
88
90
|
const generation = actorGeneration(store, actor, String(row['repo']));
|
|
89
91
|
if (row['generation'] !== generation || session.id !== sessionId || session.owner !== actor || session.generation !== generation || session.repo !== row['repo'])
|
|
90
92
|
throw Error('The coding session no longer matches your account or project.');
|
|
@@ -132,18 +134,22 @@ function makeReceipt(terms) {
|
|
|
132
134
|
const id = learningSha(JSON.stringify(terms)).slice(0, 32), taskId = `coding-review-${id}`;
|
|
133
135
|
return { ...terms, id, taskId, branch: taskBranch(taskId) };
|
|
134
136
|
}
|
|
135
|
-
|
|
137
|
+
/** The saved bytes are verified before they are parsed; identity and branch are checked on the parsed terms. */
|
|
138
|
+
export function parseReceipt(row) {
|
|
136
139
|
const payload = String(row['payload']);
|
|
137
140
|
if (learningSha(payload) !== row['sha'])
|
|
138
141
|
throw Error('The coding handoff receipt could not be verified.');
|
|
139
|
-
const
|
|
142
|
+
const read = parseCodingHandoffReceipt(payload);
|
|
143
|
+
if (!read.ok)
|
|
144
|
+
throw Error(`The coding handoff receipt could not be read: ${read.issues.map(issue => issue.line).join('; ')}`);
|
|
145
|
+
const receipt = read.value;
|
|
140
146
|
const { id, taskId, branch, ...terms } = receipt;
|
|
141
147
|
const expected = makeReceipt(terms);
|
|
142
|
-
if (
|
|
148
|
+
if (row['id'] !== id || id !== expected.id || taskId !== expected.taskId || !BRANCH_PREFIXES.some(prefix => branch === `${prefix}${taskId}`) || !SHA.test(receipt.base) || !SHA.test(receipt.candidate))
|
|
143
149
|
throw Error('The coding handoff receipt identity could not be verified.');
|
|
144
150
|
return receipt;
|
|
145
151
|
}
|
|
146
|
-
function sealPayload(receipt, scopeDigest) {
|
|
152
|
+
export function sealPayload(receipt, scopeDigest) {
|
|
147
153
|
return JSON.stringify({ version: 1, id: receipt.id, receiptSha256: learningSha(JSON.stringify(receipt)), scopeDigest });
|
|
148
154
|
}
|
|
149
155
|
function verifySeal(db, receipt, digest) {
|
package/dist/coding-types.d.ts
CHANGED
|
@@ -1,29 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export type CodingSession = {
|
|
4
|
-
id: string;
|
|
5
|
-
owner: string;
|
|
6
|
-
generation: number;
|
|
7
|
-
repo: string;
|
|
8
|
-
title: string;
|
|
9
|
-
provider: 'codex';
|
|
10
|
-
model: string | null;
|
|
11
|
-
branch: string;
|
|
12
|
-
base: string;
|
|
13
|
-
worktree: string;
|
|
14
|
-
nativeThreadId: string | null;
|
|
15
|
-
turnId: string | null;
|
|
16
|
-
status: CodingStatus;
|
|
17
|
-
error: string | null;
|
|
18
|
-
createdAt: string;
|
|
19
|
-
updatedAt: string;
|
|
20
|
-
deliveryReviewRequired?: boolean;
|
|
21
|
-
initialRequest?: {
|
|
22
|
-
requestId: string;
|
|
23
|
-
prompt: string;
|
|
24
|
-
};
|
|
25
|
-
context?: CodingContext;
|
|
26
|
-
};
|
|
1
|
+
export type { CodingSession, CodingStatus } from './contracts/coding-workspace.js';
|
|
2
|
+
import type { CodingSession } from './contracts/coding-workspace.js';
|
|
27
3
|
export type CodingItem = {
|
|
28
4
|
id: string;
|
|
29
5
|
type: string;
|
|
@@ -60,6 +60,8 @@ export declare class CodingWorkspace {
|
|
|
60
60
|
constructor(options: Options);
|
|
61
61
|
private authorize;
|
|
62
62
|
private read;
|
|
63
|
+
/** Preserve legacy reads, but never mutate an unidentified row or save an unreadable record's error projection. */
|
|
64
|
+
private catalogRow;
|
|
63
65
|
private admit;
|
|
64
66
|
private releaseOperation;
|
|
65
67
|
list(actor: CodingActor): CodingSession[];
|
package/dist/coding-workspace.js
CHANGED
|
@@ -9,6 +9,7 @@ import { run } from './exec.js';
|
|
|
9
9
|
import { processMayBeAlive } from './process-liveness.js';
|
|
10
10
|
import { createCodexCodingProvider } from './coding-provider.js';
|
|
11
11
|
import { verifyCodingContext } from './coding-context.js';
|
|
12
|
+
import { codingSessionDocument, parseCodingSessionDocument } from './contracts/coding-workspace.js';
|
|
12
13
|
export class CodingActionError extends Error {
|
|
13
14
|
delivery;
|
|
14
15
|
sessionId;
|
|
@@ -77,8 +78,10 @@ export class CodingWorkspace {
|
|
|
77
78
|
const clean = !prior || prior['clean'] === 1;
|
|
78
79
|
this.recoveryRequired = !clean;
|
|
79
80
|
this.db.prepare('INSERT OR REPLACE INTO coding_owner VALUES(1,?,?,?,?)').run(this.owner, process.pid, prior?.['native_pid'] ?? null, clean ? 1 : 0);
|
|
80
|
-
for (const row of this.db.prepare('SELECT
|
|
81
|
-
const session =
|
|
81
|
+
for (const row of this.db.prepare('SELECT * FROM coding_session').all()) {
|
|
82
|
+
const { session, usable } = this.catalogRow(row);
|
|
83
|
+
if (!usable)
|
|
84
|
+
continue;
|
|
82
85
|
if (session.status !== 'closed' && (!clean || busy.has(session.status)))
|
|
83
86
|
this.save({ ...session, status: clean ? 'interrupted' : 'uncertain', turnId: null, error: clean ? null : 'The previous server stopped without a verified process exit. Work is preserved; session recovery needs a process check before resuming.' });
|
|
84
87
|
}
|
|
@@ -99,7 +102,23 @@ export class CodingWorkspace {
|
|
|
99
102
|
const row = this.db.prepare('SELECT document FROM coding_session WHERE id=?').get(id);
|
|
100
103
|
if (!row)
|
|
101
104
|
throw Error('Coding session unavailable.');
|
|
102
|
-
return
|
|
105
|
+
return parseCodingSessionDocument(String(row['document']));
|
|
106
|
+
}
|
|
107
|
+
/** Preserve legacy reads, but never mutate an unidentified row or save an unreadable record's error projection. */
|
|
108
|
+
catalogRow(row) {
|
|
109
|
+
try {
|
|
110
|
+
const session = parseCodingSessionDocument(String(row['document']));
|
|
111
|
+
const usable = session.id === row['id'] && session.owner === row['owner'] && session.generation === row['generation'] && session.repo === row['repo'];
|
|
112
|
+
return { session, usable };
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
return { usable: false, session: {
|
|
116
|
+
id: String(row['id']), owner: String(row['owner']), generation: Number(row['generation']), repo: String(row['repo']),
|
|
117
|
+
title: 'Unreadable coding session', provider: 'codex', model: null, branch: '', base: '', worktree: '',
|
|
118
|
+
nativeThreadId: null, turnId: null, status: 'failed', createdAt: '', updatedAt: '',
|
|
119
|
+
error: error instanceof Error ? error.message : 'The saved coding session could not be read.',
|
|
120
|
+
} };
|
|
121
|
+
}
|
|
103
122
|
}
|
|
104
123
|
admit() {
|
|
105
124
|
if (this.closed || this.closing || this.persistenceFailed)
|
|
@@ -116,7 +135,7 @@ export class CodingWorkspace {
|
|
|
116
135
|
}
|
|
117
136
|
}
|
|
118
137
|
list(actor) {
|
|
119
|
-
return this.db.prepare('SELECT
|
|
138
|
+
return this.db.prepare('SELECT * FROM coding_session WHERE owner=? AND generation=? ORDER BY rowid DESC').all(actor.name, actor.generation).map(row => this.catalogRow(row).session);
|
|
120
139
|
}
|
|
121
140
|
/** Inspect a fixed metadata window before loading admitted documents.
|
|
122
141
|
* A filtered window can be short without proving the entire list empty. */
|
|
@@ -127,13 +146,18 @@ export class CodingWorkspace {
|
|
|
127
146
|
const window = rows.slice(0, 100);
|
|
128
147
|
const admitted = window.filter(row => options.authorized(String(row['repo'])));
|
|
129
148
|
const selected = admitted.slice(0, Math.min(100, Math.max(1, options.limit)));
|
|
130
|
-
|
|
149
|
+
const sessions = selected.map(row => {
|
|
150
|
+
const session = this.catalogRow(this.db.prepare('SELECT * FROM coding_session WHERE id=? AND owner=? AND generation=?').get(String(row['id']), actor.name, actor.generation)).session;
|
|
151
|
+
this.authorize(actor, session.repo);
|
|
152
|
+
return session;
|
|
153
|
+
});
|
|
154
|
+
return { sessions, truncated: rows.length > window.length || admitted.length > selected.length };
|
|
131
155
|
}
|
|
132
156
|
get(id, actor) {
|
|
133
157
|
const row = this.db.prepare('SELECT document FROM coding_session WHERE id=? AND owner=? AND generation=?').get(id, actor.name, actor.generation);
|
|
134
158
|
if (!row)
|
|
135
159
|
throw Error('This coding session is not available to your account.');
|
|
136
|
-
const session =
|
|
160
|
+
const session = parseCodingSessionDocument(String(row['document']));
|
|
137
161
|
this.authorize(actor, session.repo);
|
|
138
162
|
return session;
|
|
139
163
|
}
|
|
@@ -204,13 +228,16 @@ export class CodingWorkspace {
|
|
|
204
228
|
}
|
|
205
229
|
save(session) {
|
|
206
230
|
session.updatedAt = now();
|
|
207
|
-
this.db.prepare('INSERT INTO coding_session(id,owner,generation,repo,document) VALUES(?,?,?,?,?) ON CONFLICT(id) DO UPDATE SET document=excluded.document,revision=revision+1').run(session.id, session.owner, session.generation, session.repo,
|
|
231
|
+
this.db.prepare('INSERT INTO coding_session(id,owner,generation,repo,document) VALUES(?,?,?,?,?) ON CONFLICT(id) DO UPDATE SET document=excluded.document,revision=revision+1').run(session.id, session.owner, session.generation, session.repo, codingSessionDocument(session));
|
|
208
232
|
}
|
|
209
233
|
byThread(thread) {
|
|
210
234
|
if (typeof thread !== 'string')
|
|
211
235
|
return null;
|
|
212
|
-
const row = this.db.prepare("SELECT
|
|
213
|
-
|
|
236
|
+
const row = this.db.prepare("SELECT * FROM coding_session WHERE json_extract(document,'$.nativeThreadId')=?").get(thread);
|
|
237
|
+
if (!row)
|
|
238
|
+
return null;
|
|
239
|
+
const { session, usable } = this.catalogRow(row);
|
|
240
|
+
return usable ? session : null;
|
|
214
241
|
}
|
|
215
242
|
putItem(session, item) {
|
|
216
243
|
// Re-reading unchanged native history must not invalidate the request
|
|
@@ -285,8 +312,10 @@ export class CodingWorkspace {
|
|
|
285
312
|
if (event.kind === 'exit') {
|
|
286
313
|
this.flush();
|
|
287
314
|
this.loaded.clear();
|
|
288
|
-
for (const row of this.db.prepare('SELECT
|
|
289
|
-
const session =
|
|
315
|
+
for (const row of this.db.prepare('SELECT * FROM coding_session').all()) {
|
|
316
|
+
const { session, usable } = this.catalogRow(row);
|
|
317
|
+
if (!usable)
|
|
318
|
+
continue;
|
|
290
319
|
if (busy.has(session.status))
|
|
291
320
|
this.save({ ...session, status: 'uncertain', error: 'The agent connection closed. Work is preserved; delivery and process exit need to be checked before continuing.' });
|
|
292
321
|
}
|
|
@@ -522,7 +551,12 @@ export class CodingWorkspace {
|
|
|
522
551
|
this.operations.add(id);
|
|
523
552
|
try {
|
|
524
553
|
if (this.provider) {
|
|
525
|
-
const active = this.db.prepare('SELECT
|
|
554
|
+
const active = this.db.prepare('SELECT * FROM coding_session').all().some(row => {
|
|
555
|
+
const { session, usable } = this.catalogRow(row);
|
|
556
|
+
if (!usable)
|
|
557
|
+
throw new CodingActionError('A saved coding session could not be checked. Repair its record before reconnecting the agent.', 'rejected', id);
|
|
558
|
+
return busy.has(session.status);
|
|
559
|
+
});
|
|
526
560
|
if (active)
|
|
527
561
|
throw new CodingActionError('Another coding turn is still active. Wait for it to finish or stop it before reconnecting the agent.', 'rejected', id);
|
|
528
562
|
await this.provider.close();
|
|
@@ -754,8 +788,10 @@ export class CodingWorkspace {
|
|
|
754
788
|
this.db.close();
|
|
755
789
|
return;
|
|
756
790
|
}
|
|
757
|
-
for (const row of this.db.prepare('SELECT
|
|
758
|
-
const session =
|
|
791
|
+
for (const row of this.db.prepare('SELECT * FROM coding_session').all()) {
|
|
792
|
+
const { session, usable } = this.catalogRow(row);
|
|
793
|
+
if (!usable)
|
|
794
|
+
continue;
|
|
759
795
|
const uncertain = this.db.prepare("SELECT 1 FROM coding_submission WHERE session=? AND status IN ('preparing','pending','uncertain')").get(session.id);
|
|
760
796
|
if (!uncertain && (busy.has(session.status) || session.status === 'uncertain'))
|
|
761
797
|
this.save({ ...session, status: 'interrupted', turnId: null, error: null });
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The acceptance rubric's vocabulary and limits: the evidence kinds a criterion may require, and how many criteria
|
|
3
|
+
* and bytes a rubric may hold. A leaf with no imports but TEXT_LIMITS, because the plan contract (src/contracts/plan.ts)
|
|
4
|
+
* reads these through scope.ts while scope.ts reads the plan contract's criterion: kept here, both load in either order.
|
|
5
|
+
*/
|
|
6
|
+
export declare const EVIDENCE_KINDS: readonly ["check", "screenshot", "changed-path", "manual-review"];
|
|
7
|
+
export type EvidenceKind = (typeof EVIDENCE_KINDS)[number];
|
|
8
|
+
export declare const ACCEPTANCE_LIMITS: {
|
|
9
|
+
readonly criteria: 12;
|
|
10
|
+
readonly id: 40;
|
|
11
|
+
readonly statement: 1000;
|
|
12
|
+
readonly how: 500;
|
|
13
|
+
readonly evidenceKinds: 4;
|
|
14
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The acceptance rubric's vocabulary and limits: the evidence kinds a criterion may require, and how many criteria
|
|
3
|
+
* and bytes a rubric may hold. A leaf with no imports but TEXT_LIMITS, because the plan contract (src/contracts/plan.ts)
|
|
4
|
+
* reads these through scope.ts while scope.ts reads the plan contract's criterion: kept here, both load in either order.
|
|
5
|
+
*/
|
|
6
|
+
import { TEXT_LIMITS } from "../text-limits.js";
|
|
7
|
+
export const EVIDENCE_KINDS = ["check", "screenshot", "changed-path", "manual-review"];
|
|
8
|
+
export const ACCEPTANCE_LIMITS = {
|
|
9
|
+
criteria: 12,
|
|
10
|
+
id: TEXT_LIMITS.acceptanceIdBytes,
|
|
11
|
+
// A statement is one testable outcome; three hundred bytes forced people to
|
|
12
|
+
// drop the qualifying clause that made it testable.
|
|
13
|
+
statement: TEXT_LIMITS.acceptanceStatementBytes,
|
|
14
|
+
how: TEXT_LIMITS.acceptanceHowBytes,
|
|
15
|
+
evidenceKinds: EVIDENCE_KINDS.length,
|
|
16
|
+
};
|