@akagilnc/pi-workflow-roles 0.1.5037 → 0.1.5066
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 +2 -2
- package/README.zh-CN.md +2 -2
- package/THIRD_PARTY_NOTICES.md +11 -23
- package/dist/acp-host/production-host.js +410 -878
- package/dist/headless-host/description.js +0 -2
- package/dist/headless-host/production-host.js +413 -914
- package/dist/host-descriptions.js +2 -3
- package/dist/migrate-book-topology.js +4 -10
- package/dist/packaged-role-registry.js +17 -16
- package/dist/pi/role-turn-host.js +3 -27
- package/dist/public-cli/cli.js +6 -0
- package/dist/public-cli/instruction-seat-run.js +12 -40
- package/dist/public-cli/machine-method-skills.js +150 -0
- package/dist/public-cli/main.js +378 -579
- package/dist/public-cli/post-admission.js +2 -0
- package/dist/public-cli/registry.js +2 -1
- package/dist/public-cli/settlement.js +12 -99
- package/dist/public-cli/turn-request.js +16 -8
- package/package.json +3 -1
- package/resources/836-deleted-machine-instruction-inventory.md +1 -1
- package/scripts/build-package.mjs +1 -6
- package/src/headless-host/description.ts +0 -3
- package/src/headless-host/role-turn-host.ts +2 -23
- package/src/host-contracts.ts +2 -23
- package/src/host-descriptions.ts +2 -3
- package/src/packaged-role-registry.ts +14 -14
- package/src/pi/adapter.ts +0 -27
- package/src/pi/role-turn-host.ts +3 -31
- package/src/public-cli/cli.ts +6 -0
- package/src/public-cli/instruction-seat-run.ts +9 -42
- package/src/public-cli/machine-method-skills.ts +153 -0
- package/src/public-cli/post-admission.ts +2 -0
- package/src/public-cli/registry.ts +1 -0
- package/src/public-cli/settlement.ts +6 -138
- package/src/public-cli/turn-request.ts +24 -16
- package/src/reviewer-role.ts +1 -12
- package/src/role-envelope.ts +0 -13
- package/src/role-runtime-dependencies.ts +0 -13
- package/src/role-runtime.ts +4 -56
- package/src/worker-role.ts +1 -81
- package/dist/method-host-plugin/.claude-plugin/plugin.json +0 -5
- package/dist/method-host-plugin/skills/ak-cross-m-review/CONTEXT.md +0 -48
- package/dist/method-host-plugin/skills/ak-cross-m-review/LICENSE +0 -21
- package/dist/method-host-plugin/skills/ak-cross-m-review/SKILL.md +0 -170
- package/dist/method-host-plugin/skills/ak-cross-m-review/prompts/cmr-completeness.md +0 -118
- package/dist/method-host-plugin/skills/ak-cross-m-review/prompts/cmr-reviewer.md +0 -128
- package/dist/method-host-plugin/skills/ak-cross-m-review/provenance.json +0 -41
- package/dist/method-host-plugin/skills/diagnosing-bugs/SKILL.md +0 -134
- package/dist/method-host-plugin/skills/diagnosing-bugs/agents/openai.yaml +0 -3
- package/dist/method-host-plugin/skills/diagnosing-bugs/provenance.json +0 -31
- package/dist/method-host-plugin/skills/diagnosing-bugs/scripts/hitl-loop.template.sh +0 -41
- package/dist/method-host-plugin/skills/resolving-merge-conflicts/SKILL.md +0 -14
- package/dist/method-host-plugin/skills/resolving-merge-conflicts/agents/openai.yaml +0 -3
- package/dist/method-host-plugin/skills/resolving-merge-conflicts/provenance.json +0 -26
- package/dist/method-host-plugin/skills/tdd/SKILL.md +0 -38
- package/dist/method-host-plugin/skills/tdd/agents/openai.yaml +0 -3
- package/dist/method-host-plugin/skills/tdd/mocking.md +0 -59
- package/dist/method-host-plugin/skills/tdd/provenance.json +0 -36
- package/dist/method-host-plugin/skills/tdd/tests.md +0 -77
- package/dist/package-resources/method-skill.js +0 -259
- package/resources/method-host-plugin/.claude-plugin/plugin.json +0 -5
- package/resources/methods/ak-cross-m-review/CONTEXT.md +0 -48
- package/resources/methods/ak-cross-m-review/LICENSE +0 -21
- package/resources/methods/ak-cross-m-review/SKILL.md +0 -170
- package/resources/methods/ak-cross-m-review/prompts/cmr-completeness.md +0 -118
- package/resources/methods/ak-cross-m-review/prompts/cmr-reviewer.md +0 -128
- package/resources/methods/ak-cross-m-review/provenance.json +0 -41
- package/resources/methods/diagnosing-bugs/SKILL.md +0 -134
- package/resources/methods/diagnosing-bugs/agents/openai.yaml +0 -3
- package/resources/methods/diagnosing-bugs/provenance.json +0 -31
- package/resources/methods/diagnosing-bugs/scripts/hitl-loop.template.sh +0 -41
- package/resources/methods/resolving-merge-conflicts/SKILL.md +0 -14
- package/resources/methods/resolving-merge-conflicts/agents/openai.yaml +0 -3
- package/resources/methods/resolving-merge-conflicts/provenance.json +0 -26
- package/resources/methods/tdd/SKILL.md +0 -38
- package/resources/methods/tdd/agents/openai.yaml +0 -3
- package/resources/methods/tdd/mocking.md +0 -59
- package/resources/methods/tdd/provenance.json +0 -36
- package/resources/methods/tdd/tests.md +0 -77
- package/src/canonical-skill-binding.ts +0 -118
- package/src/host-native-method.ts +0 -185
- package/src/package-resources/method-skill-binding.ts +0 -60
- package/src/package-resources/method-skill.ts +0 -363
|
@@ -41,9 +41,8 @@ export const HOST_DESCRIPTIONS = Object.freeze({
|
|
|
41
41
|
* Headless CLI family (#645 / #646). Claude print-mode is the first row;
|
|
42
42
|
* codex exec (#646) adds another. Protocol-specific argv/parse live in
|
|
43
43
|
* headless-host helpers (#752 per-host impl).
|
|
44
|
-
* Claude fixedArgs: print mode
|
|
45
|
-
* host events for sitian records (#811); result is last line.
|
|
46
|
-
* ride `--plugin-dir` (#922); operator skill/setting surfaces stay open.
|
|
44
|
+
* Claude fixedArgs: print mode. stream-json + verbose: live
|
|
45
|
+
* host events for sitian records (#811); result is last line.
|
|
47
46
|
*/
|
|
48
47
|
export const HEADLESS_HOST_DESCRIPTIONS = Object.freeze({
|
|
49
48
|
"claude": Object.freeze({
|
|
@@ -14051,8 +14051,7 @@ var init_packaged_role_registry = __esm({
|
|
|
14051
14051
|
{ key: "packetPath" },
|
|
14052
14052
|
{ key: "prerequisitesPath", omitUndefined: true },
|
|
14053
14053
|
{ key: "prerequisites" }
|
|
14054
|
-
]
|
|
14055
|
-
method: "observed"
|
|
14054
|
+
]
|
|
14056
14055
|
},
|
|
14057
14056
|
boardPlacement: "marshal",
|
|
14058
14057
|
activationFlags: [
|
|
@@ -14078,7 +14077,6 @@ var init_packaged_role_registry = __esm({
|
|
|
14078
14077
|
worker: true,
|
|
14079
14078
|
applyMethod: "tdd",
|
|
14080
14079
|
/** Method-material load failure keeps the activation cause (not reviewer/fixer). */
|
|
14081
|
-
methodLoadFailureCause: "activation",
|
|
14082
14080
|
boardPlacement: "coder",
|
|
14083
14081
|
phases: ["plan", "apply"],
|
|
14084
14082
|
outputTool: CODER_OUTPUT_TOOL_NAME,
|
|
@@ -14089,8 +14087,7 @@ var init_packaged_role_registry = __esm({
|
|
|
14089
14087
|
leaves: [
|
|
14090
14088
|
{ key: "phase" },
|
|
14091
14089
|
{ key: "taskPath" }
|
|
14092
|
-
]
|
|
14093
|
-
method: "optional"
|
|
14090
|
+
]
|
|
14094
14091
|
},
|
|
14095
14092
|
activationFlags: [
|
|
14096
14093
|
{ field: "taskPath", flag: "ak-coder-task", binds: "input" },
|
|
@@ -14131,8 +14128,7 @@ var init_packaged_role_registry = __esm({
|
|
|
14131
14128
|
{ key: "lens" },
|
|
14132
14129
|
{ key: "authorityRefs", copyArray: true },
|
|
14133
14130
|
{ key: "callerProvenance", callerProvenance: true }
|
|
14134
|
-
]
|
|
14135
|
-
method: "observed"
|
|
14131
|
+
]
|
|
14136
14132
|
},
|
|
14137
14133
|
/** Frozen base/lens/authority become the initial prompt; instruction follows. */
|
|
14138
14134
|
transportPrompt: "skill-args",
|
|
@@ -14231,7 +14227,6 @@ var init_packaged_role_registry = __esm({
|
|
|
14231
14227
|
methodSkills: ["resolving-merge-conflicts"],
|
|
14232
14228
|
settleMethod: "resolving-merge-conflicts",
|
|
14233
14229
|
/** Method-material load failure keeps the activation cause (not reviewer/fixer). */
|
|
14234
|
-
methodLoadFailureCause: "activation",
|
|
14235
14230
|
phases: [null],
|
|
14236
14231
|
outputTool: MERGER_OUTPUT_TOOL_NAME,
|
|
14237
14232
|
settlement: "residual",
|
|
@@ -14243,8 +14238,7 @@ var init_packaged_role_registry = __esm({
|
|
|
14243
14238
|
leaves: [
|
|
14244
14239
|
{ key: "mergerInputPath" },
|
|
14245
14240
|
{ key: "derived" }
|
|
14246
|
-
]
|
|
14247
|
-
method: "observed"
|
|
14241
|
+
]
|
|
14248
14242
|
},
|
|
14249
14243
|
activationFlags: [
|
|
14250
14244
|
{ field: "inputPath", from: "mergerInputPath", flag: "ak-merger-input", binds: "input" }
|
|
@@ -93,8 +93,7 @@ const PUBLIC_ROLE_RECORDS = [
|
|
|
93
93
|
{ key: "packetPath" },
|
|
94
94
|
{ key: "prerequisitesPath", omitUndefined: true },
|
|
95
95
|
{ key: "prerequisites" }
|
|
96
|
-
]
|
|
97
|
-
method: "observed"
|
|
96
|
+
]
|
|
98
97
|
},
|
|
99
98
|
boardPlacement: "marshal",
|
|
100
99
|
activationFlags: [
|
|
@@ -120,7 +119,6 @@ const PUBLIC_ROLE_RECORDS = [
|
|
|
120
119
|
worker: true,
|
|
121
120
|
applyMethod: "tdd",
|
|
122
121
|
/** Method-material load failure keeps the activation cause (not reviewer/fixer). */
|
|
123
|
-
methodLoadFailureCause: "activation",
|
|
124
122
|
boardPlacement: "coder",
|
|
125
123
|
phases: ["plan", "apply"],
|
|
126
124
|
outputTool: CODER_OUTPUT_TOOL_NAME,
|
|
@@ -131,8 +129,7 @@ const PUBLIC_ROLE_RECORDS = [
|
|
|
131
129
|
leaves: [
|
|
132
130
|
{ key: "phase" },
|
|
133
131
|
{ key: "taskPath" }
|
|
134
|
-
]
|
|
135
|
-
method: "optional"
|
|
132
|
+
]
|
|
136
133
|
},
|
|
137
134
|
activationFlags: [
|
|
138
135
|
{ field: "taskPath", flag: "ak-coder-task", binds: "input" },
|
|
@@ -173,8 +170,7 @@ const PUBLIC_ROLE_RECORDS = [
|
|
|
173
170
|
{ key: "lens" },
|
|
174
171
|
{ key: "authorityRefs", copyArray: true },
|
|
175
172
|
{ key: "callerProvenance", callerProvenance: true }
|
|
176
|
-
]
|
|
177
|
-
method: "observed"
|
|
173
|
+
]
|
|
178
174
|
},
|
|
179
175
|
/** Frozen base/lens/authority become the initial prompt; instruction follows. */
|
|
180
176
|
transportPrompt: "skill-args",
|
|
@@ -273,7 +269,6 @@ const PUBLIC_ROLE_RECORDS = [
|
|
|
273
269
|
methodSkills: ["resolving-merge-conflicts"],
|
|
274
270
|
settleMethod: "resolving-merge-conflicts",
|
|
275
271
|
/** Method-material load failure keeps the activation cause (not reviewer/fixer). */
|
|
276
|
-
methodLoadFailureCause: "activation",
|
|
277
272
|
phases: [null],
|
|
278
273
|
outputTool: MERGER_OUTPUT_TOOL_NAME,
|
|
279
274
|
settlement: "residual",
|
|
@@ -285,8 +280,7 @@ const PUBLIC_ROLE_RECORDS = [
|
|
|
285
280
|
leaves: [
|
|
286
281
|
{ key: "mergerInputPath" },
|
|
287
282
|
{ key: "derived" }
|
|
288
|
-
]
|
|
289
|
-
method: "observed"
|
|
283
|
+
]
|
|
290
284
|
},
|
|
291
285
|
activationFlags: [
|
|
292
286
|
{ field: "inputPath", from: "mergerInputPath", flag: "ak-merger-input", binds: "input" }
|
|
@@ -526,6 +520,18 @@ const PACKAGED_ROLE_REGISTRY = PUBLIC_ROLE_RECORDS.map(({ sessionMaterials: _omi
|
|
|
526
520
|
function packagedRoleMetadata(role) {
|
|
527
521
|
return PACKAGED_ROLE_REGISTRY.find((entry) => entry.role === role);
|
|
528
522
|
}
|
|
523
|
+
function packagedMethodSkillNames() {
|
|
524
|
+
const names = [];
|
|
525
|
+
for (const record of PACKAGED_ROLE_REGISTRY) {
|
|
526
|
+
if ("methodSkills" in record && record.methodSkills !== void 0) {
|
|
527
|
+
for (const name of record.methodSkills) if (!names.includes(name)) names.push(name);
|
|
528
|
+
}
|
|
529
|
+
if ("applyMethod" in record && record.applyMethod !== void 0 && !names.includes(record.applyMethod)) {
|
|
530
|
+
names.push(record.applyMethod);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
return names;
|
|
534
|
+
}
|
|
529
535
|
function isOfficerReviewSeat(role) {
|
|
530
536
|
const record = packagedRoleMetadata(role);
|
|
531
537
|
return record !== void 0 && "reviewOfficer" in record && record.reviewOfficer === true;
|
|
@@ -560,11 +566,6 @@ function packagedRolePhaseFlag(role) {
|
|
|
560
566
|
function packagedRoleOutputTool(role) {
|
|
561
567
|
return packagedRoleMetadata(role)?.outputTool;
|
|
562
568
|
}
|
|
563
|
-
function packagedMethodLoadFailureCause(role) {
|
|
564
|
-
const record = packagedRoleMetadata(role);
|
|
565
|
-
if (record === void 0 || !("methodLoadFailureCause" in record)) return void 0;
|
|
566
|
-
return record.methodLoadFailureCause;
|
|
567
|
-
}
|
|
568
569
|
function packagedBindsBoardTicket(role) {
|
|
569
570
|
const record = packagedRoleMetadata(role);
|
|
570
571
|
return record?.sameParent === "board-ticket";
|
|
@@ -690,7 +691,7 @@ export {
|
|
|
690
691
|
packagedEmitsAuthorityRefs,
|
|
691
692
|
packagedGateStageLabel,
|
|
692
693
|
packagedGateSummon,
|
|
693
|
-
|
|
694
|
+
packagedMethodSkillNames,
|
|
694
695
|
packagedModelParent,
|
|
695
696
|
packagedNavigatorSubject,
|
|
696
697
|
packagedProjectsTargetBindRejection,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { execFile, spawn } from "node:child_process";
|
|
7
7
|
import { constants } from "node:fs";
|
|
8
8
|
import { access, appendFile, readFile, realpath } from "node:fs/promises";
|
|
9
|
-
import {
|
|
9
|
+
import { delimiter, dirname, isAbsolute, join, resolve } from "node:path";
|
|
10
10
|
import { platform } from "node:process";
|
|
11
11
|
import { promisify } from "node:util";
|
|
12
12
|
import { randomUUID } from "node:crypto";
|
|
@@ -67,33 +67,11 @@ function buildMethodArgs(methods) {
|
|
|
67
67
|
const skillArgs = [];
|
|
68
68
|
for (const method of methods) {
|
|
69
69
|
if (method.kind === "skill") {
|
|
70
|
-
skillArgs.push("--skill", method.path);
|
|
70
|
+
skillArgs.push("--skill", dirname(method.path));
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
return skillArgs;
|
|
74
74
|
}
|
|
75
|
-
/**
|
|
76
|
-
* Pi-native `/skill:<name>` for a single forced method (ADR 0082: pi is one adapter
|
|
77
|
-
* with no privilege; Pi-only seams stay inside the pi adapter).
|
|
78
|
-
* Driven by typed RoleTurnRequest.methods — middle-layer decision, Pi-only syntax.
|
|
79
|
-
* Zero/many methods leave the prompt alone (Fixer optional pair stays `--skill` only).
|
|
80
|
-
*/
|
|
81
|
-
export function applyPiNativeSkillInvocation(methods, prompt) {
|
|
82
|
-
const skills = methods.filter((method) => method.kind === "skill");
|
|
83
|
-
if (skills.length !== 1)
|
|
84
|
-
return prompt;
|
|
85
|
-
const name = basename(dirname(skills[0].path));
|
|
86
|
-
if (name.length === 0)
|
|
87
|
-
return prompt;
|
|
88
|
-
const token = `/skill:${name}`;
|
|
89
|
-
const trimmed = prompt.trimStart();
|
|
90
|
-
if (trimmed === token
|
|
91
|
-
|| trimmed.startsWith(`${token} `)
|
|
92
|
-
|| trimmed.startsWith(`${token}\n`)) {
|
|
93
|
-
return prompt;
|
|
94
|
-
}
|
|
95
|
-
return prompt.length === 0 ? token : `${token} ${prompt}`;
|
|
96
|
-
}
|
|
97
75
|
/**
|
|
98
76
|
* Pi last-hop argv after `--no-extensions -e entry` (#819).
|
|
99
77
|
* Activation flag membership comes from middle-layer projectActivationFlags;
|
|
@@ -135,9 +113,7 @@ function piUserDialogueBody(request) {
|
|
|
135
113
|
const _exhaustive = request.continuation;
|
|
136
114
|
return _exhaustive;
|
|
137
115
|
})();
|
|
138
|
-
return
|
|
139
|
-
? rawPrompt
|
|
140
|
-
: applyPiNativeSkillInvocation(request.methods, rawPrompt);
|
|
116
|
+
return rawPrompt;
|
|
141
117
|
}
|
|
142
118
|
const execFileAsync = promisify(execFile);
|
|
143
119
|
async function resolveSelectedPi(command, cwd, env) {
|
package/dist/public-cli/cli.js
CHANGED
|
@@ -12,6 +12,7 @@ import { loadHostProvidersTable, projectHostFacingProvider, renderHostProvidersT
|
|
|
12
12
|
import { packagedModelParent } from "../packaged-role-registry.js";
|
|
13
13
|
import { seatModelOnly } from "./registry.js";
|
|
14
14
|
import { CliUsageError } from "./cli-errors.js";
|
|
15
|
+
import { runMachineSkillSetup } from "./machine-method-skills.js";
|
|
15
16
|
import { appendPiSessionCustomEntry } from "../pi/role-turn-host.js";
|
|
16
17
|
import { composeRoleTurnHostAdapters, formatHostSelectionFailure, HostSelectionError, selectRoleTurnHost, } from "./role-turn-host-resolution.js";
|
|
17
18
|
import { parseAnalystArgv, parsePublicSeatArgv, } from "./invocation.js";
|
|
@@ -793,6 +794,11 @@ export async function runAkRole(argv, env) {
|
|
|
793
794
|
exitCode: await runConfigCommand(parsed.args, home, env.packageRoot, io),
|
|
794
795
|
};
|
|
795
796
|
}
|
|
797
|
+
if (parsed.command === "setup") {
|
|
798
|
+
if (parsed.args.length !== 0)
|
|
799
|
+
throw new CliUsageError("setup takes no arguments");
|
|
800
|
+
return { exitCode: await runMachineSkillSetup(home, io.stdout) };
|
|
801
|
+
}
|
|
796
802
|
// #724 explicit fresh summons: `ak-role new <role> …` — same role argv, always mint.
|
|
797
803
|
// Rewrites onto the role command with freshSummons; auto-resume and resume stay intact.
|
|
798
804
|
if (parsed.command === "new") {
|
|
@@ -8,17 +8,17 @@ import { resolve, sep } from "node:path";
|
|
|
8
8
|
import { isSafePositiveTicketNumber, readBoardTicketNumber } from "../run-ticket-number.js";
|
|
9
9
|
import { NotarySourceRunError, resolveNotarySourceRunLocator } from "../notary-source-run.js";
|
|
10
10
|
import { engineSessionMaterialFromOptions, pickEngineAxis } from "../package-resources/engine-material.js";
|
|
11
|
-
import {
|
|
12
|
-
import { packagedAdmitsCountersign, packagedBindsBoardTicket, packagedMethodLoadFailureCause, packagedRebindSourceOnResume, packagedRoleMetadata, } from "../packaged-role-registry.js";
|
|
11
|
+
import { packagedAdmitsCountersign, packagedBindsBoardTicket, packagedRebindSourceOnResume, packagedRoleMetadata, } from "../packaged-role-registry.js";
|
|
13
12
|
import { isAuditorSoulRole } from "../auditor-soul.js";
|
|
14
13
|
import { CliUsageError } from "./cli-errors.js";
|
|
15
14
|
import { admitPublicRole, bindAdmittedTicketNumber, bindCourtTicketNumbersOnAdmitted, buildInstructionTransportPrompt, materializeCountersignInvocation, persistAdmittedSourceRunPath, recordAdmittedCorrelation, recordChildDiaristRun, relocateAdmittedRunToTicket, withPreparedAttachments, } from "./invocation.js";
|
|
16
|
-
import { presentControlledFailure, prepareSummonsResumeMaterials,
|
|
15
|
+
import { presentControlledFailure, prepareSummonsResumeMaterials, roleTurnOptions, runPostAdmissionOneShot, runPostAdmissionResumable, runPostAdmissionSeatResume, resumeTurnRequestProjectionOptions, } from "./post-admission.js";
|
|
17
16
|
import { buildAutoResumeContinuationPrompt, loadResumablePublicRole, markRunAdmitted, parentRunPathFromGatePointerInstruction, } from "./run-lifecycle.js";
|
|
18
17
|
import { tryResumeSameTicketSeatRun } from "./seat-ticket-binding.js";
|
|
19
18
|
import { presentStructuralRejection, seatKnownFailureResolver, trySettlePublicSeat, } from "./settlement.js";
|
|
19
|
+
import { warnMissingMethodSkills } from "./machine-method-skills.js";
|
|
20
20
|
import { formatTerminalResult, isLawfulTypedTerminalOutcome, } from "./terminal.js";
|
|
21
|
-
import { admittedSeatTurnDetails,
|
|
21
|
+
import { admittedSeatTurnDetails, projectRoleTurnRequest, requiredMethodSkills, } from "./turn-request.js";
|
|
22
22
|
import { invokeCourtDiarist, runCountersignCourtDiaristStation, } from "./countersign-run.js";
|
|
23
23
|
function roleRecord(role) {
|
|
24
24
|
const record = packagedRoleMetadata(role);
|
|
@@ -29,7 +29,7 @@ function roleRecord(role) {
|
|
|
29
29
|
}
|
|
30
30
|
/** Project any admitted public role onto the host-neutral turn request. */
|
|
31
31
|
export function buildInstructionSeatTurnRequest(admitted, options) {
|
|
32
|
-
return projectRoleTurnRequest(admitted, admittedSeatTurnDetails(admitted, options.
|
|
32
|
+
return projectRoleTurnRequest(admitted, admittedSeatTurnDetails(admitted, options.home, options.host), options);
|
|
33
33
|
}
|
|
34
34
|
function initialPrompt(admitted, env) {
|
|
35
35
|
const record = roleRecord(admitted.role);
|
|
@@ -58,11 +58,11 @@ async function bindAndRelocateDiarist(admitted, authority, lease) {
|
|
|
58
58
|
}
|
|
59
59
|
await relocateAdmittedRunToTicket(admitted, authority, lease);
|
|
60
60
|
}
|
|
61
|
-
function seatAdapters(admitted, env
|
|
61
|
+
function seatAdapters(admitted, env) {
|
|
62
62
|
const record = roleRecord(admitted.role);
|
|
63
63
|
const present = "presentSettled" in record ? record.presentSettled : "default";
|
|
64
64
|
return {
|
|
65
|
-
trySettle: (seat, authority, scope) => trySettlePublicSeat(seat, authority, scope
|
|
65
|
+
trySettle: (seat, authority, scope) => trySettlePublicSeat(seat, authority, scope),
|
|
66
66
|
...(present === "always" ? { shouldPresentSettled: () => true } : {}),
|
|
67
67
|
...(present === "typed"
|
|
68
68
|
? { shouldPresentSettled: (terminal) => isLawfulTypedTerminalOutcome(terminal.roleOutcome) }
|
|
@@ -126,24 +126,8 @@ async function withAuditorSoulEnv(options) {
|
|
|
126
126
|
}
|
|
127
127
|
async function dispatchAdmitted(admitted, env, io) {
|
|
128
128
|
const record = roleRecord(admitted.role);
|
|
129
|
-
|
|
130
|
-
const
|
|
131
|
-
if (skill !== undefined) {
|
|
132
|
-
try {
|
|
133
|
-
material = await loadPackagedMethodSkillMaterial(env.packageRoot, skill);
|
|
134
|
-
}
|
|
135
|
-
catch (error) {
|
|
136
|
-
const knownCause = packagedMethodLoadFailureCause(admitted.role);
|
|
137
|
-
return await presentControlledFailure(admitted, {
|
|
138
|
-
timedOut: false,
|
|
139
|
-
code: null,
|
|
140
|
-
stderr: "",
|
|
141
|
-
thrown: error,
|
|
142
|
-
...(knownCause === undefined ? {} : { knownCause }),
|
|
143
|
-
}, seatAdapters(admitted, env), env.principalAuthority, io);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
const adapters = seatAdapters(admitted, env, material);
|
|
129
|
+
await warnMissingMethodSkills(env.home, env.host, admitted.role, requiredMethodSkills(admitted), io.stdout);
|
|
130
|
+
const adapters = seatAdapters(admitted, env);
|
|
147
131
|
const execute = async (activeEnv) => {
|
|
148
132
|
const auto = "inCallAutoResume" in record && record.inCallAutoResume === true;
|
|
149
133
|
if (auto) {
|
|
@@ -650,21 +634,9 @@ export async function runPublicInstructionSeatResume(request, env, io) {
|
|
|
650
634
|
adapters: {
|
|
651
635
|
trySettle: async () => undefined,
|
|
652
636
|
},
|
|
653
|
-
afterAdmittedLoad: (admitted) => {
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
return Promise.resolve({ kind: "continue", adapters: seatAdapters(admitted, env) });
|
|
657
|
-
}
|
|
658
|
-
const knownCause = packagedMethodLoadFailureCause(admitted.role);
|
|
659
|
-
return resolveResumeMethodMaterialAdapters({
|
|
660
|
-
admitted,
|
|
661
|
-
authority: env.principalAuthority,
|
|
662
|
-
io,
|
|
663
|
-
loadMaterial: () => loadPackagedMethodSkillMaterial(env.packageRoot, skill),
|
|
664
|
-
adaptersWith: (material) => seatAdapters(admitted, env, material),
|
|
665
|
-
emptyAdapters: seatAdapters(admitted, env),
|
|
666
|
-
...(knownCause === undefined ? {} : { knownCause }),
|
|
667
|
-
});
|
|
637
|
+
afterAdmittedLoad: async (admitted) => {
|
|
638
|
+
await warnMissingMethodSkills(env.home, env.host, admitted.role, requiredMethodSkills(admitted), io.stdout);
|
|
639
|
+
return { kind: "continue", adapters: seatAdapters(admitted, env) };
|
|
668
640
|
},
|
|
669
641
|
...(env.engine === undefined ? {} : { effectiveEngine: env.engine }),
|
|
670
642
|
});
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { accessSync, constants, statSync } from "node:fs";
|
|
2
|
+
import { lstat, mkdir, symlink } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { spawnSync } from "node:child_process";
|
|
5
|
+
import { HEADLESS_HOST_DESCRIPTIONS, HOST_DESCRIPTIONS } from "../host-descriptions.js";
|
|
6
|
+
import { packagedMethodSkillNames } from "../packaged-role-registry.js";
|
|
7
|
+
/** Install source only. Which names are required comes from the role registry. */
|
|
8
|
+
const SKILL_SOURCE = {
|
|
9
|
+
tdd: "mattpocock/skills",
|
|
10
|
+
"diagnosing-bugs": "mattpocock/skills",
|
|
11
|
+
"resolving-merge-conflicts": "mattpocock/skills",
|
|
12
|
+
"ak-cross-m-review": "Akagilnc/ak-cross-m-review",
|
|
13
|
+
};
|
|
14
|
+
function skillRoot(home) {
|
|
15
|
+
return join(home, ".agents/skills");
|
|
16
|
+
}
|
|
17
|
+
export function installedMethodSkillPath(home, name) {
|
|
18
|
+
return installedSkillPath(skillRoot(home), name);
|
|
19
|
+
}
|
|
20
|
+
function installedSkillPath(root, name) {
|
|
21
|
+
const path = join(root, name, "SKILL.md");
|
|
22
|
+
try {
|
|
23
|
+
if (!statSync(path).isFile())
|
|
24
|
+
return undefined;
|
|
25
|
+
accessSync(path, constants.R_OK);
|
|
26
|
+
return path;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
const code = error.code;
|
|
30
|
+
if (code === "ENOENT" || code === "ENOTDIR" || code === "EACCES" || code === "EPERM" || code === "ELOOP")
|
|
31
|
+
return undefined;
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function linkedSkillRoot(home, host) {
|
|
36
|
+
if (host === "claude" || host === "claude-code") {
|
|
37
|
+
return join(process.env.CLAUDE_CONFIG_DIR?.trim() || join(home, ".claude"), "skills");
|
|
38
|
+
}
|
|
39
|
+
if (host === "hermes")
|
|
40
|
+
return join(home, ".hermes/skills");
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
async function occupied(path) {
|
|
44
|
+
try {
|
|
45
|
+
await lstat(path);
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
if (error.code !== "ENOENT")
|
|
50
|
+
throw error;
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function warnOccupied(path, stdout) {
|
|
55
|
+
stdout(`Warning: ${path} is already occupied; left untouched.\n`);
|
|
56
|
+
}
|
|
57
|
+
export async function warnMissingMethodSkills(home, host, role, skills, stdout) {
|
|
58
|
+
const missing = [];
|
|
59
|
+
const linkedRoot = linkedSkillRoot(home, host);
|
|
60
|
+
for (const skill of skills) {
|
|
61
|
+
if (installedMethodSkillPath(home, skill) === undefined ||
|
|
62
|
+
(linkedRoot !== undefined && installedSkillPath(linkedRoot, skill) === undefined))
|
|
63
|
+
missing.push(skill);
|
|
64
|
+
}
|
|
65
|
+
for (const skill of missing) {
|
|
66
|
+
stdout(`Warning: required machine Skill "${skill}" is missing for ${role}; its method guidance may be unavailable and reduce work quality. Run \`ak-role setup\` to install required Skills.\n`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function runSkillsCli(args, home) {
|
|
70
|
+
const result = spawnSync("npx", ["--yes", "skills", ...args], {
|
|
71
|
+
stdio: "inherit",
|
|
72
|
+
env: { ...process.env, HOME: home },
|
|
73
|
+
});
|
|
74
|
+
if (result.error !== undefined)
|
|
75
|
+
throw result.error;
|
|
76
|
+
return result.status === 0;
|
|
77
|
+
}
|
|
78
|
+
function addSkills(source, skills, home) {
|
|
79
|
+
if (skills.length === 0)
|
|
80
|
+
return true;
|
|
81
|
+
return runSkillsCli([
|
|
82
|
+
"add", source,
|
|
83
|
+
...skills.flatMap((skill) => ["--skill", skill]),
|
|
84
|
+
"--agent", "codex", "--global", "--yes",
|
|
85
|
+
], home);
|
|
86
|
+
}
|
|
87
|
+
function updateRequiredSkills(home) {
|
|
88
|
+
const names = packagedMethodSkillNames();
|
|
89
|
+
if (names.length === 0)
|
|
90
|
+
return true;
|
|
91
|
+
return runSkillsCli(["update", "-g", "-y", ...names], home);
|
|
92
|
+
}
|
|
93
|
+
/** Explicit user-run setup; delegates acquisition/install to the ecosystem Skills CLI. */
|
|
94
|
+
export async function runMachineSkillSetup(home, stdout) {
|
|
95
|
+
const canonical = skillRoot(home);
|
|
96
|
+
const missingBySource = new Map();
|
|
97
|
+
let unsourced = false;
|
|
98
|
+
for (const name of packagedMethodSkillNames()) {
|
|
99
|
+
const path = join(canonical, name);
|
|
100
|
+
if (await occupied(path)) {
|
|
101
|
+
warnOccupied(path, stdout);
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const source = SKILL_SOURCE[name];
|
|
105
|
+
if (source === undefined) {
|
|
106
|
+
unsourced = true;
|
|
107
|
+
stdout(`Warning: required machine Skill "${name}" has no install source; setup did not install it.\n`);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
const missing = missingBySource.get(source) ?? [];
|
|
111
|
+
missing.push(name);
|
|
112
|
+
missingBySource.set(source, missing);
|
|
113
|
+
}
|
|
114
|
+
for (const [source, missing] of missingBySource) {
|
|
115
|
+
if (!addSkills(source, missing, home))
|
|
116
|
+
return 1;
|
|
117
|
+
}
|
|
118
|
+
if (unsourced)
|
|
119
|
+
return 1;
|
|
120
|
+
for (const host of ["claude-code", "hermes"]) {
|
|
121
|
+
const root = linkedSkillRoot(home, host);
|
|
122
|
+
const binaryFromHome = host === "claude-code"
|
|
123
|
+
? HEADLESS_HOST_DESCRIPTIONS.claude.binaryFromHome
|
|
124
|
+
: HOST_DESCRIPTIONS.hermes.binaryFromHome;
|
|
125
|
+
try {
|
|
126
|
+
accessSync(join(home, ...binaryFromHome), constants.X_OK);
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
if (["ENOENT", "ENOTDIR", "EACCES"].includes(error.code ?? ""))
|
|
130
|
+
continue;
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
for (const name of packagedMethodSkillNames()) {
|
|
134
|
+
const target = join(canonical, name);
|
|
135
|
+
if (installedMethodSkillPath(home, name) === undefined)
|
|
136
|
+
continue;
|
|
137
|
+
const link = join(root, name);
|
|
138
|
+
if (await occupied(link)) {
|
|
139
|
+
warnOccupied(link, stdout);
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
await mkdir(root, { recursive: true });
|
|
143
|
+
await symlink(target, link, "dir");
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (!updateRequiredSkills(home))
|
|
147
|
+
return 1;
|
|
148
|
+
stdout("Machine method Skills setup finished. Existing same-name Skills were left untouched.\n");
|
|
149
|
+
return 0;
|
|
150
|
+
}
|