robisie 0.1.0 → 0.1.1
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 +69 -0
- package/README.md +76 -12
- package/dist/active-recovery.d.ts +58 -0
- package/dist/active-recovery.js +143 -0
- package/dist/agents.d.ts +34 -0
- package/dist/agents.js +77 -16
- package/dist/attempt-identity.d.ts +21 -0
- package/dist/attempt-identity.js +39 -0
- package/dist/ci-failure-result.d.ts +23 -0
- package/dist/ci-failure-result.js +90 -0
- package/dist/claude-headless.d.ts +7 -0
- package/dist/claude-headless.js +28 -0
- package/dist/cli.d.ts +17 -0
- package/dist/cli.js +55 -15
- package/dist/commands.d.ts +18 -0
- package/dist/commands.js +190 -85
- package/dist/constants.d.ts +32 -0
- package/dist/constants.js +3 -3
- package/dist/context.d.ts +24 -0
- package/dist/context.js +22 -6
- package/dist/dependency-readiness.d.ts +13 -0
- package/dist/dependency-readiness.js +80 -0
- package/dist/dispatch-scope.d.ts +18 -0
- package/dist/dispatch-scope.js +46 -0
- package/dist/done-evidence.d.ts +31 -0
- package/dist/done-evidence.js +216 -0
- package/dist/engine-config.d.ts +65 -0
- package/dist/engine-config.js +139 -0
- package/dist/fsops.d.ts +87 -0
- package/dist/fsops.js +117 -24
- package/dist/helpers.d.ts +15 -0
- package/dist/helpers.js +262 -45
- package/dist/intent-rules/admission.d.ts +10 -0
- package/dist/intent-rules/admission.js +35 -0
- package/dist/intent-rules/done-when-roles.d.ts +21 -0
- package/dist/intent-rules/done-when-roles.js +101 -0
- package/dist/intent-rules/hooks.d.ts +29 -0
- package/dist/intent-rules/hooks.js +23 -0
- package/dist/k3-codex-role.d.ts +20 -0
- package/dist/k3-codex-role.js +68 -0
- package/dist/manifest.d.ts +41 -0
- package/dist/manifest.js +59 -14
- package/dist/mcp.d.ts +18 -0
- package/dist/mcp.js +89 -39
- package/dist/opencode-result.d.ts +19 -0
- package/dist/opencode-result.js +136 -0
- package/dist/opencode-review-guard.d.ts +1 -0
- package/dist/opencode-review-guard.js +19 -0
- package/dist/opencode-session-export.d.ts +5 -0
- package/dist/opencode-session-export.js +28 -0
- package/dist/outcome-moves.d.ts +15 -0
- package/dist/outcome-moves.js +39 -0
- package/dist/planer-client.d.ts +214 -0
- package/dist/planer-client.js +351 -0
- package/dist/restart-recovery.d.ts +47 -0
- package/dist/restart-recovery.js +70 -0
- package/dist/review-source-packet.d.ts +17 -0
- package/dist/review-source-packet.js +44 -0
- package/dist/role-registry.d.ts +19 -0
- package/dist/role-registry.js +83 -0
- package/dist/role-results.d.ts +15 -0
- package/dist/role-results.js +42 -0
- package/dist/roles.d.ts +30 -0
- package/dist/roles.js +20 -16
- package/dist/seed-validation.d.ts +28 -0
- package/dist/seed-validation.js +294 -0
- package/dist/selection-result.d.ts +44 -0
- package/dist/selection-result.js +144 -0
- package/dist/sparse-policy.d.ts +8 -0
- package/dist/sparse-policy.js +49 -0
- package/dist/tester-identity.d.ts +11 -0
- package/dist/tester-identity.js +53 -0
- package/dist/worker-env.d.ts +5 -0
- package/dist/worker-env.js +34 -0
- package/docs/ENGINE-API.md +78 -0
- package/docs/ENGINE-CONFIG.md +115 -0
- package/docs/README.en.md +24 -15
- package/docs/README.md +26 -15
- package/docs/RELEASE-0.1.0.md +81 -8
- package/docs/RELEASE-0.1.1.md +110 -0
- package/helpers/ceo-client-launcher-mcp.mjs +36 -8
- package/helpers/client-spawn-session.sh +181 -0
- package/helpers/client-spawn.sh +825 -0
- package/package.json +9 -4
- package/roles/ceo-client.md +3 -2
- package/roles/manager-builder-client.md +18 -4
- package/roles/quality-officer-client.md +20 -6
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type OpenCodeTokenUsage = Readonly<{
|
|
2
|
+
input?: number;
|
|
3
|
+
output?: number;
|
|
4
|
+
reasoning?: number;
|
|
5
|
+
cacheRead?: number;
|
|
6
|
+
cacheWrite?: number;
|
|
7
|
+
}>;
|
|
8
|
+
export declare function parseOpenCodeStream(raw: string, model: string): {
|
|
9
|
+
sessionId: string;
|
|
10
|
+
messageId: string;
|
|
11
|
+
report: string;
|
|
12
|
+
costUsd?: number;
|
|
13
|
+
usage?: OpenCodeTokenUsage;
|
|
14
|
+
};
|
|
15
|
+
export declare function bindOpenCodeExport(raw: string, stream: {
|
|
16
|
+
sessionId: string;
|
|
17
|
+
messageId: string;
|
|
18
|
+
report: string;
|
|
19
|
+
}, model: string): void;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
const PROVIDER = "opencode-go";
|
|
2
|
+
const REPORT_MARKER = "### RAPORT MASZYNISTY";
|
|
3
|
+
const SAFE_STREAM_ID = /^(?:ses|msg)_[A-Za-z0-9]+$/;
|
|
4
|
+
function record(value) {
|
|
5
|
+
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
6
|
+
? value
|
|
7
|
+
: null;
|
|
8
|
+
}
|
|
9
|
+
function countMarker(text) {
|
|
10
|
+
return text.split(REPORT_MARKER).length - 1;
|
|
11
|
+
}
|
|
12
|
+
export function parseOpenCodeStream(raw, model) {
|
|
13
|
+
const lines = raw.split(/\r?\n/).filter((line) => line.trim());
|
|
14
|
+
if (lines.length === 0)
|
|
15
|
+
throw new Error("OpenCode stream is empty");
|
|
16
|
+
let sessionId = null;
|
|
17
|
+
const textByMessage = new Map();
|
|
18
|
+
const seenModels = new Set(), seenProviders = new Set();
|
|
19
|
+
const costs = [];
|
|
20
|
+
const usage = {};
|
|
21
|
+
let usageObserved = false;
|
|
22
|
+
let lastTextMessageId = null;
|
|
23
|
+
for (const line of lines) {
|
|
24
|
+
let parsed;
|
|
25
|
+
try {
|
|
26
|
+
parsed = JSON.parse(line);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
throw new Error("OpenCode stream contains malformed JSON");
|
|
30
|
+
}
|
|
31
|
+
const event = record(parsed), part = record(event?.part);
|
|
32
|
+
if (!event || !part || typeof event.timestamp !== "number" || !Number.isFinite(event.timestamp)
|
|
33
|
+
|| typeof event.sessionID !== "string" || !SAFE_STREAM_ID.test(event.sessionID))
|
|
34
|
+
throw new Error("OpenCode stream envelope is malformed");
|
|
35
|
+
if (sessionId !== null && event.sessionID !== sessionId)
|
|
36
|
+
throw new Error("OpenCode stream mixes sessions");
|
|
37
|
+
sessionId = event.sessionID;
|
|
38
|
+
const type = event.type, partType = part.type;
|
|
39
|
+
if (!["step_start", "reasoning", "tool_use", "text", "step_finish"].includes(type)) {
|
|
40
|
+
throw new Error(`OpenCode stream event is unsupported: ${String(type)}`);
|
|
41
|
+
}
|
|
42
|
+
const messageId = part.messageID;
|
|
43
|
+
if (messageId !== undefined && (typeof messageId !== "string" || !SAFE_STREAM_ID.test(messageId)))
|
|
44
|
+
throw new Error("OpenCode stream message identity is malformed");
|
|
45
|
+
if (type === "step_start") {
|
|
46
|
+
if (partType !== "step-start")
|
|
47
|
+
throw new Error("OpenCode step_start is malformed");
|
|
48
|
+
if (typeof part.model === "string" && part.model.trim())
|
|
49
|
+
seenModels.add(part.model);
|
|
50
|
+
if (typeof part.provider === "string" && part.provider.trim())
|
|
51
|
+
seenProviders.add(part.provider);
|
|
52
|
+
}
|
|
53
|
+
else if (type === "text") {
|
|
54
|
+
if (partType !== "text" || typeof messageId !== "string" || typeof part.text !== "string")
|
|
55
|
+
throw new Error("OpenCode text event is malformed");
|
|
56
|
+
const chunks = textByMessage.get(messageId) ?? [];
|
|
57
|
+
chunks.push(part.text);
|
|
58
|
+
textByMessage.set(messageId, chunks);
|
|
59
|
+
lastTextMessageId = messageId;
|
|
60
|
+
}
|
|
61
|
+
else if (type === "reasoning" && partType !== "reasoning")
|
|
62
|
+
throw new Error("OpenCode reasoning event is malformed");
|
|
63
|
+
else if (type === "step_finish") {
|
|
64
|
+
if (partType !== "step-finish")
|
|
65
|
+
throw new Error("OpenCode step_finish is malformed");
|
|
66
|
+
if (part.cost !== undefined) {
|
|
67
|
+
if (typeof part.cost !== "number" || !Number.isFinite(part.cost) || part.cost < 0)
|
|
68
|
+
throw new Error("OpenCode stream cost is malformed");
|
|
69
|
+
costs.push(part.cost);
|
|
70
|
+
}
|
|
71
|
+
if (part.tokens !== undefined) {
|
|
72
|
+
const tokens = record(part.tokens), cache = record(tokens?.cache);
|
|
73
|
+
if (!tokens)
|
|
74
|
+
throw new Error("OpenCode stream usage is malformed");
|
|
75
|
+
const values = [
|
|
76
|
+
["input", tokens.input], ["output", tokens.output], ["reasoning", tokens.reasoning],
|
|
77
|
+
["cacheRead", cache?.read], ["cacheWrite", cache?.write],
|
|
78
|
+
];
|
|
79
|
+
for (const [key, value] of values) {
|
|
80
|
+
if (value === undefined)
|
|
81
|
+
continue;
|
|
82
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0)
|
|
83
|
+
throw new Error("OpenCode stream usage is malformed");
|
|
84
|
+
usage[key] = (usage[key] ?? 0) + value;
|
|
85
|
+
usageObserved = true;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const reports = [...textByMessage].map(([messageId, chunks]) => ({ messageId, report: chunks.join("") }))
|
|
91
|
+
.filter(({ report }) => countMarker(report) === 1);
|
|
92
|
+
if (!sessionId || reports.length !== 1 || reports[0]?.messageId !== lastTextMessageId) {
|
|
93
|
+
throw new Error("OpenCode stream does not contain exactly one final report");
|
|
94
|
+
}
|
|
95
|
+
for (const observed of seenModels) {
|
|
96
|
+
if (observed !== model && observed !== `${PROVIDER}/${model}`)
|
|
97
|
+
throw new Error("OpenCode stream model does not match the selected model");
|
|
98
|
+
}
|
|
99
|
+
for (const observed of seenProviders)
|
|
100
|
+
if (observed !== PROVIDER)
|
|
101
|
+
throw new Error("OpenCode stream provider does not match the Go plan");
|
|
102
|
+
return { sessionId, ...reports[0], ...(costs.length ? { costUsd: costs.reduce((sum, cost) => sum + cost, 0) } : {}),
|
|
103
|
+
...(usageObserved ? { usage } : {}) };
|
|
104
|
+
}
|
|
105
|
+
export function bindOpenCodeExport(raw, stream, model) {
|
|
106
|
+
let parsed;
|
|
107
|
+
try {
|
|
108
|
+
parsed = JSON.parse(raw);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
throw new Error("OpenCode export is malformed JSON");
|
|
112
|
+
}
|
|
113
|
+
const root = record(parsed), info = record(root?.info);
|
|
114
|
+
if (!root || info?.id !== stream.sessionId || !Array.isArray(root.messages))
|
|
115
|
+
throw new Error("OpenCode export session does not match stream");
|
|
116
|
+
const matches = root.messages.map(record).filter((message) => message?.type === "assistant" && message.id === stream.messageId);
|
|
117
|
+
if (matches.length !== 1)
|
|
118
|
+
throw new Error("OpenCode export message does not match stream");
|
|
119
|
+
const assistant = matches[0], identity = record(assistant.model);
|
|
120
|
+
if (identity?.id !== model || identity.providerID !== PROVIDER || assistant.finish !== "stop" || assistant.rawFinish !== "stop") {
|
|
121
|
+
throw new Error("OpenCode export terminal identity is malformed");
|
|
122
|
+
}
|
|
123
|
+
if (assistant.error !== undefined
|
|
124
|
+
|| (assistant.modelID !== undefined && assistant.modelID !== identity.id)
|
|
125
|
+
|| (assistant.providerID !== undefined && assistant.providerID !== identity.providerID)) {
|
|
126
|
+
throw new Error("OpenCode export contains conflicting terminal identity");
|
|
127
|
+
}
|
|
128
|
+
if (!Array.isArray(assistant.content))
|
|
129
|
+
throw new Error("OpenCode export content is malformed");
|
|
130
|
+
const textParts = assistant.content.map(record).filter((part) => part?.type === "text");
|
|
131
|
+
if (textParts.length !== 1 || textParts.some((part) => typeof part?.text !== "string"))
|
|
132
|
+
throw new Error("OpenCode export report is malformed");
|
|
133
|
+
const report = textParts.map((part) => String(part?.text)).join("");
|
|
134
|
+
if (countMarker(report) !== 1 || report !== stream.report)
|
|
135
|
+
throw new Error("OpenCode export report does not match stream");
|
|
136
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const OPENCODE_REVIEW_GUARD: string;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { FILE_MARK } from "./constants.js";
|
|
2
|
+
// Keep this function self-contained: its compiled JS is the installed plugin.
|
|
3
|
+
async function robisieReviewGuard() {
|
|
4
|
+
return {
|
|
5
|
+
"tool.execute.before": async (input, output) => {
|
|
6
|
+
if (typeof input !== "object" || input === null || !("tool" in input))
|
|
7
|
+
return;
|
|
8
|
+
if (input.tool !== "robisie_create_task" && input.tool !== "robisie_update_task")
|
|
9
|
+
return;
|
|
10
|
+
if (typeof output !== "object" || output === null || !("args" in output))
|
|
11
|
+
return;
|
|
12
|
+
const args = output.args;
|
|
13
|
+
if (typeof args === "object" && args !== null && "status" in args && args.status === "delivered") {
|
|
14
|
+
throw new Error("Brak wspieranego protokołu recenzji w OpenCode. Ta próba nie zmieniła karty.");
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export const OPENCODE_REVIEW_GUARD = `// ${FILE_MARK}\nexport const RobisieReviewGuard = ${robisieReviewGuard.toString()};\n`;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type SpawnSyncOptionsWithStringEncoding, type SpawnSyncReturns } from "node:child_process";
|
|
2
|
+
/** OpenCode may exit before pipe stdout drains; a regular file preserves the export. */
|
|
3
|
+
export declare function exportOpenCodeSessionFile(binary: string, session: string, options: SpawnSyncOptionsWithStringEncoding & {
|
|
4
|
+
maxBuffer: number;
|
|
5
|
+
}): SpawnSyncReturns<string>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { closeSync, mkdtempSync, openSync, readFileSync, rmSync, statSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
/** OpenCode may exit before pipe stdout drains; a regular file preserves the export. */
|
|
6
|
+
export function exportOpenCodeSessionFile(binary, session, options) {
|
|
7
|
+
const dir = mkdtempSync(join(tmpdir(), "opencode-export-"));
|
|
8
|
+
let fd;
|
|
9
|
+
try {
|
|
10
|
+
const file = join(dir, "session.json");
|
|
11
|
+
fd = openSync(file, "w", 0o600);
|
|
12
|
+
const result = spawnSync(binary, ["session", "export", session], { ...options, shell: false, stdio: ["ignore", fd, "pipe"] });
|
|
13
|
+
if (statSync(file).size > options.maxBuffer) {
|
|
14
|
+
return { ...result, status: null, stdout: "", error: result.error ?? Object.assign(new Error(`spawnSync ${binary} ENOBUFS: session export exceeds ${options.maxBuffer} bytes`), { code: "ENOBUFS" }) };
|
|
15
|
+
}
|
|
16
|
+
return { ...result, stdout: readFileSync(file, "utf8") };
|
|
17
|
+
}
|
|
18
|
+
finally {
|
|
19
|
+
// IO errors propagate to the caller's existing process-error handling.
|
|
20
|
+
try {
|
|
21
|
+
if (fd !== undefined)
|
|
22
|
+
closeSync(fd);
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
rmSync(dir, { recursive: true, force: true });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type WorkerOutcome, type ReviewVerdict } from "./role-results.js";
|
|
2
|
+
/** Mapuje wynik Workera na ruch na tablicy. */
|
|
3
|
+
export declare function decideBoardMove(outcome: WorkerOutcome, attempts: number, maxAttempts?: number): {
|
|
4
|
+
status: "in_review";
|
|
5
|
+
note: string;
|
|
6
|
+
} | {
|
|
7
|
+
status: "blocked";
|
|
8
|
+
note: string;
|
|
9
|
+
} | {
|
|
10
|
+
status: "retry";
|
|
11
|
+
note: string;
|
|
12
|
+
};
|
|
13
|
+
export declare const MAX_REVIEW_ROUNDS = 3;
|
|
14
|
+
/** reviewRound = indeks od zera; unavailable obejmuje bieżącą próbę. Grant R3 weryfikuje i trwale konsumuje caller. */
|
|
15
|
+
export declare function decideReviewMove(verdict: ReviewVerdict, reviewRound: number, unavailable?: number, verifiedR3Grant?: boolean): "land" | "repair" | "blocked" | "retry-review";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { plainMarkers } from "./role-results.js";
|
|
2
|
+
/** Mapuje wynik Workera na ruch na tablicy. */
|
|
3
|
+
export function decideBoardMove(outcome, attempts, maxAttempts = 3) {
|
|
4
|
+
/** Powód: tekst po „CZEGO NIE ZROBIONO I DLACZEGO:” w tej samej linii, inaczej pierwsza niepusta linia niżej. */
|
|
5
|
+
const reasonOf = (status) => {
|
|
6
|
+
const lines = plainMarkers(outcome.report).split(/\r?\n/).map((line) => line.trim());
|
|
7
|
+
const statusLine = lines.findIndex((line) => new RegExp(`^[-*]?\\s*STATUS:\\s*${status}\\b`).test(line));
|
|
8
|
+
const header = /^[-*]?\s*CZEGO NIE ZROBIONO I DLACZEGO:\s*(.*)$/;
|
|
9
|
+
const field = lines.findIndex((line, index) => index > statusLine && header.test(line));
|
|
10
|
+
const reason = (field >= 0 ? header.exec(lines[field])?.[1] : "")
|
|
11
|
+
|| lines.slice((field >= 0 ? field : statusLine) + 1).find(Boolean)?.replace(/^[-*]\s*/, "") || "brak podanego powodu";
|
|
12
|
+
return Array.from(reason).slice(0, 200).join("");
|
|
13
|
+
};
|
|
14
|
+
switch (outcome.status) {
|
|
15
|
+
case "WORKER_FINISHED":
|
|
16
|
+
case "ALREADY_DONE":
|
|
17
|
+
return { status: "in_review", note: `${outcome.status} — dowód w details.maszynista` };
|
|
18
|
+
case "NEEDS_HUMAN":
|
|
19
|
+
return { status: "blocked", note: `worker: WYMAGA CZŁOWIEKA — ${reasonOf("NEEDS_HUMAN")}` };
|
|
20
|
+
case "ACTIONABLE_BLOCKER":
|
|
21
|
+
return { status: "blocked", note: `worker: ACTIONABLE_BLOCKER — ${reasonOf("ACTIONABLE_BLOCKER")}` };
|
|
22
|
+
case "FAILED":
|
|
23
|
+
case "UNKNOWN":
|
|
24
|
+
default:
|
|
25
|
+
if (attempts < maxAttempts)
|
|
26
|
+
return { status: "retry", note: `próba ${attempts}/${maxAttempts} nieudana (${outcome.status})` };
|
|
27
|
+
return { status: "blocked", note: `${maxAttempts} próby nieudane (${outcome.status}) — blokada techniczna, do CR/Reksia` };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export const MAX_REVIEW_ROUNDS = 3;
|
|
31
|
+
/** reviewRound = indeks od zera; unavailable obejmuje bieżącą próbę. Grant R3 weryfikuje i trwale konsumuje caller. */
|
|
32
|
+
export function decideReviewMove(verdict, reviewRound, unavailable = 0, verifiedR3Grant = false) {
|
|
33
|
+
if (verdict === "PASS")
|
|
34
|
+
return "land";
|
|
35
|
+
if (verdict === "FAIL")
|
|
36
|
+
return reviewRound < MAX_REVIEW_ROUNDS - 1
|
|
37
|
+
|| verifiedR3Grant === true && reviewRound === MAX_REVIEW_ROUNDS - 1 ? "repair" : "blocked";
|
|
38
|
+
return unavailable >= 3 ? "blocked" : "retry-review";
|
|
39
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** No environment, filesystem, DB or Keychain reads. Pass Ctx.origin/fetch and ROBISIE_KEY explicitly. */
|
|
3
|
+
export type PlanerClientConfig = ({
|
|
4
|
+
origin: string;
|
|
5
|
+
endpoint?: never;
|
|
6
|
+
} | {
|
|
7
|
+
endpoint: string;
|
|
8
|
+
origin?: never;
|
|
9
|
+
}) & {
|
|
10
|
+
token: string;
|
|
11
|
+
fetch?: typeof fetch;
|
|
12
|
+
deadlineMs?: number;
|
|
13
|
+
};
|
|
14
|
+
type Operation = "connect" | "close" | "list_projects" | "list_tracks" | "list_tasks" | "get_task" | "reserve_task" | "update_task" | "append_detail" | "close_decision_matter" | "get_review_snapshot" | "accept_review" | "create_track" | "create_task";
|
|
15
|
+
type Failure = "INVALID_CONFIG" | "INVALID_ARGUMENT" | "NOT_CONNECTED" | "CLOSED" | "CONTRACT_VERSION" | "INVALID_RESPONSE" | "DETAILS_READ_ERROR" | "TOOL_ERROR" | "UNAUTHORIZED" | "FORBIDDEN" | "RATE_LIMITED" | "HTTP_ERROR" | "RPC_ERROR" | "TRANSPORT_ERROR" | "TIMEOUT";
|
|
16
|
+
/** Fixed reason only. In particular, never attach SDK message, cause, raw body or caller arguments. */
|
|
17
|
+
export declare class PlanerClientError extends Error {
|
|
18
|
+
readonly code: Failure;
|
|
19
|
+
readonly operation: Operation;
|
|
20
|
+
/** A write may have reached the server: caller must read/decide before another write. */
|
|
21
|
+
readonly uncertain: boolean;
|
|
22
|
+
constructor(code: Failure, operation: Operation,
|
|
23
|
+
/** A write may have reached the server: caller must read/decide before another write. */
|
|
24
|
+
uncertain?: boolean, diagnostic?: {
|
|
25
|
+
plannerCode?: string;
|
|
26
|
+
requestId?: string;
|
|
27
|
+
});
|
|
28
|
+
readonly plannerCode?: string;
|
|
29
|
+
readonly requestId?: string;
|
|
30
|
+
}
|
|
31
|
+
declare const jsonObject: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
|
|
32
|
+
declare const projectSchema: z.ZodObject<{
|
|
33
|
+
id: z.ZodUUID;
|
|
34
|
+
name: z.ZodString;
|
|
35
|
+
slug: z.ZodString;
|
|
36
|
+
}, z.core.$strip>;
|
|
37
|
+
declare const trackSchema: z.ZodObject<{
|
|
38
|
+
id: z.ZodUUID;
|
|
39
|
+
projectId: z.ZodUUID;
|
|
40
|
+
name: z.ZodString;
|
|
41
|
+
position: z.ZodNumber;
|
|
42
|
+
}, z.core.$strip>;
|
|
43
|
+
declare const taskSchema: z.ZodObject<{
|
|
44
|
+
id: z.ZodUUID;
|
|
45
|
+
projectId: z.ZodUUID;
|
|
46
|
+
trackId: z.ZodUUID;
|
|
47
|
+
title: z.ZodString;
|
|
48
|
+
status: z.ZodEnum<{
|
|
49
|
+
ready: "ready";
|
|
50
|
+
in_review: "in_review";
|
|
51
|
+
in_progress: "in_progress";
|
|
52
|
+
delivered: "delivered";
|
|
53
|
+
blocked: "blocked";
|
|
54
|
+
done: "done";
|
|
55
|
+
draft: "draft";
|
|
56
|
+
}>;
|
|
57
|
+
assignee: z.ZodNullable<z.ZodString>;
|
|
58
|
+
dependsOn: z.ZodArray<z.ZodUUID>;
|
|
59
|
+
}, z.core.$strip>;
|
|
60
|
+
declare const echoSchema: z.ZodObject<{
|
|
61
|
+
id: z.ZodUUID;
|
|
62
|
+
title: z.ZodString;
|
|
63
|
+
status: z.ZodEnum<{
|
|
64
|
+
ready: "ready";
|
|
65
|
+
in_review: "in_review";
|
|
66
|
+
in_progress: "in_progress";
|
|
67
|
+
delivered: "delivered";
|
|
68
|
+
blocked: "blocked";
|
|
69
|
+
done: "done";
|
|
70
|
+
draft: "draft";
|
|
71
|
+
}>;
|
|
72
|
+
trackId: z.ZodUUID;
|
|
73
|
+
updatedAt: z.ZodISODateTime;
|
|
74
|
+
}, z.core.$strip>;
|
|
75
|
+
declare const createTaskSchema: z.ZodObject<{
|
|
76
|
+
id: z.ZodUUID;
|
|
77
|
+
title: z.ZodString;
|
|
78
|
+
status: z.ZodEnum<{
|
|
79
|
+
ready: "ready";
|
|
80
|
+
in_review: "in_review";
|
|
81
|
+
in_progress: "in_progress";
|
|
82
|
+
delivered: "delivered";
|
|
83
|
+
blocked: "blocked";
|
|
84
|
+
done: "done";
|
|
85
|
+
draft: "draft";
|
|
86
|
+
}>;
|
|
87
|
+
trackId: z.ZodUUID;
|
|
88
|
+
updatedAt: z.ZodISODateTime;
|
|
89
|
+
similarOpenCards: z.ZodArray<z.ZodObject<{
|
|
90
|
+
id: z.ZodUUID;
|
|
91
|
+
title: z.ZodString;
|
|
92
|
+
track: z.ZodString;
|
|
93
|
+
status: z.ZodEnum<{
|
|
94
|
+
ready: "ready";
|
|
95
|
+
in_review: "in_review";
|
|
96
|
+
in_progress: "in_progress";
|
|
97
|
+
delivered: "delivered";
|
|
98
|
+
blocked: "blocked";
|
|
99
|
+
done: "done";
|
|
100
|
+
draft: "draft";
|
|
101
|
+
}>;
|
|
102
|
+
score: z.ZodNumber;
|
|
103
|
+
}, z.core.$strip>>;
|
|
104
|
+
}, z.core.$strip>;
|
|
105
|
+
declare const reviewSnapshotSchema: z.ZodObject<{
|
|
106
|
+
cardId: z.ZodUUID;
|
|
107
|
+
projectId: z.ZodUUID;
|
|
108
|
+
submissionId: z.ZodUUID;
|
|
109
|
+
snapshot: z.ZodString;
|
|
110
|
+
label: z.ZodLiteral<"recenzja innym kluczem; dostawca deklarowany">;
|
|
111
|
+
}, z.core.$strip>;
|
|
112
|
+
declare const acceptReviewInput: z.ZodObject<{
|
|
113
|
+
id: z.ZodUUID;
|
|
114
|
+
cardId: z.ZodUUID;
|
|
115
|
+
projectId: z.ZodUUID;
|
|
116
|
+
submissionId: z.ZodUUID;
|
|
117
|
+
snapshot: z.ZodString;
|
|
118
|
+
providerDeclared: z.ZodString;
|
|
119
|
+
}, z.core.$strict>;
|
|
120
|
+
export type ReviewSnapshot = z.infer<typeof reviewSnapshotSchema>;
|
|
121
|
+
export type AcceptReviewInput = z.infer<typeof acceptReviewInput>;
|
|
122
|
+
declare const reservationSchema: z.ZodObject<{
|
|
123
|
+
id: z.ZodUUID;
|
|
124
|
+
status: z.ZodEnum<{
|
|
125
|
+
ready: "ready";
|
|
126
|
+
in_review: "in_review";
|
|
127
|
+
in_progress: "in_progress";
|
|
128
|
+
delivered: "delivered";
|
|
129
|
+
blocked: "blocked";
|
|
130
|
+
done: "done";
|
|
131
|
+
draft: "draft";
|
|
132
|
+
}>;
|
|
133
|
+
assignee: z.ZodNullable<z.ZodString>;
|
|
134
|
+
trackId: z.ZodUUID;
|
|
135
|
+
updatedAt: z.ZodISODateTime;
|
|
136
|
+
}, z.core.$strip>;
|
|
137
|
+
declare const appendSchema: z.ZodObject<{
|
|
138
|
+
id: z.ZodUUID;
|
|
139
|
+
title: z.ZodString;
|
|
140
|
+
status: z.ZodEnum<{
|
|
141
|
+
ready: "ready";
|
|
142
|
+
in_review: "in_review";
|
|
143
|
+
in_progress: "in_progress";
|
|
144
|
+
delivered: "delivered";
|
|
145
|
+
blocked: "blocked";
|
|
146
|
+
done: "done";
|
|
147
|
+
draft: "draft";
|
|
148
|
+
}>;
|
|
149
|
+
trackId: z.ZodUUID;
|
|
150
|
+
updatedAt: z.ZodISODateTime;
|
|
151
|
+
appendedKeys: z.ZodArray<z.ZodString>;
|
|
152
|
+
}, z.core.$strip>;
|
|
153
|
+
declare const closeSchema: z.ZodObject<{
|
|
154
|
+
outcome: z.ZodEnum<{
|
|
155
|
+
CLOSED: "CLOSED";
|
|
156
|
+
ALREADY_CLOSED: "ALREADY_CLOSED";
|
|
157
|
+
CONFLICT: "CONFLICT";
|
|
158
|
+
NOT_APPLIED: "NOT_APPLIED";
|
|
159
|
+
}>;
|
|
160
|
+
cardId: z.ZodUUID;
|
|
161
|
+
matterId: z.ZodString;
|
|
162
|
+
matter: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodJSONSchema>>;
|
|
163
|
+
}, z.core.$strip>;
|
|
164
|
+
export type PlanerTask = z.infer<typeof taskSchema> & {
|
|
165
|
+
details?: z.infer<typeof jsonObject> | null;
|
|
166
|
+
availableDetailsKeys?: string[] | null;
|
|
167
|
+
};
|
|
168
|
+
export type PlanerTaskWithReadiness = PlanerTask & {
|
|
169
|
+
depsReady: boolean;
|
|
170
|
+
};
|
|
171
|
+
export type AppendDetailResult = {
|
|
172
|
+
write: z.infer<typeof appendSchema>;
|
|
173
|
+
/** Write confirmation survives a failed readback; never repeat the append to repair a read. */
|
|
174
|
+
readback: {
|
|
175
|
+
ok: true;
|
|
176
|
+
task: PlanerTask | null;
|
|
177
|
+
} | {
|
|
178
|
+
ok: false;
|
|
179
|
+
error: PlanerClientError;
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
export type CloseDecisionResult = Omit<z.infer<typeof closeSchema>, "matter"> & {
|
|
183
|
+
isError: boolean;
|
|
184
|
+
};
|
|
185
|
+
/** Existing MCP operations only. No auto-connect, retry, CAS emulation or runtime cutover. */
|
|
186
|
+
export declare class PlanerClient {
|
|
187
|
+
#private;
|
|
188
|
+
constructor(config: unknown);
|
|
189
|
+
connect(): Promise<void>;
|
|
190
|
+
close(): Promise<void>;
|
|
191
|
+
listProjects(args?: unknown): Promise<z.infer<typeof projectSchema>[]>;
|
|
192
|
+
listTracks(args: unknown): Promise<z.infer<typeof trackSchema>[]>;
|
|
193
|
+
createTrack(args: unknown): Promise<z.infer<typeof trackSchema>>;
|
|
194
|
+
createTask(args: unknown): Promise<z.infer<typeof createTaskSchema>>;
|
|
195
|
+
listTasks(args: unknown): Promise<PlanerTaskWithReadiness[]>;
|
|
196
|
+
getTask(args: unknown): Promise<PlanerTask | null>;
|
|
197
|
+
reserveTask(args: unknown): Promise<z.infer<typeof reservationSchema>>;
|
|
198
|
+
/** Server snapshot of an in_review card; does not confirm enforced policy or code/model provenance.
|
|
199
|
+
* Rejects malformed/mismatched responses with INVALID_RESPONSE, uncertain=false. */
|
|
200
|
+
getReviewSnapshot(args: unknown): Promise<ReviewSnapshot>;
|
|
201
|
+
/** Server owns policy, authenticated actor and atomic receipt/delivered write. providerDeclared is
|
|
202
|
+
* only a declaration, not proof of model execution. No retry, update_task fallback or snapshot refresh.
|
|
203
|
+
* Strict input: matching id/cardId, UUIDs, lowercase 64-hex snapshot, trimmed 1–200 character declaration.
|
|
204
|
+
* Local validation fails with INVALID_ARGUMENT/uncertain=false; failures after sending are uncertain.
|
|
205
|
+
* After an uncertain write, caller must explicitly getTask({id, include:['review_receipt']}) and decide. */
|
|
206
|
+
acceptReview(args: unknown): Promise<z.infer<typeof echoSchema>>;
|
|
207
|
+
/** For draft promotion, pass {status:'ready', expected:{status:'draft'}}. Server owns CAS/permissions. */
|
|
208
|
+
updateTask(args: unknown): Promise<z.infer<typeof echoSchema>>;
|
|
209
|
+
/** Flat server merge; null is literal. No deep merge, chunking, append guard or implicit retry. */
|
|
210
|
+
appendDetail(args: unknown): Promise<AppendDetailResult>;
|
|
211
|
+
/** full/owner_validator authority stays on the server. Non-CLOSED outcomes retain isError. */
|
|
212
|
+
closeDecisionMatter(args: unknown): Promise<CloseDecisionResult>;
|
|
213
|
+
}
|
|
214
|
+
export {};
|