@akagilnc/pi-workflow-roles 0.1.3558 → 0.1.3572
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/README.md +4 -1
- package/README.zh-CN.md +1 -1
- package/dist/acp-host/description.js +21 -0
- package/dist/{grok → acp-host}/mcp-relay.mjs +5 -5
- package/dist/{grok → acp-host}/production-host.js +860 -162
- package/dist/diarist-contracts.js +72 -0
- package/dist/host-descriptions.js +34 -0
- package/dist/package-contracts/terminating-tools.js +20 -2
- package/dist/packaged-role-registry.js +20 -0
- package/dist/public-cli/config.js +23 -10
- package/dist/public-cli/main.js +622 -671
- package/dist/public-cli/registry.js +4 -1
- package/extensions/role-runtime.ts +1 -0
- package/package.json +1 -1
- package/resources/diarist-collect.md +6 -10
- package/scripts/build-package.mjs +8 -8
- package/souls/diarist.md +9 -0
- package/src/acp-host/description.ts +43 -0
- package/src/{grok → acp-host}/mcp-relay.mjs +5 -5
- package/src/{grok → acp-host}/production-host.ts +31 -37
- package/src/{grok → acp-host}/role-envelope.ts +25 -24
- package/src/{grok → acp-host}/role-turn-host.ts +46 -81
- package/src/{grok → acp-host}/session-identity.ts +7 -7
- package/src/diarist-contracts.ts +88 -0
- package/src/diarist-role.ts +60 -0
- package/src/diarist.ts +253 -179
- package/src/host-contracts.ts +11 -4
- package/src/host-descriptions.ts +51 -0
- package/src/host-transition-prior-native.ts +12 -24
- package/src/package-contracts/terminating-tools.ts +22 -2
- package/src/packaged-role-registry.ts +20 -0
- package/src/pi/role-turn-host.ts +10 -1
- package/src/public-cli/cli.ts +39 -9
- package/src/public-cli/config.ts +24 -11
- package/src/public-cli/countersign-run.ts +9 -129
- package/src/public-cli/diarist-run.ts +312 -0
- package/src/public-cli/invocation.ts +23 -2
- package/src/public-cli/load-production-acp-host.ts +52 -0
- package/src/public-cli/option-definitions.ts +18 -0
- package/src/public-cli/post-admission.ts +3 -3
- package/src/public-cli/registry.ts +3 -0
- package/src/public-cli/run-lifecycle.ts +31 -3
- package/src/public-cli/settlement.ts +50 -2
- package/src/public-cli/terminal.ts +2 -1
- package/src/role-runtime.ts +117 -6
- package/src/ticket-provenance-contracts.ts +1 -0
- package/src/ticket-provenance.ts +0 -23
- package/src/diarist-llm-collector.ts +0 -324
- package/src/public-cli/load-production-grok-host.ts +0 -35
|
@@ -1238,9 +1238,8 @@ var init_in_process_session = __esm({
|
|
|
1238
1238
|
}
|
|
1239
1239
|
});
|
|
1240
1240
|
|
|
1241
|
-
// src/
|
|
1241
|
+
// src/acp-host/production-host.ts
|
|
1242
1242
|
import { readFile as readFile15 } from "node:fs/promises";
|
|
1243
|
-
import { join as join24 } from "node:path";
|
|
1244
1243
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
1245
1244
|
|
|
1246
1245
|
// src/canonical-skill-binding.ts
|
|
@@ -2875,6 +2874,50 @@ function validateRecordedInspectorOutput(value) {
|
|
|
2875
2874
|
throw new Error("Inspector output has no execution discriminator");
|
|
2876
2875
|
}
|
|
2877
2876
|
|
|
2877
|
+
// src/diarist-contracts.ts
|
|
2878
|
+
var DIARIST_OUTPUT_TOOL_NAME = "ak_diarist_output";
|
|
2879
|
+
var DIARIST_ACCEPTED_TEXT = "\u8D77\u5C45\u90CE\u56DE\u6267\u5DF2\u63A5\u53D7";
|
|
2880
|
+
var DIARIST_SOURCES_FLAG = {
|
|
2881
|
+
name: "ak-diarist-sources",
|
|
2882
|
+
definition: {
|
|
2883
|
+
description: "Frozen per-ticket source catalog the diarist selects from",
|
|
2884
|
+
type: "string"
|
|
2885
|
+
}
|
|
2886
|
+
};
|
|
2887
|
+
function validateRecordedDiaristOutput(value) {
|
|
2888
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
2889
|
+
throw new Error("Diarist output has no execution discriminator");
|
|
2890
|
+
}
|
|
2891
|
+
let status;
|
|
2892
|
+
try {
|
|
2893
|
+
status = value.status;
|
|
2894
|
+
} catch {
|
|
2895
|
+
throw new Error("Diarist output has no execution discriminator");
|
|
2896
|
+
}
|
|
2897
|
+
if (status === "completed") {
|
|
2898
|
+
return value;
|
|
2899
|
+
}
|
|
2900
|
+
throw new Error("Diarist output has no execution discriminator");
|
|
2901
|
+
}
|
|
2902
|
+
function projectDiaristSelections(value) {
|
|
2903
|
+
const rows = value?.selections;
|
|
2904
|
+
if (!Array.isArray(rows)) return [];
|
|
2905
|
+
const out = [];
|
|
2906
|
+
for (const row of rows) {
|
|
2907
|
+
if (row === null || typeof row !== "object" || Array.isArray(row)) continue;
|
|
2908
|
+
const record4 = row;
|
|
2909
|
+
const index = record4.candidateIndex;
|
|
2910
|
+
if (typeof index !== "number" || !Number.isInteger(index) || index < 0) continue;
|
|
2911
|
+
const quotes = Array.isArray(record4.quotes) ? record4.quotes.filter((q) => typeof q === "string" && q.length > 0) : [];
|
|
2912
|
+
out.push({
|
|
2913
|
+
candidateIndex: index,
|
|
2914
|
+
quotes,
|
|
2915
|
+
...typeof record4.note === "string" ? { note: record4.note } : {}
|
|
2916
|
+
});
|
|
2917
|
+
}
|
|
2918
|
+
return out;
|
|
2919
|
+
}
|
|
2920
|
+
|
|
2878
2921
|
// src/packaged-role-registry.ts
|
|
2879
2922
|
var NOTARY_SESSION_MATERIALS = [
|
|
2880
2923
|
"CLAUDE.md",
|
|
@@ -3041,6 +3084,22 @@ var PUBLIC_ROLE_RECORDS = [
|
|
|
3041
3084
|
phaseFlag: void 0,
|
|
3042
3085
|
activationStage: "load-and-install",
|
|
3043
3086
|
sessionMaterials: ["CLAUDE.md", "souls/navigator.md"]
|
|
3087
|
+
},
|
|
3088
|
+
// #708 / ADR 0075 `diarist-is-role`: 起居郎 is a seat like any other. The
|
|
3089
|
+
// frozen source catalog rides the shared input-flag seam; it is absent for a
|
|
3090
|
+
// true-unbound summons (no ticket → no diary).
|
|
3091
|
+
{
|
|
3092
|
+
role: "diarist",
|
|
3093
|
+
phases: [null],
|
|
3094
|
+
outputTool: DIARIST_OUTPUT_TOOL_NAME,
|
|
3095
|
+
inputFlag: DIARIST_SOURCES_FLAG.name,
|
|
3096
|
+
phaseFlag: void 0,
|
|
3097
|
+
activationStage: "load-and-install",
|
|
3098
|
+
sessionMaterials: [
|
|
3099
|
+
"CLAUDE.md",
|
|
3100
|
+
"souls/diarist.md",
|
|
3101
|
+
"resources/diarist-collect.md"
|
|
3102
|
+
]
|
|
3044
3103
|
}
|
|
3045
3104
|
];
|
|
3046
3105
|
var PACKAGED_ROLE_REGISTRY = PUBLIC_ROLE_RECORDS.map(({ sessionMaterials: _omit, ...metadata }) => metadata);
|
|
@@ -3696,6 +3755,29 @@ function appendEngineSessionMaterial(lines, engineMaterial) {
|
|
|
3696
3755
|
return out;
|
|
3697
3756
|
}
|
|
3698
3757
|
|
|
3758
|
+
// src/host-descriptions.ts
|
|
3759
|
+
var PRIVATE_COMPAT_ENV = Object.fromEntries(
|
|
3760
|
+
["CLAUDE", "CURSOR", "CODEX"].flatMap((vendor) => ["SKILLS", "RULES", "AGENTS", "MCPS", "HOOKS", "SESSIONS"].map((kind) => [`GROK_${vendor}_${kind}_ENABLED`, "false"]))
|
|
3761
|
+
);
|
|
3762
|
+
var HOST_DESCRIPTIONS = Object.freeze({
|
|
3763
|
+
/** Operator home `~/.grok`, native session/load resume, `agent [--model X] stdio`. */
|
|
3764
|
+
"grok-build": Object.freeze({
|
|
3765
|
+
binaryFromHome: Object.freeze([".grok", "bin", "grok"]),
|
|
3766
|
+
argv: Object.freeze({
|
|
3767
|
+
prefix: Object.freeze(["agent"]),
|
|
3768
|
+
suffix: Object.freeze(["stdio"]),
|
|
3769
|
+
modelFlag: "--model"
|
|
3770
|
+
}),
|
|
3771
|
+
boundResume: "session/load",
|
|
3772
|
+
sessionBindingFile: "grok-acp-session.json",
|
|
3773
|
+
childEnv: Object.freeze({
|
|
3774
|
+
...PRIVATE_COMPAT_ENV,
|
|
3775
|
+
GROK_MEMORY: "0",
|
|
3776
|
+
GROK_SUBAGENTS: "0"
|
|
3777
|
+
})
|
|
3778
|
+
})
|
|
3779
|
+
});
|
|
3780
|
+
|
|
3699
3781
|
// src/institutional-resolution.ts
|
|
3700
3782
|
import { readFile as readFile4, writeFile as writeFile2 } from "node:fs/promises";
|
|
3701
3783
|
import { join as join7 } from "node:path";
|
|
@@ -5166,7 +5248,8 @@ var TERMINATING_TOOL_NAMES = [
|
|
|
5166
5248
|
GLEANER_LEFT_OUTPUT_TOOL_NAME,
|
|
5167
5249
|
INSPECTOR_OUTPUT_TOOL_NAME,
|
|
5168
5250
|
GATEKEEPER_OUTPUT_TOOL_NAME,
|
|
5169
|
-
NAVIGATOR_OUTPUT_TOOL_NAME
|
|
5251
|
+
NAVIGATOR_OUTPUT_TOOL_NAME,
|
|
5252
|
+
DIARIST_OUTPUT_TOOL_NAME
|
|
5170
5253
|
];
|
|
5171
5254
|
function isTerminatingToolName(name) {
|
|
5172
5255
|
return TERMINATING_TOOL_NAMES.includes(name);
|
|
@@ -5212,7 +5295,8 @@ function validateAcceptedDetails(toolName, details) {
|
|
|
5212
5295
|
[GLEANER_LEFT_OUTPUT_TOOL_NAME]: ["completed"],
|
|
5213
5296
|
[INSPECTOR_OUTPUT_TOOL_NAME]: ["pass", "bounce"],
|
|
5214
5297
|
[GATEKEEPER_OUTPUT_TOOL_NAME]: ["dispatch", "pass"],
|
|
5215
|
-
[NAVIGATOR_OUTPUT_TOOL_NAME]: ["advice"]
|
|
5298
|
+
[NAVIGATOR_OUTPUT_TOOL_NAME]: ["advice"],
|
|
5299
|
+
[DIARIST_OUTPUT_TOOL_NAME]: ["completed"]
|
|
5216
5300
|
};
|
|
5217
5301
|
const collectorDiscriminator = toolName === COLLECTOR_OUTPUT_TOOL && Array.isArray(candidate?.groups);
|
|
5218
5302
|
const baseDiscriminator = discriminator;
|
|
@@ -5248,6 +5332,8 @@ function validateAcceptedDetails(toolName, details) {
|
|
|
5248
5332
|
return validateRecordedGatekeeperOutput(details);
|
|
5249
5333
|
case NAVIGATOR_OUTPUT_TOOL_NAME:
|
|
5250
5334
|
return validateRecordedNavigatorOutput(details);
|
|
5335
|
+
case DIARIST_OUTPUT_TOOL_NAME:
|
|
5336
|
+
return validateRecordedDiaristOutput(details);
|
|
5251
5337
|
}
|
|
5252
5338
|
} catch (error) {
|
|
5253
5339
|
if (error instanceof Error && error.constructor === Error) throw new AcceptedDetailsContractError(error.message, { cause: error });
|
|
@@ -5265,6 +5351,7 @@ function acceptedFacts(toolName, details) {
|
|
|
5265
5351
|
case INSPECTOR_OUTPUT_TOOL_NAME:
|
|
5266
5352
|
case GATEKEEPER_OUTPUT_TOOL_NAME:
|
|
5267
5353
|
case NAVIGATOR_OUTPUT_TOOL_NAME:
|
|
5354
|
+
case DIARIST_OUTPUT_TOOL_NAME:
|
|
5268
5355
|
return { status: details.status };
|
|
5269
5356
|
case JUDGE_OUTPUT_TOOL_NAME:
|
|
5270
5357
|
return { status: details.judgeStatus };
|
|
@@ -6571,6 +6658,10 @@ var COUNTERSIGN_OPTIONS = [
|
|
|
6571
6658
|
bindOwner("countersign", SHARED_PROJECT_SEMANTICS),
|
|
6572
6659
|
bindOwner("countersign", SHARED_ATTACH_SEMANTICS)
|
|
6573
6660
|
];
|
|
6661
|
+
var DIARIST_OPTIONS = [
|
|
6662
|
+
bindOwner("diarist", SHARED_PROJECT_SEMANTICS),
|
|
6663
|
+
bindOwner("diarist", SHARED_ATTACH_SEMANTICS)
|
|
6664
|
+
];
|
|
6574
6665
|
var CODER_OPTIONS = [
|
|
6575
6666
|
{
|
|
6576
6667
|
id: "phase",
|
|
@@ -6885,6 +6976,15 @@ var ROLE_COMMAND_HELP = {
|
|
|
6885
6976
|
'ak-role navigator "\u521A\u5B8C\u6210 coder apply \u6536\u655B\uFF0C\u4E0B\u4E00\u6B65\uFF1F"'
|
|
6886
6977
|
]
|
|
6887
6978
|
},
|
|
6979
|
+
diarist: {
|
|
6980
|
+
command: "diarist",
|
|
6981
|
+
summary: "Direct Diarist (\u8D77\u5C45\u90CE) pass: gather and organize this case's decision basis into its \u8D77\u5C45\u5F55.",
|
|
6982
|
+
usage: ["ak-role diarist [options] [instruction]"],
|
|
6983
|
+
examples: [
|
|
6984
|
+
'ak-role diarist "\u6574\u7406 #708 \u7684\u672C\u6848\u4F9D\u636E\u3002"',
|
|
6985
|
+
'ak-role diarist --attach ./design.md "\u8865\u5F55\u672C\u8F6E\u8BBE\u8BA1\u4FEE\u8BA2\u3002"'
|
|
6986
|
+
]
|
|
6987
|
+
},
|
|
6888
6988
|
notary: {
|
|
6889
6989
|
command: "notary",
|
|
6890
6990
|
summary: "Direct Notary document check (quote fidelity + ticket alignment); zero prompt/attachment.",
|
|
@@ -7053,7 +7153,7 @@ async function readRoleRunStateDisk(runDirectory) {
|
|
|
7053
7153
|
if (typeof record4.runId !== "string" || record4.runId.trim() === "") {
|
|
7054
7154
|
return void 0;
|
|
7055
7155
|
}
|
|
7056
|
-
if (record4.role !== "judge" && record4.role !== "coder" && record4.role !== "fixer" && record4.role !== "collector" && record4.role !== "doctor" && record4.role !== "reviewer" && record4.role !== "merger" && record4.role !== "notary" && record4.role !== "countersign" && record4.role !== "gleaner-left" && record4.role !== "inspector" && record4.role !== "gatekeeper" && record4.role !== "navigator") {
|
|
7156
|
+
if (record4.role !== "judge" && record4.role !== "coder" && record4.role !== "fixer" && record4.role !== "collector" && record4.role !== "doctor" && record4.role !== "reviewer" && record4.role !== "merger" && record4.role !== "notary" && record4.role !== "countersign" && record4.role !== "gleaner-left" && record4.role !== "inspector" && record4.role !== "gatekeeper" && record4.role !== "navigator" && record4.role !== "diarist") {
|
|
7057
7157
|
return void 0;
|
|
7058
7158
|
}
|
|
7059
7159
|
if (record4.state !== "admitted" && record4.state !== "running" && record4.state !== "resumable" && record4.state !== "terminal") {
|
|
@@ -11275,6 +11375,561 @@ var INSPECTOR_TOOL_SPEC = {
|
|
|
11275
11375
|
parameters: inspectorOutputSchema
|
|
11276
11376
|
};
|
|
11277
11377
|
|
|
11378
|
+
// src/diarist-role.ts
|
|
11379
|
+
import { Type as Type23 } from "typebox";
|
|
11380
|
+
var diaristOutputSchema = withInfrastructureFailureDeclaration(
|
|
11381
|
+
openToolObject(
|
|
11382
|
+
Type23.Object({
|
|
11383
|
+
status: Type23.Unknown({
|
|
11384
|
+
description: "completed \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8"
|
|
11385
|
+
}),
|
|
11386
|
+
selections: Type23.Array(
|
|
11387
|
+
Type23.Object(
|
|
11388
|
+
{
|
|
11389
|
+
candidateIndex: Type23.Number({ description: "\u5019\u9009\u76EE\u5F55\u4E2D\u7684\u6574\u5757\u5E8F\u53F7" }),
|
|
11390
|
+
quotes: Type23.Array(Type23.String(), {
|
|
11391
|
+
description: "\u8BE5\u5757 transcript \u5185\u7684\u8FDE\u7EED\u539F\u6587\uFF1B\u673A\u68B0\u53CD\u9A8C"
|
|
11392
|
+
}),
|
|
11393
|
+
note: Type23.Optional(
|
|
11394
|
+
Type23.String({ description: "\u8BE5\u6750\u6599\u4E0E\u672C\u6848\u7684\u5173\u7CFB\uFF08\u4EBA\u8BFB\uFF09" })
|
|
11395
|
+
)
|
|
11396
|
+
},
|
|
11397
|
+
{ additionalProperties: true, description: "\u4E00\u6761\u5165\u5F55\u9009\u62E9" }
|
|
11398
|
+
),
|
|
11399
|
+
{ description: "\u5165\u5F55\u9009\u62E9\uFF1B\u7A7A\u5217\u8868\u5408\u6CD5\u5B8C\u5C40" }
|
|
11400
|
+
)
|
|
11401
|
+
})
|
|
11402
|
+
)
|
|
11403
|
+
);
|
|
11404
|
+
var DIARIST_TOOL_SPEC = {
|
|
11405
|
+
name: DIARIST_OUTPUT_TOOL_NAME,
|
|
11406
|
+
label: "\u8D77\u5C45\u90CE\u8F93\u51FA",
|
|
11407
|
+
description: "\u8D77\u5C45\u90CE\u5165\u5F55\u9009\u62E9\u3002",
|
|
11408
|
+
promptSnippet: "\u8D77\u5C45\u90CE\u5165\u5F55\u9009\u62E9",
|
|
11409
|
+
parameters: diaristOutputSchema
|
|
11410
|
+
};
|
|
11411
|
+
|
|
11412
|
+
// src/diarist.ts
|
|
11413
|
+
import { readFileSync as readFileSync4 } from "node:fs";
|
|
11414
|
+
|
|
11415
|
+
// src/diarist-mechanical.ts
|
|
11416
|
+
init_activation_ledger_topology();
|
|
11417
|
+
var DEFAULT_QUOTE_MIN = 6;
|
|
11418
|
+
function extractCornerQuotes(text, minLength = DEFAULT_QUOTE_MIN) {
|
|
11419
|
+
const out = [];
|
|
11420
|
+
const re = /「([^」]+)」/g;
|
|
11421
|
+
let match;
|
|
11422
|
+
while ((match = re.exec(text)) !== null) {
|
|
11423
|
+
const q = match[1].trim();
|
|
11424
|
+
if (q.length >= minLength) out.push(q);
|
|
11425
|
+
}
|
|
11426
|
+
return out;
|
|
11427
|
+
}
|
|
11428
|
+
function buildDiaristAnchors(input) {
|
|
11429
|
+
const fromBody = input.ticketBody === void 0 ? [] : extractCornerQuotes(input.ticketBody);
|
|
11430
|
+
const quotes = [...fromBody, ...input.extraQuotes ?? []];
|
|
11431
|
+
const seen = /* @__PURE__ */ new Set();
|
|
11432
|
+
const uniqueQuotes = [];
|
|
11433
|
+
for (const q of quotes) {
|
|
11434
|
+
if (seen.has(q)) continue;
|
|
11435
|
+
seen.add(q);
|
|
11436
|
+
uniqueQuotes.push(q);
|
|
11437
|
+
}
|
|
11438
|
+
return {
|
|
11439
|
+
ticketNumber: input.ticketNumber,
|
|
11440
|
+
quotes: uniqueQuotes
|
|
11441
|
+
};
|
|
11442
|
+
}
|
|
11443
|
+
function verifyQuotesVerbatim(sourceText, quotes) {
|
|
11444
|
+
const failed2 = [];
|
|
11445
|
+
for (const q of quotes) {
|
|
11446
|
+
if (q.length === 0) continue;
|
|
11447
|
+
if (!sourceText.includes(q)) failed2.push(q);
|
|
11448
|
+
}
|
|
11449
|
+
if (failed2.length === 0) return { ok: true };
|
|
11450
|
+
return { ok: false, failedQuotes: failed2 };
|
|
11451
|
+
}
|
|
11452
|
+
function blockToLlmEntry(block, input) {
|
|
11453
|
+
const verify = verifyQuotesVerbatim(block.transcript, input.quotes);
|
|
11454
|
+
if (!verify.ok) {
|
|
11455
|
+
return {
|
|
11456
|
+
ok: false,
|
|
11457
|
+
failedQuotes: verify.failedQuotes,
|
|
11458
|
+
cause: `verbatim verify failed: ${verify.failedQuotes.join(" | ")}`
|
|
11459
|
+
};
|
|
11460
|
+
}
|
|
11461
|
+
const anchorNotes = [`#${input.anchors.ticketNumber}`];
|
|
11462
|
+
const seen = new Set(anchorNotes);
|
|
11463
|
+
for (const q of [...input.anchors.quotes, ...input.quotes]) {
|
|
11464
|
+
if (seen.has(q)) continue;
|
|
11465
|
+
seen.add(q);
|
|
11466
|
+
anchorNotes.push(q);
|
|
11467
|
+
if (anchorNotes.length >= 12) break;
|
|
11468
|
+
}
|
|
11469
|
+
return {
|
|
11470
|
+
ok: true,
|
|
11471
|
+
entry: {
|
|
11472
|
+
basis: {
|
|
11473
|
+
method: "llm-semantic",
|
|
11474
|
+
anchors: anchorNotes,
|
|
11475
|
+
...input.note === void 0 ? {} : { note: input.note }
|
|
11476
|
+
},
|
|
11477
|
+
sourceKind: block.sourceKind,
|
|
11478
|
+
sourceRef: block.sourceRef,
|
|
11479
|
+
transcript: block.transcript,
|
|
11480
|
+
timestamp: block.timestamp
|
|
11481
|
+
}
|
|
11482
|
+
};
|
|
11483
|
+
}
|
|
11484
|
+
|
|
11485
|
+
// src/ticket-provenance.ts
|
|
11486
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
11487
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync6 } from "node:fs";
|
|
11488
|
+
import { join as join22 } from "node:path";
|
|
11489
|
+
|
|
11490
|
+
// src/ticket-provenance-contracts.ts
|
|
11491
|
+
var TICKET_PROVENANCE_KIND = "ticket-provenance";
|
|
11492
|
+
var TICKET_PROVENANCE_HUMAN_VIEW = "\u8D77\u5C45\u5F55.md";
|
|
11493
|
+
var TICKET_PROVENANCE_OFFERED_WATERMARK = "offered-identities.jsonl";
|
|
11494
|
+
var TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC = "diagnostic";
|
|
11495
|
+
function isRecord13(value) {
|
|
11496
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
11497
|
+
}
|
|
11498
|
+
var SOURCE_KINDS = /* @__PURE__ */ new Set([
|
|
11499
|
+
"cc-session",
|
|
11500
|
+
"issue-body-comment",
|
|
11501
|
+
"adr-decision-key",
|
|
11502
|
+
"ticket-decree-block"
|
|
11503
|
+
]);
|
|
11504
|
+
var BASIS_METHODS = /* @__PURE__ */ new Set(["llm-semantic"]);
|
|
11505
|
+
var DIAGNOSTIC_KINDS = /* @__PURE__ */ new Set([
|
|
11506
|
+
"collector-failed",
|
|
11507
|
+
"issue-source-failed",
|
|
11508
|
+
"quote-verify-failed"
|
|
11509
|
+
]);
|
|
11510
|
+
function projectTicketProvenanceDiagnostic(value) {
|
|
11511
|
+
if (!isRecord13(value)) return void 0;
|
|
11512
|
+
if (value.recordClass !== TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC) {
|
|
11513
|
+
return void 0;
|
|
11514
|
+
}
|
|
11515
|
+
if (typeof value.diagnosticKind !== "string" || !DIAGNOSTIC_KINDS.has(value.diagnosticKind)) {
|
|
11516
|
+
return void 0;
|
|
11517
|
+
}
|
|
11518
|
+
if (typeof value.cause !== "string" || value.cause.length === 0) {
|
|
11519
|
+
return void 0;
|
|
11520
|
+
}
|
|
11521
|
+
if (typeof value.recordedAt !== "string" || value.recordedAt.length === 0) {
|
|
11522
|
+
return void 0;
|
|
11523
|
+
}
|
|
11524
|
+
return {
|
|
11525
|
+
recordClass: TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC,
|
|
11526
|
+
diagnosticKind: value.diagnosticKind,
|
|
11527
|
+
cause: value.cause,
|
|
11528
|
+
recordedAt: value.recordedAt,
|
|
11529
|
+
...typeof value.reason === "string" ? { reason: value.reason } : {}
|
|
11530
|
+
};
|
|
11531
|
+
}
|
|
11532
|
+
function projectTicketProvenanceEntry(value) {
|
|
11533
|
+
if (!isRecord13(value)) return void 0;
|
|
11534
|
+
if (value.recordClass === TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC) {
|
|
11535
|
+
return void 0;
|
|
11536
|
+
}
|
|
11537
|
+
if (!isRecord13(value.basis)) return void 0;
|
|
11538
|
+
if (typeof value.basis.method !== "string" || !BASIS_METHODS.has(value.basis.method)) {
|
|
11539
|
+
return void 0;
|
|
11540
|
+
}
|
|
11541
|
+
if (typeof value.sourceKind !== "string" || !SOURCE_KINDS.has(value.sourceKind)) {
|
|
11542
|
+
return void 0;
|
|
11543
|
+
}
|
|
11544
|
+
if (!isRecord13(value.sourceRef)) return void 0;
|
|
11545
|
+
if (typeof value.transcript !== "string" || value.transcript.length === 0) {
|
|
11546
|
+
return void 0;
|
|
11547
|
+
}
|
|
11548
|
+
if (typeof value.timestamp !== "string" || value.timestamp.length === 0) {
|
|
11549
|
+
return void 0;
|
|
11550
|
+
}
|
|
11551
|
+
const basis = {
|
|
11552
|
+
method: value.basis.method,
|
|
11553
|
+
...Array.isArray(value.basis.anchors) ? {
|
|
11554
|
+
anchors: value.basis.anchors.filter(
|
|
11555
|
+
(item) => typeof item === "string"
|
|
11556
|
+
)
|
|
11557
|
+
} : {},
|
|
11558
|
+
...typeof value.basis.note === "string" ? { note: value.basis.note } : {}
|
|
11559
|
+
};
|
|
11560
|
+
const sourceRef = {
|
|
11561
|
+
...typeof value.sourceRef.sessionFile === "string" ? { sessionFile: value.sourceRef.sessionFile } : {},
|
|
11562
|
+
...typeof value.sourceRef.entryId === "string" || typeof value.sourceRef.entryId === "number" ? { entryId: value.sourceRef.entryId } : {},
|
|
11563
|
+
...typeof value.sourceRef.path === "string" ? { path: value.sourceRef.path } : {},
|
|
11564
|
+
...typeof value.sourceRef.url === "string" ? { url: value.sourceRef.url } : {}
|
|
11565
|
+
};
|
|
11566
|
+
return {
|
|
11567
|
+
basis,
|
|
11568
|
+
sourceKind: value.sourceKind,
|
|
11569
|
+
sourceRef,
|
|
11570
|
+
transcript: value.transcript,
|
|
11571
|
+
timestamp: value.timestamp
|
|
11572
|
+
};
|
|
11573
|
+
}
|
|
11574
|
+
|
|
11575
|
+
// src/ticket-provenance.ts
|
|
11576
|
+
function ticketProvenanceSubject(ticketNumber) {
|
|
11577
|
+
if (!Number.isSafeInteger(ticketNumber) || ticketNumber < 1) {
|
|
11578
|
+
throw new Error(`ticket-provenance subject requires a positive ticket number, got ${String(ticketNumber)}`);
|
|
11579
|
+
}
|
|
11580
|
+
return String(ticketNumber);
|
|
11581
|
+
}
|
|
11582
|
+
function ticketProvenanceEntryIdentity(input) {
|
|
11583
|
+
const ref = input.sourceRef;
|
|
11584
|
+
const refKey = [
|
|
11585
|
+
ref.sessionFile ?? "",
|
|
11586
|
+
ref.entryId === void 0 ? "" : String(ref.entryId),
|
|
11587
|
+
ref.path ?? "",
|
|
11588
|
+
ref.url ?? ""
|
|
11589
|
+
].join("");
|
|
11590
|
+
const material = [
|
|
11591
|
+
String(input.ticketNumber),
|
|
11592
|
+
input.sourceKind,
|
|
11593
|
+
refKey,
|
|
11594
|
+
input.transcript
|
|
11595
|
+
].join("\0");
|
|
11596
|
+
return createHash9("sha256").update(material, "utf8").digest("hex");
|
|
11597
|
+
}
|
|
11598
|
+
function appendTicketProvenanceEntry(input) {
|
|
11599
|
+
const subject = ticketProvenanceSubject(input.ticketNumber);
|
|
11600
|
+
const identity = ticketProvenanceEntryIdentity({
|
|
11601
|
+
ticketNumber: input.ticketNumber,
|
|
11602
|
+
sourceKind: input.entry.sourceKind,
|
|
11603
|
+
sourceRef: input.entry.sourceRef,
|
|
11604
|
+
transcript: input.entry.transcript
|
|
11605
|
+
});
|
|
11606
|
+
return sitianReport({
|
|
11607
|
+
level: "event",
|
|
11608
|
+
kind: TICKET_PROVENANCE_KIND,
|
|
11609
|
+
identity,
|
|
11610
|
+
subject,
|
|
11611
|
+
cwd: input.cwd,
|
|
11612
|
+
...input.home === void 0 ? {} : { home: input.home },
|
|
11613
|
+
host: input.host ?? "diarist",
|
|
11614
|
+
source: input.source ?? "diarist",
|
|
11615
|
+
payload: input.entry,
|
|
11616
|
+
raw: input.entry.sourceRef.sessionFile !== void 0 && input.entry.sourceRef.entryId !== void 0 ? {
|
|
11617
|
+
sessionFile: input.entry.sourceRef.sessionFile,
|
|
11618
|
+
entryId: input.entry.sourceRef.entryId
|
|
11619
|
+
} : void 0
|
|
11620
|
+
});
|
|
11621
|
+
}
|
|
11622
|
+
function resolveTicketProvenanceVolume(ticketNumber, cwd, home) {
|
|
11623
|
+
const path = resolveSitianRecordPath({
|
|
11624
|
+
level: "event",
|
|
11625
|
+
kind: TICKET_PROVENANCE_KIND,
|
|
11626
|
+
subject: ticketProvenanceSubject(ticketNumber),
|
|
11627
|
+
cwd,
|
|
11628
|
+
...home === void 0 ? {} : { home }
|
|
11629
|
+
});
|
|
11630
|
+
return {
|
|
11631
|
+
recordFile: path.recordFile,
|
|
11632
|
+
volumeDir: path.sessionDir,
|
|
11633
|
+
humanViewFile: join22(path.sessionDir, TICKET_PROVENANCE_HUMAN_VIEW),
|
|
11634
|
+
offeredWatermarkFile: join22(path.sessionDir, TICKET_PROVENANCE_OFFERED_WATERMARK)
|
|
11635
|
+
};
|
|
11636
|
+
}
|
|
11637
|
+
var TicketProvenanceWatermarkError = class extends Error {
|
|
11638
|
+
code = "ticket-provenance-watermark";
|
|
11639
|
+
reason;
|
|
11640
|
+
constructor(reason, message, options) {
|
|
11641
|
+
super(message, options);
|
|
11642
|
+
this.name = "TicketProvenanceWatermarkError";
|
|
11643
|
+
this.reason = reason;
|
|
11644
|
+
}
|
|
11645
|
+
};
|
|
11646
|
+
function readOfferedIdentities(ticketNumber, cwd, home) {
|
|
11647
|
+
const { offeredWatermarkFile } = resolveTicketProvenanceVolume(ticketNumber, cwd, home);
|
|
11648
|
+
if (!existsSync7(offeredWatermarkFile)) return /* @__PURE__ */ new Set();
|
|
11649
|
+
let text;
|
|
11650
|
+
try {
|
|
11651
|
+
text = readFileSync3(offeredWatermarkFile, "utf8");
|
|
11652
|
+
} catch (error) {
|
|
11653
|
+
throw new TicketProvenanceWatermarkError(
|
|
11654
|
+
"unreadable",
|
|
11655
|
+
`ticket-provenance offered watermark unreadable (${offeredWatermarkFile})`,
|
|
11656
|
+
{ cause: error }
|
|
11657
|
+
);
|
|
11658
|
+
}
|
|
11659
|
+
const seen = /* @__PURE__ */ new Set();
|
|
11660
|
+
const lines = text.split("\n");
|
|
11661
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
11662
|
+
const trimmed = lines[index].trim();
|
|
11663
|
+
if (!trimmed) continue;
|
|
11664
|
+
let parsed;
|
|
11665
|
+
try {
|
|
11666
|
+
parsed = JSON.parse(trimmed);
|
|
11667
|
+
} catch (error) {
|
|
11668
|
+
throw new TicketProvenanceWatermarkError(
|
|
11669
|
+
"malformed-json",
|
|
11670
|
+
`ticket-provenance offered watermark malformed JSON at line ${index + 1} (${offeredWatermarkFile})`,
|
|
11671
|
+
{ cause: error }
|
|
11672
|
+
);
|
|
11673
|
+
}
|
|
11674
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed) || typeof parsed.identity !== "string" || parsed.identity.length === 0) {
|
|
11675
|
+
throw new TicketProvenanceWatermarkError(
|
|
11676
|
+
"bad-shape",
|
|
11677
|
+
`ticket-provenance offered watermark bad shape at line ${index + 1} (${offeredWatermarkFile})`
|
|
11678
|
+
);
|
|
11679
|
+
}
|
|
11680
|
+
seen.add(parsed.identity);
|
|
11681
|
+
}
|
|
11682
|
+
return seen;
|
|
11683
|
+
}
|
|
11684
|
+
function recordOfferedIdentities(input) {
|
|
11685
|
+
if (input.identities.length === 0) return;
|
|
11686
|
+
const { volumeDir, offeredWatermarkFile } = resolveTicketProvenanceVolume(
|
|
11687
|
+
input.ticketNumber,
|
|
11688
|
+
input.cwd,
|
|
11689
|
+
input.home
|
|
11690
|
+
);
|
|
11691
|
+
const already = new Set(readOfferedIdentities(input.ticketNumber, input.cwd, input.home));
|
|
11692
|
+
const rows = [];
|
|
11693
|
+
for (const identity of input.identities) {
|
|
11694
|
+
if (identity.length === 0 || already.has(identity)) continue;
|
|
11695
|
+
rows.push(`${JSON.stringify({ identity })}
|
|
11696
|
+
`);
|
|
11697
|
+
already.add(identity);
|
|
11698
|
+
}
|
|
11699
|
+
if (rows.length === 0) return;
|
|
11700
|
+
mkdirSync3(volumeDir, { recursive: true });
|
|
11701
|
+
appendFileSync2(offeredWatermarkFile, rows.join(""), "utf8");
|
|
11702
|
+
}
|
|
11703
|
+
async function readTicketProvenance(ticketNumber, cwd, home) {
|
|
11704
|
+
const { recordFile } = resolveTicketProvenanceVolume(ticketNumber, cwd, home);
|
|
11705
|
+
const { records: records2 } = await readSitianRecords(recordFile);
|
|
11706
|
+
const entries = [];
|
|
11707
|
+
const diagnostics = [];
|
|
11708
|
+
let skipped = 0;
|
|
11709
|
+
for (const record4 of records2) {
|
|
11710
|
+
if (record4.kind !== TICKET_PROVENANCE_KIND) {
|
|
11711
|
+
skipped += 1;
|
|
11712
|
+
continue;
|
|
11713
|
+
}
|
|
11714
|
+
const diagnostic = projectTicketProvenanceDiagnostic(record4.payload);
|
|
11715
|
+
if (diagnostic !== void 0) {
|
|
11716
|
+
diagnostics.push(diagnostic);
|
|
11717
|
+
continue;
|
|
11718
|
+
}
|
|
11719
|
+
const entry = projectTicketProvenanceEntry(record4.payload);
|
|
11720
|
+
if (entry === void 0) {
|
|
11721
|
+
skipped += 1;
|
|
11722
|
+
continue;
|
|
11723
|
+
}
|
|
11724
|
+
entries.push(entry);
|
|
11725
|
+
}
|
|
11726
|
+
return { entries, diagnostics, records: records2, recordFile, skipped };
|
|
11727
|
+
}
|
|
11728
|
+
function markdownFenceFor(text) {
|
|
11729
|
+
let longest = 0;
|
|
11730
|
+
const runs = text.match(/`+/g);
|
|
11731
|
+
if (runs !== null) {
|
|
11732
|
+
for (const run of runs) {
|
|
11733
|
+
if (run.length > longest) longest = run.length;
|
|
11734
|
+
}
|
|
11735
|
+
}
|
|
11736
|
+
return "`".repeat(Math.max(3, longest + 1));
|
|
11737
|
+
}
|
|
11738
|
+
function renderTicketProvenanceMarkdown(input) {
|
|
11739
|
+
const lines = [
|
|
11740
|
+
`# \u8D77\u5C45\u5F55 \xB7 #${input.ticketNumber}`,
|
|
11741
|
+
"",
|
|
11742
|
+
`\u6761\u76EE\u6570\uFF1A${input.entries.length}`,
|
|
11743
|
+
""
|
|
11744
|
+
];
|
|
11745
|
+
let index = 0;
|
|
11746
|
+
for (const entry of input.entries) {
|
|
11747
|
+
index += 1;
|
|
11748
|
+
lines.push(`## ${index}. ${entry.sourceKind} \xB7 ${entry.timestamp}`);
|
|
11749
|
+
lines.push("");
|
|
11750
|
+
lines.push(`- basis.method: \`${entry.basis.method}\``);
|
|
11751
|
+
if (entry.basis.anchors !== void 0 && entry.basis.anchors.length > 0) {
|
|
11752
|
+
lines.push(`- anchors: ${entry.basis.anchors.map((a) => `\`${a}\``).join(", ")}`);
|
|
11753
|
+
}
|
|
11754
|
+
if (entry.basis.note !== void 0) {
|
|
11755
|
+
lines.push(`- note: ${entry.basis.note}`);
|
|
11756
|
+
}
|
|
11757
|
+
const refParts = [];
|
|
11758
|
+
if (entry.sourceRef.sessionFile !== void 0) {
|
|
11759
|
+
refParts.push(`sessionFile=${entry.sourceRef.sessionFile}`);
|
|
11760
|
+
}
|
|
11761
|
+
if (entry.sourceRef.entryId !== void 0) {
|
|
11762
|
+
refParts.push(`entryId=${String(entry.sourceRef.entryId)}`);
|
|
11763
|
+
}
|
|
11764
|
+
if (entry.sourceRef.path !== void 0) {
|
|
11765
|
+
refParts.push(`path=${entry.sourceRef.path}`);
|
|
11766
|
+
}
|
|
11767
|
+
if (entry.sourceRef.url !== void 0) {
|
|
11768
|
+
refParts.push(`url=${entry.sourceRef.url}`);
|
|
11769
|
+
}
|
|
11770
|
+
if (refParts.length > 0) {
|
|
11771
|
+
lines.push(`- sourceRef: ${refParts.join(" \xB7 ")}`);
|
|
11772
|
+
}
|
|
11773
|
+
lines.push("");
|
|
11774
|
+
const fence = markdownFenceFor(entry.transcript);
|
|
11775
|
+
lines.push(fence);
|
|
11776
|
+
lines.push(entry.transcript);
|
|
11777
|
+
lines.push(fence);
|
|
11778
|
+
lines.push("");
|
|
11779
|
+
}
|
|
11780
|
+
return lines.join("\n");
|
|
11781
|
+
}
|
|
11782
|
+
function ensureTicketProvenanceVolume(ticketNumber, cwd, home) {
|
|
11783
|
+
const volume = resolveTicketProvenanceVolume(ticketNumber, cwd, home);
|
|
11784
|
+
mkdirSync3(volume.volumeDir, { recursive: true });
|
|
11785
|
+
appendFileSync2(volume.recordFile, "", "utf8");
|
|
11786
|
+
return volume;
|
|
11787
|
+
}
|
|
11788
|
+
function appendTicketProvenanceDiagnostic(input) {
|
|
11789
|
+
const subject = ticketProvenanceSubject(input.ticketNumber);
|
|
11790
|
+
const identityParts = input.diagnostic.diagnosticKind === "quote-verify-failed" ? [
|
|
11791
|
+
subject,
|
|
11792
|
+
input.diagnostic.recordClass,
|
|
11793
|
+
input.diagnostic.diagnosticKind,
|
|
11794
|
+
input.diagnostic.cause,
|
|
11795
|
+
input.diagnostic.reason ?? ""
|
|
11796
|
+
] : [
|
|
11797
|
+
subject,
|
|
11798
|
+
input.diagnostic.recordClass,
|
|
11799
|
+
input.diagnostic.diagnosticKind,
|
|
11800
|
+
input.diagnostic.recordedAt,
|
|
11801
|
+
input.diagnostic.cause,
|
|
11802
|
+
input.diagnostic.reason ?? ""
|
|
11803
|
+
];
|
|
11804
|
+
const identity = createHash9("sha256").update(identityParts.join("\0"), "utf8").digest("hex");
|
|
11805
|
+
return sitianReport({
|
|
11806
|
+
level: "event",
|
|
11807
|
+
kind: TICKET_PROVENANCE_KIND,
|
|
11808
|
+
identity,
|
|
11809
|
+
subject,
|
|
11810
|
+
cwd: input.cwd,
|
|
11811
|
+
...input.home === void 0 ? {} : { home: input.home },
|
|
11812
|
+
host: input.host ?? "diarist",
|
|
11813
|
+
source: input.source ?? "diarist-diagnostic",
|
|
11814
|
+
payload: input.diagnostic
|
|
11815
|
+
});
|
|
11816
|
+
}
|
|
11817
|
+
function appendQuoteVerifyFailureDiagnostic(input) {
|
|
11818
|
+
const recordedAt = input.recordedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
11819
|
+
return appendTicketProvenanceDiagnostic({
|
|
11820
|
+
ticketNumber: input.ticketNumber,
|
|
11821
|
+
cwd: input.cwd,
|
|
11822
|
+
...input.home === void 0 ? {} : { home: input.home },
|
|
11823
|
+
source: "diarist-quote-verify",
|
|
11824
|
+
diagnostic: {
|
|
11825
|
+
recordClass: TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC,
|
|
11826
|
+
diagnosticKind: "quote-verify-failed",
|
|
11827
|
+
cause: input.cause,
|
|
11828
|
+
recordedAt
|
|
11829
|
+
}
|
|
11830
|
+
});
|
|
11831
|
+
}
|
|
11832
|
+
function writeTicketProvenanceHumanView(input) {
|
|
11833
|
+
const volume = ensureTicketProvenanceVolume(input.ticketNumber, input.cwd, input.home);
|
|
11834
|
+
const md = renderTicketProvenanceMarkdown({
|
|
11835
|
+
ticketNumber: input.ticketNumber,
|
|
11836
|
+
entries: input.entries
|
|
11837
|
+
});
|
|
11838
|
+
writeFileSync6(volume.humanViewFile, md, "utf8");
|
|
11839
|
+
return volume.humanViewFile;
|
|
11840
|
+
}
|
|
11841
|
+
|
|
11842
|
+
// src/diarist.ts
|
|
11843
|
+
function blockEntryIdentity(ticketNumber, block) {
|
|
11844
|
+
return ticketProvenanceEntryIdentity({
|
|
11845
|
+
ticketNumber,
|
|
11846
|
+
sourceKind: block.sourceKind,
|
|
11847
|
+
sourceRef: block.sourceRef,
|
|
11848
|
+
transcript: block.transcript
|
|
11849
|
+
});
|
|
11850
|
+
}
|
|
11851
|
+
function loadDiaristSourceCatalog(path) {
|
|
11852
|
+
const parsed = JSON.parse(readFileSync4(path, "utf8"));
|
|
11853
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
11854
|
+
throw new Error(`diarist source catalog is not an object (${path})`);
|
|
11855
|
+
}
|
|
11856
|
+
const record4 = parsed;
|
|
11857
|
+
if (typeof record4.ticketNumber !== "number" || typeof record4.cwd !== "string") {
|
|
11858
|
+
throw new Error(`diarist source catalog is missing ticket coordinates (${path})`);
|
|
11859
|
+
}
|
|
11860
|
+
if (!Array.isArray(record4.candidates)) {
|
|
11861
|
+
throw new Error(`diarist source catalog is missing candidates (${path})`);
|
|
11862
|
+
}
|
|
11863
|
+
return parsed;
|
|
11864
|
+
}
|
|
11865
|
+
async function commitDiaristSelections(input) {
|
|
11866
|
+
const { ticketNumber, cwd } = input.catalog;
|
|
11867
|
+
const homeOpt = input.catalog.home === void 0 ? {} : { home: input.catalog.home };
|
|
11868
|
+
const volumePaths = ensureTicketProvenanceVolume(ticketNumber, cwd, input.catalog.home);
|
|
11869
|
+
const anchors = buildDiaristAnchors({ ticketNumber });
|
|
11870
|
+
const before = await readTicketProvenance(ticketNumber, cwd, input.catalog.home);
|
|
11871
|
+
let acceptedRows = 0;
|
|
11872
|
+
let rejectedQuotes = 0;
|
|
11873
|
+
let unknownCandidate = false;
|
|
11874
|
+
for (const selection of input.selections) {
|
|
11875
|
+
const block = input.catalog.candidates[selection.candidateIndex];
|
|
11876
|
+
if (block === void 0) {
|
|
11877
|
+
unknownCandidate = true;
|
|
11878
|
+
continue;
|
|
11879
|
+
}
|
|
11880
|
+
const projected = blockToLlmEntry(block, {
|
|
11881
|
+
anchors,
|
|
11882
|
+
quotes: selection.quotes,
|
|
11883
|
+
...selection.note === void 0 ? {} : { note: selection.note }
|
|
11884
|
+
});
|
|
11885
|
+
if (!projected.ok) {
|
|
11886
|
+
rejectedQuotes += 1;
|
|
11887
|
+
appendQuoteVerifyFailureDiagnostic({
|
|
11888
|
+
ticketNumber,
|
|
11889
|
+
cwd,
|
|
11890
|
+
...homeOpt,
|
|
11891
|
+
cause: projected.cause
|
|
11892
|
+
});
|
|
11893
|
+
continue;
|
|
11894
|
+
}
|
|
11895
|
+
appendTicketProvenanceEntry({
|
|
11896
|
+
ticketNumber,
|
|
11897
|
+
cwd,
|
|
11898
|
+
...homeOpt,
|
|
11899
|
+
entry: projected.entry,
|
|
11900
|
+
source: "diarist"
|
|
11901
|
+
});
|
|
11902
|
+
acceptedRows += 1;
|
|
11903
|
+
}
|
|
11904
|
+
const identities = input.catalog.candidates.map(
|
|
11905
|
+
(block) => blockEntryIdentity(ticketNumber, block)
|
|
11906
|
+
);
|
|
11907
|
+
const alreadyWatermarked = readOfferedIdentities(ticketNumber, cwd, input.catalog.home);
|
|
11908
|
+
const watermarked = identities.filter((identity) => !alreadyWatermarked.has(identity)).length;
|
|
11909
|
+
recordOfferedIdentities({ ticketNumber, cwd, ...homeOpt, identities });
|
|
11910
|
+
const volume = await readTicketProvenance(ticketNumber, cwd, input.catalog.home);
|
|
11911
|
+
const humanViewFile = writeTicketProvenanceHumanView({
|
|
11912
|
+
ticketNumber,
|
|
11913
|
+
cwd,
|
|
11914
|
+
...homeOpt,
|
|
11915
|
+
entries: volume.entries
|
|
11916
|
+
});
|
|
11917
|
+
return {
|
|
11918
|
+
ticketNumber,
|
|
11919
|
+
offered: input.catalog.candidates.length,
|
|
11920
|
+
appended: volume.entries.length - before.entries.length,
|
|
11921
|
+
rejectedQuotes,
|
|
11922
|
+
watermarked,
|
|
11923
|
+
volumeRecordFile: volumePaths.recordFile,
|
|
11924
|
+
humanViewFile,
|
|
11925
|
+
collectorStatus: input.catalog.candidates.length === 0 ? "skipped-no-fresh" : acceptedRows > 0 ? "ok" : input.selections.length === 0 ? "empty-selection" : "nothing-appended",
|
|
11926
|
+
failureCauses: [
|
|
11927
|
+
...unknownCandidate ? ["unknown-candidate"] : [],
|
|
11928
|
+
...rejectedQuotes > 0 ? ["quote-verify-rejected"] : []
|
|
11929
|
+
]
|
|
11930
|
+
};
|
|
11931
|
+
}
|
|
11932
|
+
|
|
11278
11933
|
// src/navigator-role.ts
|
|
11279
11934
|
var NAVIGATOR_TOOL_SPEC = {
|
|
11280
11935
|
name: NAVIGATOR_OUTPUT_TOOL_NAME,
|
|
@@ -11326,30 +11981,30 @@ function raceNavigatorGrace(work, graceMs = NAVIGATOR_POST_ROLE_GRACE_MS, sleep
|
|
|
11326
11981
|
}
|
|
11327
11982
|
|
|
11328
11983
|
// src/judge-role.ts
|
|
11329
|
-
import { Type as
|
|
11984
|
+
import { Type as Type24 } from "typebox";
|
|
11330
11985
|
var judgeVerdictSchema = withInfrastructureFailureDeclaration(
|
|
11331
|
-
|
|
11986
|
+
Type24.Object(
|
|
11332
11987
|
{
|
|
11333
11988
|
judgeStatus: stringEnum(["converged", "continue", "escalate"], { description: "converged | continue | escalate \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8" }),
|
|
11334
|
-
fix:
|
|
11335
|
-
|
|
11336
|
-
{ summary:
|
|
11989
|
+
fix: Type24.Optional(
|
|
11990
|
+
Type24.Object(
|
|
11991
|
+
{ summary: Type24.String({ minLength: 1, description: "continue \u65F6\u7684\u8865\u6551\u6458\u8981" }) },
|
|
11337
11992
|
{ additionalProperties: false, description: "continue \u65F6\u7684\u8865\u6551\u8BF4\u660E" }
|
|
11338
11993
|
)
|
|
11339
11994
|
),
|
|
11340
|
-
classes:
|
|
11341
|
-
name:
|
|
11342
|
-
owner:
|
|
11343
|
-
boundary:
|
|
11344
|
-
disposition:
|
|
11995
|
+
classes: Type24.Optional(Type24.Array(Type24.Object({
|
|
11996
|
+
name: Type24.String({ minLength: 1 }),
|
|
11997
|
+
owner: Type24.String({ minLength: 1 }),
|
|
11998
|
+
boundary: Type24.String({ minLength: 1 }),
|
|
11999
|
+
disposition: Type24.String({ minLength: 1 })
|
|
11345
12000
|
}, { additionalProperties: false }), { minItems: 1, description: "\u5DF2\u88C1\u51B3 finding \u7C7B\u53CA\u5176 owner \u4E0E\u4FEE\u7406\u8FB9\u754C" })),
|
|
11346
|
-
note:
|
|
11347
|
-
evidence:
|
|
11348
|
-
decisionGate:
|
|
11349
|
-
|
|
12001
|
+
note: Type24.Optional(Type24.String({ minLength: 1, description: "\u53EF\u9009\u88C1\u51B3\u9644\u6CE8" })),
|
|
12002
|
+
evidence: Type24.Optional(Type24.Unknown({ description: "\u7559\u5B58\u7684\u88C1\u51B3\u8BC1\u636E" })),
|
|
12003
|
+
decisionGate: Type24.Optional(
|
|
12004
|
+
Type24.Object(
|
|
11350
12005
|
{
|
|
11351
|
-
question:
|
|
11352
|
-
options:
|
|
12006
|
+
question: Type24.String({ minLength: 1 }),
|
|
12007
|
+
options: Type24.Array(Type24.String({ minLength: 1 }), { minItems: 1 })
|
|
11353
12008
|
},
|
|
11354
12009
|
{ additionalProperties: false, description: "\u9700\u4EBA\u6743\u5A01\u5904\u7F6E\u7684\u95EE\u9898\u4E0E\u9009\u9879" }
|
|
11355
12010
|
)
|
|
@@ -11439,7 +12094,7 @@ ${soul}
|
|
|
11439
12094
|
}
|
|
11440
12095
|
|
|
11441
12096
|
// src/reviewer-role.ts
|
|
11442
|
-
import { Type as
|
|
12097
|
+
import { Type as Type25 } from "typebox";
|
|
11443
12098
|
|
|
11444
12099
|
// src/reviewer-execution-ledger.ts
|
|
11445
12100
|
function projectAcceptedDispatch(dispatch) {
|
|
@@ -11645,19 +12300,19 @@ function assembleRuntimeReviewerReceipt(input) {
|
|
|
11645
12300
|
}
|
|
11646
12301
|
|
|
11647
12302
|
// src/reviewer-role.ts
|
|
11648
|
-
var reviewerAmendmentsSchema =
|
|
11649
|
-
standards:
|
|
11650
|
-
spec:
|
|
12303
|
+
var reviewerAmendmentsSchema = Type25.Object({
|
|
12304
|
+
standards: Type25.Optional(Type25.String({ description: "\u76F8\u5BF9 Standards \u5B50\u62A5\u544A\u7684\u589E\u91CF\uFF1A\u589E finding\u3001\u64A4\u56DE\u6216\u4E8B\u5B9E\u66F4\u6B63" })),
|
|
12305
|
+
spec: Type25.Optional(Type25.String({ description: "\u76F8\u5BF9 Spec \u5B50\u62A5\u544A\u7684\u589E\u91CF\uFF1A\u589E finding\u3001\u64A4\u56DE\u6216\u4E8B\u5B9E\u66F4\u6B63" }))
|
|
11651
12306
|
}, { additionalProperties: true, description: "\u76F8\u5BF9\u5B50\u62A5\u544A\u7684\u53EF\u9009\u8F74\u589E\u91CF\uFF1B\u975E\u66FF\u4EE3\u62A5\u544A\u3002\u65E0\u589E\u91CF\u7684\u8F74\u53EF\u7701\u7565\u3002" });
|
|
11652
|
-
var reviewerOutputVariants =
|
|
11653
|
-
|
|
11654
|
-
status:
|
|
11655
|
-
amendments:
|
|
12307
|
+
var reviewerOutputVariants = Type25.Union([
|
|
12308
|
+
Type25.Object({
|
|
12309
|
+
status: Type25.Literal("completed", { description: "completed \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8" }),
|
|
12310
|
+
amendments: Type25.Optional(reviewerAmendmentsSchema)
|
|
11656
12311
|
}, { additionalProperties: false }),
|
|
11657
|
-
|
|
11658
|
-
status:
|
|
11659
|
-
diagnostic:
|
|
11660
|
-
amendments:
|
|
12312
|
+
Type25.Object({
|
|
12313
|
+
status: Type25.Literal("refused", { description: "refused \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8" }),
|
|
12314
|
+
diagnostic: Type25.String({ minLength: 1, description: "\u62D2\u7EDD\u8BCA\u65AD\u8BF4\u660E" }),
|
|
12315
|
+
amendments: Type25.Optional(reviewerAmendmentsSchema)
|
|
11661
12316
|
}, { additionalProperties: false })
|
|
11662
12317
|
]);
|
|
11663
12318
|
var reviewerOutputSchema = withInfrastructureFailureDeclaration(
|
|
@@ -11785,12 +12440,12 @@ function createReviewerRoleRuntime(pi, dependencies, hostActions) {
|
|
|
11785
12440
|
}
|
|
11786
12441
|
|
|
11787
12442
|
// src/worker-role.ts
|
|
11788
|
-
import { Type as
|
|
12443
|
+
import { Type as Type26 } from "typebox";
|
|
11789
12444
|
|
|
11790
12445
|
// src/worker-submission-gates.ts
|
|
11791
12446
|
init_archivist_record_entry();
|
|
11792
12447
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
11793
|
-
import { existsSync as
|
|
12448
|
+
import { existsSync as existsSync8, lstatSync as lstatSync3, readdirSync as readdirSync2, readFileSync as readFileSync5, rmdirSync, rmSync } from "node:fs";
|
|
11794
12449
|
import { resolve as resolve16 } from "node:path";
|
|
11795
12450
|
var WORKER_SUBMISSION_GATE_RECORD_KIND = WORKER_SUBMISSION_GATE_KIND;
|
|
11796
12451
|
var WORKER_COMMIT_BASELINE_ENTRY_TYPE = "commit-baseline";
|
|
@@ -11821,7 +12476,7 @@ function statusOf(error) {
|
|
|
11821
12476
|
return typeof error === "object" && error !== null && "status" in error ? error.status : void 0;
|
|
11822
12477
|
}
|
|
11823
12478
|
function tryGetAll(file, key) {
|
|
11824
|
-
if (!
|
|
12479
|
+
if (!existsSync8(file)) return [];
|
|
11825
12480
|
try {
|
|
11826
12481
|
const out = gitFile(file, ["--get-all", key]);
|
|
11827
12482
|
return out.length === 0 ? [] : out.split("\n");
|
|
@@ -11831,8 +12486,8 @@ function tryGetAll(file, key) {
|
|
|
11831
12486
|
}
|
|
11832
12487
|
}
|
|
11833
12488
|
function ownedHook(path) {
|
|
11834
|
-
if (!
|
|
11835
|
-
return
|
|
12489
|
+
if (!existsSync8(path)) return false;
|
|
12490
|
+
return readFileSync5(path, "utf8").includes(HOOK_MARKER);
|
|
11836
12491
|
}
|
|
11837
12492
|
function escapeGitConfigValueRegex(value) {
|
|
11838
12493
|
return value.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&");
|
|
@@ -11858,11 +12513,11 @@ function rmOwnedDir(dir) {
|
|
|
11858
12513
|
const hookPath = resolve16(dir, HOOK_FILE);
|
|
11859
12514
|
if (!ownedHook(hookPath)) return;
|
|
11860
12515
|
rmSync(hookPath, { force: true });
|
|
11861
|
-
if (
|
|
12516
|
+
if (existsSync8(dir) && readdirSync2(dir).length === 0) rmdirSync(dir);
|
|
11862
12517
|
}
|
|
11863
12518
|
function linkedGitDirs(commonDir) {
|
|
11864
12519
|
const root = resolve16(commonDir, "worktrees");
|
|
11865
|
-
if (!
|
|
12520
|
+
if (!existsSync8(root)) return [];
|
|
11866
12521
|
return readdirSync2(root).map((name) => resolve16(root, name)).filter((dir) => lstatSync3(dir).isDirectory());
|
|
11867
12522
|
}
|
|
11868
12523
|
function uninstallPackageWorkerHooks(cwd) {
|
|
@@ -11887,7 +12542,7 @@ function uninstallPackageWorkerHooks(cwd) {
|
|
|
11887
12542
|
rmOwnedDir(resolve16(gitDir, HOOKS_DIR));
|
|
11888
12543
|
}
|
|
11889
12544
|
}
|
|
11890
|
-
function
|
|
12545
|
+
function isRecord14(value) {
|
|
11891
12546
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
11892
12547
|
}
|
|
11893
12548
|
function unfinishedReasonPresent(details) {
|
|
@@ -11903,7 +12558,7 @@ function readGateState(session) {
|
|
|
11903
12558
|
if (entry.type !== "custom") continue;
|
|
11904
12559
|
if (entry.customType === WORKER_COMMIT_BASELINE_ENTRY_TYPE) {
|
|
11905
12560
|
const data = entry.data;
|
|
11906
|
-
if (
|
|
12561
|
+
if (isRecord14(data) && (data.head === null || typeof data.head === "string")) {
|
|
11907
12562
|
baseline = data.head;
|
|
11908
12563
|
}
|
|
11909
12564
|
} else if (entry.customType === WORKER_COMMIT_REMINDER_BOUNCE_ENTRY_TYPE) {
|
|
@@ -12046,24 +12701,24 @@ function fixerBashSeatbeltDenyReason(matched) {
|
|
|
12046
12701
|
}
|
|
12047
12702
|
|
|
12048
12703
|
// src/worker-role.ts
|
|
12049
|
-
var coderOutputVariants =
|
|
12050
|
-
|
|
12704
|
+
var coderOutputVariants = Type26.Union([
|
|
12705
|
+
Type26.Object({
|
|
12051
12706
|
status: stringEnum(["planned"], { description: "planned \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8" }),
|
|
12052
|
-
report:
|
|
12707
|
+
report: Type26.String({ minLength: 1, description: "\u5982\u5B9E\u7ED3\u679C\u62A5\u544A" })
|
|
12053
12708
|
}, { additionalProperties: false }),
|
|
12054
|
-
|
|
12709
|
+
Type26.Object({
|
|
12055
12710
|
status: stringEnum(["completed", "refused"], {
|
|
12056
12711
|
description: "completed | refused \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\uFF1Bcompleted \u56DE\u6267\u542B TDD\u3001\u540C\u6A21\u5F0F\u3001\u5F15\u5165\u56DE\u5F52\u3001\u884C\u4E3A\u4E8B\u5B9E\u56DB\u9879\u8BC1\u636E"
|
|
12057
12712
|
}),
|
|
12058
|
-
report:
|
|
12713
|
+
report: Type26.String({ minLength: 1, description: "\u5982\u5B9E\u7ED3\u679C\u62A5\u544A" })
|
|
12059
12714
|
}, { additionalProperties: false }),
|
|
12060
|
-
|
|
12715
|
+
Type26.Object({
|
|
12061
12716
|
status: stringEnum(["unfinished"], {
|
|
12062
12717
|
description: "unfinished \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\uFF1B\u7F3A\u524D\u7F6E\u6216\u8FDD\u5BAA\u7EA6\u675F\u81F4\u672C\u5C40\u672A\u5B8C\u6210\u65F6\u53EF\u7528\u3002\u7F3A\u5F85\u51B3 owner \u51B3\u5B9A\u6216\u7B54\u590D\u5C5E\u7F3A\u524D\u7F6E\u3002"
|
|
12063
12718
|
}),
|
|
12064
|
-
report:
|
|
12065
|
-
remainingScope:
|
|
12066
|
-
reason:
|
|
12719
|
+
report: Type26.String({ minLength: 1, description: "\u5982\u5B9E\u7ED3\u679C\u62A5\u544A" }),
|
|
12720
|
+
remainingScope: Type26.String({ minLength: 1, description: "\u672C\u5C40\u540E\u5269\u4F59\u5DE5\u4F5C" }),
|
|
12721
|
+
reason: Type26.Optional(Type26.String({
|
|
12067
12722
|
minLength: 1,
|
|
12068
12723
|
description: "\u963B\u65AD\u539F\u56E0\uFF1A\u7F3A\u524D\u7F6E\u6216\u8FDD\u5BAA\u7EA6\u675F\u3002\u7F3A\u5F85\u51B3 owner \u51B3\u5B9A\u6216\u7B54\u590D\u5C5E\u7F3A\u524D\u7F6E\u3002"
|
|
12069
12724
|
}))
|
|
@@ -12534,6 +13189,12 @@ var GLEANER_LEFT_TRANSPORT_FLAGS = Object.freeze([
|
|
|
12534
13189
|
definition: GLEANER_LEFT_BASE_FLAG.definition
|
|
12535
13190
|
})
|
|
12536
13191
|
]);
|
|
13192
|
+
var DIARIST_TRANSPORT_FLAGS = Object.freeze([
|
|
13193
|
+
Object.freeze({
|
|
13194
|
+
name: DIARIST_SOURCES_FLAG.name,
|
|
13195
|
+
definition: DIARIST_SOURCES_FLAG.definition
|
|
13196
|
+
})
|
|
13197
|
+
]);
|
|
12537
13198
|
function decodeReviewerAdmittedInputs(getFlag) {
|
|
12538
13199
|
let reviewScopeKeys;
|
|
12539
13200
|
const rawScopeKeys = getFlag("ak-review-scope-keys");
|
|
@@ -12651,6 +13312,8 @@ function activationStage(role, runtime) {
|
|
|
12651
13312
|
return { id: "load-and-install", run: async () => runtime.gatekeeper.activate() };
|
|
12652
13313
|
case "navigator":
|
|
12653
13314
|
return { id: "load-and-install", run: async () => runtime.navigator.activate() };
|
|
13315
|
+
case "diarist":
|
|
13316
|
+
return { id: "load-and-install", run: async () => runtime.diarist.activate() };
|
|
12654
13317
|
case "merger":
|
|
12655
13318
|
return { id: "prepare-git-and-install", run: async () => runtime.merger() };
|
|
12656
13319
|
}
|
|
@@ -12788,12 +13451,10 @@ function createFiledOfficerRuntime(roleHost, spec, dependencies) {
|
|
|
12788
13451
|
parameters: spec.tool.parameters,
|
|
12789
13452
|
async execute(toolCallId, parameters, signal, _onUpdate, ctx) {
|
|
12790
13453
|
if (soul === void 0) throw new Error(`${spec.role} \u804C\u5206\u672A\u88C5\u8F7D`);
|
|
12791
|
-
|
|
12792
|
-
await spec.beforeAccept({ toolCallId, parameters, signal, ctx });
|
|
12793
|
-
}
|
|
13454
|
+
const projected = spec.beforeAccept === void 0 ? void 0 : await spec.beforeAccept({ toolCallId, parameters, signal, ctx });
|
|
12794
13455
|
return {
|
|
12795
13456
|
content: [{ type: "text", text: spec.acceptedText }],
|
|
12796
|
-
details: parameters,
|
|
13457
|
+
details: projected === void 0 ? parameters : projected,
|
|
12797
13458
|
terminate: true
|
|
12798
13459
|
};
|
|
12799
13460
|
}
|
|
@@ -12870,6 +13531,47 @@ function createNavigatorRoleRuntime(roleHost, dependencies) {
|
|
|
12870
13531
|
dependencies
|
|
12871
13532
|
);
|
|
12872
13533
|
}
|
|
13534
|
+
function createDiaristRoleRuntime(roleHost, dependencies, getSourcesFlag) {
|
|
13535
|
+
let catalog;
|
|
13536
|
+
const runtime = createFiledOfficerRuntime(
|
|
13537
|
+
roleHost,
|
|
13538
|
+
{
|
|
13539
|
+
role: "diarist",
|
|
13540
|
+
tool: DIARIST_TOOL_SPEC,
|
|
13541
|
+
acceptedText: DIARIST_ACCEPTED_TEXT,
|
|
13542
|
+
soulTag: "diarist",
|
|
13543
|
+
beforeAccept: async ({ parameters }) => {
|
|
13544
|
+
const submitted = parameters !== null && typeof parameters === "object" && !Array.isArray(parameters) ? parameters : void 0;
|
|
13545
|
+
if (catalog === void 0) {
|
|
13546
|
+
if (submitted === void 0 || !("sitian" in submitted)) return void 0;
|
|
13547
|
+
const stripped = { ...submitted };
|
|
13548
|
+
delete stripped.sitian;
|
|
13549
|
+
return stripped;
|
|
13550
|
+
}
|
|
13551
|
+
const facts = await commitDiaristSelections({
|
|
13552
|
+
catalog,
|
|
13553
|
+
selections: projectDiaristSelections(parameters)
|
|
13554
|
+
});
|
|
13555
|
+
return { ...submitted ?? { receipt: parameters }, sitian: facts };
|
|
13556
|
+
}
|
|
13557
|
+
},
|
|
13558
|
+
dependencies
|
|
13559
|
+
);
|
|
13560
|
+
return {
|
|
13561
|
+
async activate() {
|
|
13562
|
+
catalog = loadFrozenDiaristCatalog(getSourcesFlag);
|
|
13563
|
+
return runtime.activate();
|
|
13564
|
+
}
|
|
13565
|
+
};
|
|
13566
|
+
}
|
|
13567
|
+
function loadFrozenDiaristCatalog(getFlag) {
|
|
13568
|
+
const raw = getFlag();
|
|
13569
|
+
if (raw === void 0) return void 0;
|
|
13570
|
+
if (typeof raw !== "string" || raw.trim() === "") {
|
|
13571
|
+
throw new Error("Diarist source catalog flag must be a nonempty path");
|
|
13572
|
+
}
|
|
13573
|
+
return loadDiaristSourceCatalog(raw);
|
|
13574
|
+
}
|
|
12873
13575
|
function createCountersignRoleRuntime(roleHost, dependencies, hostActions) {
|
|
12874
13576
|
const beforeAccept = hostActions !== void 0 && roleHost.requireGatekeeperPass !== void 0 ? async ({ toolCallId, signal, ctx }) => {
|
|
12875
13577
|
await roleHost.requireGatekeeperPass({
|
|
@@ -12913,6 +13615,9 @@ function createRoleRuntimeExtension(dependencies) {
|
|
|
12913
13615
|
for (const flag of GLEANER_LEFT_TRANSPORT_FLAGS) {
|
|
12914
13616
|
roleHost.registerFlag(flag.name, flag.definition);
|
|
12915
13617
|
}
|
|
13618
|
+
for (const flag of DIARIST_TRANSPORT_FLAGS) {
|
|
13619
|
+
roleHost.registerFlag(flag.name, flag.definition);
|
|
13620
|
+
}
|
|
12916
13621
|
let admitted = false;
|
|
12917
13622
|
let selectedRole;
|
|
12918
13623
|
let activeReviewerParent;
|
|
@@ -13303,6 +14008,16 @@ function createRoleRuntimeExtension(dependencies) {
|
|
|
13303
14008
|
return dependencies.loadNavigatorSoul();
|
|
13304
14009
|
}
|
|
13305
14010
|
});
|
|
14011
|
+
const diarist = createDiaristRoleRuntime(
|
|
14012
|
+
roleHost,
|
|
14013
|
+
{
|
|
14014
|
+
async loadSoul() {
|
|
14015
|
+
if (!dependencies.loadDiaristSoul) throw new Error("Diarist runtime dependencies are not configured");
|
|
14016
|
+
return dependencies.loadDiaristSoul();
|
|
14017
|
+
}
|
|
14018
|
+
},
|
|
14019
|
+
() => envelopeHost.host.getFlag(DIARIST_SOURCES_FLAG.name)
|
|
14020
|
+
);
|
|
13306
14021
|
let sessionMergerGitState = dependencies.mergerGitState;
|
|
13307
14022
|
const merger = createMergerRoleRuntime(roleHost, {
|
|
13308
14023
|
async loadSoul() {
|
|
@@ -13455,6 +14170,7 @@ function createRoleRuntimeExtension(dependencies) {
|
|
|
13455
14170
|
inspector,
|
|
13456
14171
|
gatekeeper,
|
|
13457
14172
|
navigator,
|
|
14173
|
+
diarist,
|
|
13458
14174
|
merger: async () => {
|
|
13459
14175
|
if (dependencies.mergerGitState === void 0) {
|
|
13460
14176
|
sessionMergerGitState = dependencies.createMergerGitState?.(ctx.cwd);
|
|
@@ -13564,14 +14280,30 @@ function createRoleRuntimeExtension(dependencies) {
|
|
|
13564
14280
|
};
|
|
13565
14281
|
}
|
|
13566
14282
|
|
|
13567
|
-
// src/
|
|
14283
|
+
// src/acp-host/description.ts
|
|
14284
|
+
import { join as join23 } from "node:path";
|
|
14285
|
+
function resolveAcpBinary(description, operatorHome) {
|
|
14286
|
+
return join23(operatorHome, ...description.binaryFromHome);
|
|
14287
|
+
}
|
|
14288
|
+
function acpStdioArgs(description, model) {
|
|
14289
|
+
const { prefix, suffix, modelFlag, thinkingFlag } = description.argv;
|
|
14290
|
+
const pair = (flag, value) => flag === void 0 || value === void 0 ? [] : [flag, value];
|
|
14291
|
+
return [
|
|
14292
|
+
...prefix,
|
|
14293
|
+
...pair(modelFlag, model?.model),
|
|
14294
|
+
...pair(thinkingFlag, model?.thinking),
|
|
14295
|
+
...suffix
|
|
14296
|
+
];
|
|
14297
|
+
}
|
|
14298
|
+
|
|
14299
|
+
// src/acp-host/role-envelope.ts
|
|
13568
14300
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
13569
14301
|
import { mkdir as mkdir3, readFile as readFile13, writeFile as writeFile7 } from "node:fs/promises";
|
|
13570
14302
|
import { createServer } from "node:net";
|
|
13571
|
-
import { basename as basename7, dirname as dirname15, join as
|
|
14303
|
+
import { basename as basename7, dirname as dirname15, join as join24 } from "node:path";
|
|
13572
14304
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
13573
14305
|
|
|
13574
|
-
// src/
|
|
14306
|
+
// src/acp-host/role-turn-host.ts
|
|
13575
14307
|
import { spawn as spawn4 } from "node:child_process";
|
|
13576
14308
|
import { createInterface } from "node:readline";
|
|
13577
14309
|
|
|
@@ -13581,8 +14313,8 @@ function renderAgentStartMaterials(body, materials) {
|
|
|
13581
14313
|
return [body, ...materials.map((material) => JSON.stringify(material))].join("\n\n");
|
|
13582
14314
|
}
|
|
13583
14315
|
|
|
13584
|
-
// src/
|
|
13585
|
-
function
|
|
14316
|
+
// src/acp-host/role-turn-host.ts
|
|
14317
|
+
function renderAcpSystemPromptOverride(authority) {
|
|
13586
14318
|
return renderAgentStartMaterials(authority.body, authority.materials);
|
|
13587
14319
|
}
|
|
13588
14320
|
function failure(cause, name, code, details) {
|
|
@@ -13598,19 +14330,13 @@ function failure(cause, name, code, details) {
|
|
|
13598
14330
|
};
|
|
13599
14331
|
}
|
|
13600
14332
|
function hostAbortedError() {
|
|
13601
|
-
return Object.assign(new Error("
|
|
14333
|
+
return Object.assign(new Error("ACP host aborted"), { code: "host-aborted" });
|
|
13602
14334
|
}
|
|
13603
14335
|
function acpError(code, message, cause) {
|
|
13604
14336
|
return Object.assign(new Error(message, cause === void 0 ? void 0 : { cause }), { code });
|
|
13605
14337
|
}
|
|
13606
|
-
function
|
|
13607
|
-
const
|
|
13608
|
-
"agent",
|
|
13609
|
-
...options.model === void 0 ? [] : ["--model", options.model],
|
|
13610
|
-
"stdio"
|
|
13611
|
-
];
|
|
13612
|
-
const env = options.toolset === void 0 ? options.env : { ...options.env, GROK_CONFIG: JSON.stringify({ toolset: options.toolset }) };
|
|
13613
|
-
const child = spawn4(options.binary, args, { cwd: options.cwd, env, stdio: ["pipe", "pipe", "pipe"] });
|
|
14338
|
+
function connectAcpStdio(options) {
|
|
14339
|
+
const child = spawn4(options.binary, [...options.args], { cwd: options.cwd, env: options.env, stdio: ["pipe", "pipe", "pipe"] });
|
|
13614
14340
|
const pending = /* @__PURE__ */ new Map();
|
|
13615
14341
|
const notificationHandlers = [];
|
|
13616
14342
|
if (options.onNotification !== void 0) notificationHandlers.push(options.onNotification);
|
|
@@ -13633,13 +14359,13 @@ function connectGrokAcpStdio(options) {
|
|
|
13633
14359
|
child.stderr.setEncoding("utf8").on("data", (chunk) => {
|
|
13634
14360
|
stderr += chunk;
|
|
13635
14361
|
});
|
|
13636
|
-
child.on("error", (error) => settleClosed(acpError("acp-process-error", `
|
|
14362
|
+
child.on("error", (error) => settleClosed(acpError("acp-process-error", `ACP process error: ${error.message}`, error)));
|
|
13637
14363
|
createInterface({ input: child.stdout }).on("line", (line2) => {
|
|
13638
14364
|
let message;
|
|
13639
14365
|
try {
|
|
13640
14366
|
message = JSON.parse(line2);
|
|
13641
14367
|
} catch (error) {
|
|
13642
|
-
terminate(acpError("acp-invalid-json", `Invalid
|
|
14368
|
+
terminate(acpError("acp-invalid-json", `Invalid ACP JSON: ${String(error)}`, error));
|
|
13643
14369
|
return;
|
|
13644
14370
|
}
|
|
13645
14371
|
if (typeof message.method === "string") {
|
|
@@ -13647,13 +14373,13 @@ function connectGrokAcpStdio(options) {
|
|
|
13647
14373
|
for (const handler of notificationHandlers) handler(message.method, params);
|
|
13648
14374
|
if (typeof message.id === "number") {
|
|
13649
14375
|
if (message.method !== "session/request_permission") {
|
|
13650
|
-
terminate(acpError("acp-unsupported-client-request", `Unsupported
|
|
14376
|
+
terminate(acpError("acp-unsupported-client-request", `Unsupported ACP client request: ${message.method}`));
|
|
13651
14377
|
return;
|
|
13652
14378
|
}
|
|
13653
14379
|
const choices = Array.isArray(params.options) ? params.options : [];
|
|
13654
14380
|
const selected = choices.find((value) => typeof value === "object" && value !== null && value.kind === "allow_once");
|
|
13655
14381
|
if (typeof selected?.optionId !== "string") {
|
|
13656
|
-
terminate(acpError("acp-permission-missing-allow-once", "
|
|
14382
|
+
terminate(acpError("acp-permission-missing-allow-once", "ACP permission request omitted allow_once"));
|
|
13657
14383
|
return;
|
|
13658
14384
|
}
|
|
13659
14385
|
child.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", id: message.id, result: { outcome: { outcome: "selected", optionId: selected.optionId } } })}
|
|
@@ -13665,13 +14391,13 @@ function connectGrokAcpStdio(options) {
|
|
|
13665
14391
|
const waiter = pending.get(message.id);
|
|
13666
14392
|
if (waiter === void 0) return;
|
|
13667
14393
|
pending.delete(message.id);
|
|
13668
|
-
if (message.error !== void 0) waiter.reject(acpError("acp-upstream-error", `
|
|
14394
|
+
if (message.error !== void 0) waiter.reject(acpError("acp-upstream-error", `ACP error: ${JSON.stringify(message.error)}`));
|
|
13669
14395
|
else waiter.resolve(message.result ?? {});
|
|
13670
14396
|
});
|
|
13671
|
-
child.on("close", (code) => settleClosed(acpError("acp-closed", `
|
|
14397
|
+
child.on("close", (code) => settleClosed(acpError("acp-closed", `ACP closed (${String(code)}): ${stderr}`)));
|
|
13672
14398
|
return Promise.resolve({
|
|
13673
14399
|
request(method, params) {
|
|
13674
|
-
if (closed) return Promise.reject(terminalError ?? acpError("acp-connection-closed", "
|
|
14400
|
+
if (closed) return Promise.reject(terminalError ?? acpError("acp-connection-closed", "ACP connection is closed"));
|
|
13675
14401
|
const id = ++nextId;
|
|
13676
14402
|
return new Promise((resolve17, reject) => {
|
|
13677
14403
|
pending.set(id, { resolve: resolve17, reject });
|
|
@@ -13681,12 +14407,12 @@ function connectGrokAcpStdio(options) {
|
|
|
13681
14407
|
const waiter = pending.get(id);
|
|
13682
14408
|
if (waiter === void 0) return;
|
|
13683
14409
|
pending.delete(id);
|
|
13684
|
-
waiter.reject(acpError("acp-write-failed", `
|
|
14410
|
+
waiter.reject(acpError("acp-write-failed", `ACP write failed: ${error.message}`, error));
|
|
13685
14411
|
});
|
|
13686
14412
|
});
|
|
13687
14413
|
},
|
|
13688
14414
|
notify(method, params) {
|
|
13689
|
-
if (closed) throw terminalError ?? acpError("acp-connection-closed", "
|
|
14415
|
+
if (closed) throw terminalError ?? acpError("acp-connection-closed", "ACP connection is closed");
|
|
13690
14416
|
child.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", method, params })}
|
|
13691
14417
|
`);
|
|
13692
14418
|
},
|
|
@@ -13695,14 +14421,14 @@ function connectGrokAcpStdio(options) {
|
|
|
13695
14421
|
},
|
|
13696
14422
|
async close() {
|
|
13697
14423
|
if (closed) return;
|
|
13698
|
-
settleClosed(acpError("acp-connection-closed", "
|
|
14424
|
+
settleClosed(acpError("acp-connection-closed", "ACP connection is closed"));
|
|
13699
14425
|
child.stdin.end();
|
|
13700
14426
|
child.kill("SIGTERM");
|
|
13701
14427
|
await new Promise((resolve17) => child.once("close", () => resolve17()));
|
|
13702
14428
|
}
|
|
13703
14429
|
});
|
|
13704
14430
|
}
|
|
13705
|
-
function
|
|
14431
|
+
function createAcpRoleTurnHost(config) {
|
|
13706
14432
|
let serial = Promise.resolve();
|
|
13707
14433
|
return {
|
|
13708
14434
|
executeTurn(request) {
|
|
@@ -13714,7 +14440,7 @@ function createGrokRoleTurnHost(config) {
|
|
|
13714
14440
|
let accepted = false;
|
|
13715
14441
|
try {
|
|
13716
14442
|
if (prepared.mcpServers.length === 0) {
|
|
13717
|
-
return failure("activation", "
|
|
14443
|
+
return failure("activation", "UncontrolledAcpSession", "ak-config-missing");
|
|
13718
14444
|
}
|
|
13719
14445
|
connection = await config.connect(request);
|
|
13720
14446
|
const initialized = await connection.request("initialize", {
|
|
@@ -13725,49 +14451,36 @@ function createGrokRoleTurnHost(config) {
|
|
|
13725
14451
|
const modelState = initializeMeta?.modelState;
|
|
13726
14452
|
const availableModels = Array.isArray(modelState?.availableModels) ? modelState.availableModels : void 0;
|
|
13727
14453
|
if (request.model !== void 0 && availableModels !== void 0 && !availableModels.some((entry) => typeof entry === "object" && entry !== null && entry.modelId === request.model?.model)) {
|
|
13728
|
-
return failure("activation", "
|
|
14454
|
+
return failure("activation", "AcpHostModelMismatch", "host-model-mismatch", {
|
|
13729
14455
|
provider: request.model.provider,
|
|
13730
14456
|
model: request.model.model
|
|
13731
14457
|
});
|
|
13732
14458
|
}
|
|
13733
|
-
const priorNativePaths = continuation.kind === "resume"
|
|
13734
|
-
if (continuation.kind === "resume") {
|
|
14459
|
+
const priorNativePaths = continuation.kind === "resume" ? request.hostTransition?.priorNativePaths : void 0;
|
|
14460
|
+
if (continuation.kind === "resume" && config.boundResume === "session/load") {
|
|
13735
14461
|
const boundSessionId = await config.sessionIdentity.load(request.principal);
|
|
13736
14462
|
if (boundSessionId !== void 0 && boundSessionId !== "") {
|
|
13737
14463
|
const loaded = await connection.request("session/load", {
|
|
13738
14464
|
sessionId: boundSessionId,
|
|
13739
14465
|
cwd: request.cwd,
|
|
13740
14466
|
mcpServers: prepared.mcpServers,
|
|
13741
|
-
_meta: { systemPromptOverride:
|
|
14467
|
+
_meta: { systemPromptOverride: renderAcpSystemPromptOverride(prepared.systemPrompt), yoloMode: false }
|
|
13742
14468
|
});
|
|
13743
14469
|
sessionId = typeof loaded.sessionId === "string" && loaded.sessionId !== "" ? loaded.sessionId : boundSessionId;
|
|
13744
|
-
} else {
|
|
13745
|
-
const session = await connection.request(
|
|
13746
|
-
"session/new",
|
|
13747
|
-
{
|
|
13748
|
-
cwd: request.cwd,
|
|
13749
|
-
mcpServers: prepared.mcpServers,
|
|
13750
|
-
_meta: { systemPromptOverride: renderGrokSystemPromptOverride(prepared.systemPrompt), yoloMode: false }
|
|
13751
|
-
}
|
|
13752
|
-
);
|
|
13753
|
-
sessionId = typeof session.sessionId === "string" ? session.sessionId : void 0;
|
|
13754
|
-
if (sessionId === void 0 || sessionId === "") {
|
|
13755
|
-
return failure("session", "GrokAcpSessionFailure", "session-id-missing");
|
|
13756
|
-
}
|
|
13757
|
-
await config.sessionIdentity.bind(request.principal, sessionId);
|
|
13758
14470
|
}
|
|
13759
|
-
}
|
|
14471
|
+
}
|
|
14472
|
+
if (sessionId === void 0) {
|
|
13760
14473
|
const session = await connection.request(
|
|
13761
14474
|
"session/new",
|
|
13762
14475
|
{
|
|
13763
14476
|
cwd: request.cwd,
|
|
13764
14477
|
mcpServers: prepared.mcpServers,
|
|
13765
|
-
_meta: { systemPromptOverride:
|
|
14478
|
+
_meta: { systemPromptOverride: renderAcpSystemPromptOverride(prepared.systemPrompt), yoloMode: false }
|
|
13766
14479
|
}
|
|
13767
14480
|
);
|
|
13768
14481
|
sessionId = typeof session.sessionId === "string" ? session.sessionId : void 0;
|
|
13769
14482
|
if (sessionId === void 0 || sessionId === "") {
|
|
13770
|
-
return failure("session", "
|
|
14483
|
+
return failure("session", "AcpSessionFailure", "session-id-missing");
|
|
13771
14484
|
}
|
|
13772
14485
|
await config.sessionIdentity.bind(request.principal, sessionId);
|
|
13773
14486
|
}
|
|
@@ -13828,7 +14541,7 @@ ${priorNativePaths.join("\n")}` : prepared.prompt;
|
|
|
13828
14541
|
throw error;
|
|
13829
14542
|
}
|
|
13830
14543
|
if (result2.stopReason === "refusal") {
|
|
13831
|
-
return failure("output", "
|
|
14544
|
+
return failure("output", "AcpRefusal", "refusal", { sessionId });
|
|
13832
14545
|
}
|
|
13833
14546
|
const closure = await prepared.closeRound();
|
|
13834
14547
|
if (closure.accepted) {
|
|
@@ -13841,7 +14554,7 @@ ${priorNativePaths.join("\n")}` : prepared.prompt;
|
|
|
13841
14554
|
}
|
|
13842
14555
|
prompt = `The prior terminal submission was rejected (${closure.retry.code}). Resubmit it as the sole terminal tool call. Rejected call ids: ${closure.retry.toolCallIds.join(", ") || "none"}.`;
|
|
13843
14556
|
}
|
|
13844
|
-
return failure("output", "
|
|
14557
|
+
return failure("output", "AcpRoundLimit", "round-retry-limit", { sessionId });
|
|
13845
14558
|
} finally {
|
|
13846
14559
|
if (connection !== void 0) {
|
|
13847
14560
|
if (sessionId !== void 0 && !accepted) {
|
|
@@ -13866,25 +14579,14 @@ ${priorNativePaths.join("\n")}` : prepared.prompt;
|
|
|
13866
14579
|
}
|
|
13867
14580
|
};
|
|
13868
14581
|
}
|
|
13869
|
-
var PRIVATE_COMPAT_ENV = Object.fromEntries(
|
|
13870
|
-
["CLAUDE", "CURSOR", "CODEX"].flatMap((vendor) => ["SKILLS", "RULES", "AGENTS", "MCPS", "HOOKS", "SESSIONS"].map((kind) => [`GROK_${vendor}_${kind}_ENABLED`, "false"]))
|
|
13871
|
-
);
|
|
13872
|
-
function controlledGrokChildEnv(base) {
|
|
13873
|
-
return {
|
|
13874
|
-
...base,
|
|
13875
|
-
...PRIVATE_COMPAT_ENV,
|
|
13876
|
-
GROK_MEMORY: "0",
|
|
13877
|
-
GROK_SUBAGENTS: "0"
|
|
13878
|
-
};
|
|
13879
|
-
}
|
|
13880
14582
|
|
|
13881
|
-
// src/
|
|
14583
|
+
// src/acp-host/role-envelope.ts
|
|
13882
14584
|
function parseCanonicalSkillInvocation(prompt) {
|
|
13883
14585
|
const match = /^\/skill:([A-Za-z0-9_-]+)(?:\s+([\s\S]*))?$/s.exec(prompt.trim());
|
|
13884
14586
|
if (match === null) return void 0;
|
|
13885
14587
|
return { name: match[1], userMessage: (match[2] ?? "").trim() };
|
|
13886
14588
|
}
|
|
13887
|
-
function
|
|
14589
|
+
function buildAcpSkillExpansion(methodSkills, prompt) {
|
|
13888
14590
|
const parsed = parseCanonicalSkillInvocation(prompt);
|
|
13889
14591
|
if (parsed === void 0) return void 0;
|
|
13890
14592
|
const method = methodSkills.get(parsed.name);
|
|
@@ -13898,14 +14600,14 @@ ${method.body}`,
|
|
|
13898
14600
|
userMessage: parsed.userMessage
|
|
13899
14601
|
});
|
|
13900
14602
|
}
|
|
13901
|
-
function
|
|
14603
|
+
function projectAcpActivationFlags(request) {
|
|
13902
14604
|
const activation = request.activation;
|
|
13903
14605
|
const flags = /* @__PURE__ */ new Map([["ak-role", activation.role]]);
|
|
13904
14606
|
const inputFlag = packagedRoleInputFlag(activation.role);
|
|
13905
14607
|
const phaseFlag = packagedRolePhaseFlag(activation.role);
|
|
13906
14608
|
if ("phase" in activation && phaseFlag !== void 0) flags.set(phaseFlag, activation.phase);
|
|
13907
14609
|
if (inputFlag !== void 0) {
|
|
13908
|
-
const path = "taskPath" in activation ? activation.taskPath : "packetPath" in activation ? activation.packetPath : "casePath" in activation ? activation.casePath : "inputPath" in activation ? activation.inputPath : "sourceRun" in activation ? activation.sourceRun : void 0;
|
|
14610
|
+
const path = "taskPath" in activation ? activation.taskPath : "packetPath" in activation ? activation.packetPath : "casePath" in activation ? activation.casePath : "inputPath" in activation ? activation.inputPath : "sourceRun" in activation ? activation.sourceRun : "sourcesPath" in activation ? activation.sourcesPath : void 0;
|
|
13909
14611
|
if (path !== void 0) flags.set(inputFlag, path);
|
|
13910
14612
|
}
|
|
13911
14613
|
if (activation.role === "fixer" && activation.prerequisitesPath !== void 0) flags.set("ak-fixer-prerequisites", activation.prerequisitesPath);
|
|
@@ -13936,21 +14638,21 @@ async function listen(server, path) {
|
|
|
13936
14638
|
});
|
|
13937
14639
|
});
|
|
13938
14640
|
}
|
|
13939
|
-
function
|
|
13940
|
-
return
|
|
14641
|
+
function createComposedAcpRoleTurnHost(config) {
|
|
14642
|
+
return createAcpRoleTurnHost({
|
|
13941
14643
|
...config,
|
|
13942
|
-
prepare: (request) =>
|
|
14644
|
+
prepare: (request) => prepareAcpRoleEnvelope({
|
|
13943
14645
|
request,
|
|
13944
14646
|
dependencies: config.roleRuntimeDependencies,
|
|
13945
14647
|
// Same durable-principal path settlement uses for isAvailable (#617 DK-4 layout).
|
|
13946
14648
|
sessionFile: config.sessionIdentity.resolveSessionFile(request.principal),
|
|
13947
|
-
socketPath: config.socketPath?.(request) ?? `/tmp/ak-
|
|
14649
|
+
socketPath: config.socketPath?.(request) ?? `/tmp/ak-acp-mcp-${randomUUID2()}.sock`
|
|
13948
14650
|
})
|
|
13949
14651
|
});
|
|
13950
14652
|
}
|
|
13951
|
-
async function
|
|
14653
|
+
async function prepareAcpRoleEnvelope(options) {
|
|
13952
14654
|
const { request } = options;
|
|
13953
|
-
const flags =
|
|
14655
|
+
const flags = projectAcpActivationFlags(request);
|
|
13954
14656
|
const tools = /* @__PURE__ */ new Map();
|
|
13955
14657
|
const handlers = /* @__PURE__ */ new Map();
|
|
13956
14658
|
const calls = [];
|
|
@@ -13969,7 +14671,7 @@ async function prepareGrokRoleEnvelope(options) {
|
|
|
13969
14671
|
const raw = await readFile13(method.path, "utf8");
|
|
13970
14672
|
methodSkills.set(name, { path: method.path, body: stripSkillFrontmatter(raw).trim() });
|
|
13971
14673
|
}
|
|
13972
|
-
let sessionFile = options.sessionFile ??
|
|
14674
|
+
let sessionFile = options.sessionFile ?? join24(request.runDirectory, "session", "session.jsonl");
|
|
13973
14675
|
await mkdir3(dirname15(sessionFile), { recursive: true });
|
|
13974
14676
|
if (request.continuation.kind !== "resume") {
|
|
13975
14677
|
try {
|
|
@@ -14034,7 +14736,7 @@ async function prepareGrokRoleEnvelope(options) {
|
|
|
14034
14736
|
},
|
|
14035
14737
|
capabilities: {
|
|
14036
14738
|
skillExpansion(prompt) {
|
|
14037
|
-
return
|
|
14739
|
+
return buildAcpSkillExpansion(methodSkills, prompt);
|
|
14038
14740
|
}
|
|
14039
14741
|
},
|
|
14040
14742
|
registerFlag(name, definition) {
|
|
@@ -14046,12 +14748,12 @@ async function prepareGrokRoleEnvelope(options) {
|
|
|
14046
14748
|
registerTool(tool2) {
|
|
14047
14749
|
tools.set(tool2.name, tool2);
|
|
14048
14750
|
},
|
|
14049
|
-
// The real AK-owned surface only;
|
|
14751
|
+
// The real AK-owned surface only; the host builtin surface is host-side and
|
|
14050
14752
|
// observable after session/new, never echoed back into role-requested names.
|
|
14051
14753
|
getAllTools() {
|
|
14052
14754
|
return [...tools.keys()].map((name) => ({ name }));
|
|
14053
14755
|
},
|
|
14054
|
-
//
|
|
14756
|
+
// The host receives tool choice as role guidance; every tool registered for the
|
|
14055
14757
|
// seat remains reachable through MCP.
|
|
14056
14758
|
setActiveTools(names) {
|
|
14057
14759
|
preferredTools = [...names];
|
|
@@ -14333,7 +15035,7 @@ async function prepareGrokRoleEnvelope(options) {
|
|
|
14333
15035
|
}
|
|
14334
15036
|
if (cleanupFailures.length === 1) throw cleanupFailures[0];
|
|
14335
15037
|
if (cleanupFailures.length > 1) {
|
|
14336
|
-
throw new AggregateError(cleanupFailures, "
|
|
15038
|
+
throw new AggregateError(cleanupFailures, "ACP envelope dispose cleanup failures", {
|
|
14337
15039
|
cause: cleanupFailures[0]
|
|
14338
15040
|
});
|
|
14339
15041
|
}
|
|
@@ -14410,8 +15112,8 @@ async function prepareGrokRoleEnvelope(options) {
|
|
|
14410
15112
|
command: process.execPath,
|
|
14411
15113
|
args: [relay],
|
|
14412
15114
|
env: [
|
|
14413
|
-
{ name: "
|
|
14414
|
-
{ name: "
|
|
15115
|
+
{ name: "AK_ACP_MCP_SOCKET", value: options.socketPath },
|
|
15116
|
+
{ name: "AK_ACP_MCP_TOKEN", value: token }
|
|
14415
15117
|
]
|
|
14416
15118
|
}],
|
|
14417
15119
|
systemPrompt: { body: systemPromptBody, materials: readingMaterials },
|
|
@@ -14426,7 +15128,7 @@ async function prepareGrokRoleEnvelope(options) {
|
|
|
14426
15128
|
} catch (cleanupFailure) {
|
|
14427
15129
|
throw new AggregateError(
|
|
14428
15130
|
[error, cleanupFailure],
|
|
14429
|
-
"
|
|
15131
|
+
"prepareAcpRoleEnvelope activation failed and its dispose cleanup also failed",
|
|
14430
15132
|
{ cause: error }
|
|
14431
15133
|
);
|
|
14432
15134
|
}
|
|
@@ -14434,12 +15136,11 @@ async function prepareGrokRoleEnvelope(options) {
|
|
|
14434
15136
|
}
|
|
14435
15137
|
}
|
|
14436
15138
|
|
|
14437
|
-
// src/
|
|
15139
|
+
// src/acp-host/session-identity.ts
|
|
14438
15140
|
import { mkdir as mkdir4, readFile as readFile14, rename, writeFile as writeFile8 } from "node:fs/promises";
|
|
14439
|
-
import { dirname as dirname16, join as
|
|
14440
|
-
|
|
14441
|
-
|
|
14442
|
-
const bindingPath = (principal) => join23(authority.decode(principal).sessionDirectory, GROK_ACP_SESSION_BINDING);
|
|
15141
|
+
import { dirname as dirname16, join as join25 } from "node:path";
|
|
15142
|
+
function createAcpSessionIdentityAuthority(authority, sessionBindingFile) {
|
|
15143
|
+
const bindingPath = (principal) => join25(authority.decode(principal).sessionDirectory, sessionBindingFile);
|
|
14443
15144
|
return {
|
|
14444
15145
|
resolveSessionFile(principal) {
|
|
14445
15146
|
return authority.decode(principal).sessionFile;
|
|
@@ -14448,7 +15149,7 @@ function createGrokSessionIdentityAuthority(authority) {
|
|
|
14448
15149
|
try {
|
|
14449
15150
|
const value = JSON.parse(await readFile14(bindingPath(principal), "utf8"));
|
|
14450
15151
|
if (typeof value !== "object" || value === null || typeof value.sessionId !== "string") {
|
|
14451
|
-
throw new Error("durable
|
|
15152
|
+
throw new Error("durable ACP session binding is invalid");
|
|
14452
15153
|
}
|
|
14453
15154
|
return value.sessionId;
|
|
14454
15155
|
} catch (error) {
|
|
@@ -14467,20 +15168,11 @@ function createGrokSessionIdentityAuthority(authority) {
|
|
|
14467
15168
|
};
|
|
14468
15169
|
}
|
|
14469
15170
|
|
|
14470
|
-
// src/
|
|
14471
|
-
function resolveGrokBinary(operatorHome) {
|
|
14472
|
-
return join24(operatorHome, ".grok", "bin", "grok");
|
|
14473
|
-
}
|
|
14474
|
-
function childEnv(packageRoot) {
|
|
14475
|
-
return {
|
|
14476
|
-
...controlledGrokChildEnv(process.env),
|
|
14477
|
-
AK_PACKAGE_ROOT: packageRoot
|
|
14478
|
-
};
|
|
14479
|
-
}
|
|
15171
|
+
// src/acp-host/production-host.ts
|
|
14480
15172
|
var navigatorRoutePlaybookPath = fileURLToPath3(
|
|
14481
15173
|
new URL("../../resources/navigator-route-playbook.md", import.meta.url)
|
|
14482
15174
|
);
|
|
14483
|
-
function
|
|
15175
|
+
function createAcpRoleRuntimeDependencies(packageRoot) {
|
|
14484
15176
|
const judgeAuditor = createPiJudgeAuditor();
|
|
14485
15177
|
const doctorAuditor = createPiDoctorAuditor();
|
|
14486
15178
|
const reviewerAgent = createPerDispatchReviewerAgent({ packageRoot });
|
|
@@ -14504,6 +15196,7 @@ function createGrokRoleRuntimeDependencies(packageRoot) {
|
|
|
14504
15196
|
loadNotarySoul: () => loadMainRoleSessionMaterials("notary"),
|
|
14505
15197
|
loadCountersignSoul: () => loadMainRoleSessionMaterials("countersign"),
|
|
14506
15198
|
loadGleanerLeftSoul: () => loadMainRoleSessionMaterials("gleaner-left"),
|
|
15199
|
+
loadDiaristSoul: () => loadMainRoleSessionMaterials("diarist"),
|
|
14507
15200
|
loadNotarySourceRun: loadNotarySourceRunLocator,
|
|
14508
15201
|
loadMergerSoul: () => loadMainRoleSessionMaterials("merger"),
|
|
14509
15202
|
loadMergerInput: async (path) => JSON.parse(await readFile15(path, "utf8")),
|
|
@@ -14544,23 +15237,28 @@ function createGrokRoleRuntimeDependencies(packageRoot) {
|
|
|
14544
15237
|
})
|
|
14545
15238
|
};
|
|
14546
15239
|
}
|
|
14547
|
-
function
|
|
14548
|
-
const { packageRoot, principalAuthority } = options;
|
|
14549
|
-
const env =
|
|
14550
|
-
|
|
14551
|
-
|
|
14552
|
-
|
|
15240
|
+
function createProductionAcpRoleTurnHost(options) {
|
|
15241
|
+
const { packageRoot, principalAuthority, description } = options;
|
|
15242
|
+
const env = {
|
|
15243
|
+
...process.env,
|
|
15244
|
+
...description.childEnv,
|
|
15245
|
+
AK_PACKAGE_ROOT: packageRoot
|
|
15246
|
+
};
|
|
15247
|
+
return createComposedAcpRoleTurnHost({
|
|
15248
|
+
sessionIdentity: createAcpSessionIdentityAuthority(principalAuthority, description.sessionBindingFile),
|
|
15249
|
+
boundResume: description.boundResume,
|
|
15250
|
+
roleRuntimeDependencies: createAcpRoleRuntimeDependencies(packageRoot),
|
|
14553
15251
|
async connect(request) {
|
|
14554
|
-
return
|
|
14555
|
-
binary:
|
|
15252
|
+
return connectAcpStdio({
|
|
15253
|
+
binary: resolveAcpBinary(description, request.home),
|
|
15254
|
+
args: acpStdioArgs(description, request.model),
|
|
14556
15255
|
cwd: request.cwd,
|
|
14557
|
-
env
|
|
14558
|
-
...request.model === void 0 ? {} : { model: request.model.model }
|
|
15256
|
+
env
|
|
14559
15257
|
});
|
|
14560
15258
|
}
|
|
14561
15259
|
});
|
|
14562
15260
|
}
|
|
14563
15261
|
export {
|
|
14564
|
-
|
|
14565
|
-
|
|
15262
|
+
createAcpRoleRuntimeDependencies,
|
|
15263
|
+
createProductionAcpRoleTurnHost
|
|
14566
15264
|
};
|