@sublang/playbook 17.3.0 → 17.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/docs/configuration.md +45 -4
- package/docs/embedding.md +94 -0
- package/package.json +34 -5
- package/reference/sdlc/captain.md +6 -4
- package/reference/sdlc/captain.playbook/captain.fsm.d.ts +5 -0
- package/reference/sdlc/captain.playbook/captain.fsm.js +4 -3
- package/reference/sdlc/captain.playbook/captain.fsm.ts +9 -4
- package/reference/sdlc/captain.playbook/captain.gears.md +6 -3
- package/reference/sdlc/captain.playbook/captain.playbook.d.ts +2 -0
- package/reference/sdlc/captain.playbook/captain.playbook.js +7 -3
- package/reference/sdlc/captain.playbook/captain.playbook.ts +8 -4
- package/reference/sdlc/code.md +24 -4
- package/reference/sdlc/code.playbook/asset-types.d.ts +32 -0
- package/reference/sdlc/code.playbook/bin/launch-config.js +2 -0
- package/reference/sdlc/code.playbook/bin/portable-codec.js +12 -5
- package/reference/sdlc/code.playbook/bin/run.js +68 -4
- package/reference/sdlc/code.playbook/bin/session-host.js +16 -4
- package/reference/sdlc/code.playbook/bin/session-media.js +46 -0
- package/reference/sdlc/code.playbook/bin/session-store.js +145 -13
- package/reference/sdlc/code.playbook/code.fsm.d.ts +12 -0
- package/reference/sdlc/code.playbook/code.fsm.js +40 -6
- package/reference/sdlc/code.playbook/code.fsm.ts +53 -6
- package/reference/sdlc/code.playbook/code.gears.md +32 -4
- package/reference/sdlc/code.playbook/playbook-captain.d.ts +17 -1
- package/reference/sdlc/code.playbook/playbook-captain.js +201 -19
- package/reference/sdlc/code.playbook/playbook-captain.ts +224 -24
- package/reference/sdlc/code.playbook/playbook.config.template.yaml +16 -3
- package/reference/sdlc/code.playbook/session-assets.d.ts +53 -0
- package/reference/sdlc/code.playbook/session-assets.js +303 -0
- package/reference/sdlc/code.playbook/session-host.d.ts +9 -1
- package/reference/sdlc/code.playbook/session-store.d.ts +26 -2
- package/reference/sdlc/code.playbook/worker-evidence.d.ts +8 -0
- package/reference/sdlc/code.playbook/worker-evidence.js +51 -0
- package/reference/sdlc/inspect.md +40 -0
- package/reference/sdlc/inspect.playbook/inspect.fsm.d.ts +168 -0
- package/reference/sdlc/inspect.playbook/inspect.fsm.js +354 -0
- package/reference/sdlc/inspect.playbook/inspect.fsm.ts +455 -0
- package/reference/sdlc/inspect.playbook/inspect.gears.md +36 -0
- package/reference/sdlc/inspect.playbook/inspect.playbook.d.ts +17 -0
- package/reference/sdlc/inspect.playbook/inspect.playbook.js +142 -0
- package/reference/sdlc/inspect.playbook/inspect.playbook.ts +184 -0
- package/reference/sdlc/inspect.playbook/inspect.registry.d.ts +41 -0
- package/reference/sdlc/inspect.playbook/inspect.registry.js +51 -0
- package/reference/sdlc/inspect.playbook/inspect.registry.ts +110 -0
- package/slc/gears2fsm.md +17 -3
- package/slc/text2gears.md +7 -0
- package/slc/workflow-contracts.json +43 -1
- package/src/xstate-playbook-runtime.js +5 -0
- package/src/xstate-playbook-runtime.ts +7 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
|
|
3
|
+
// Generated by slc/materialize-link.mjs; governed by the complete slc/link.md.
|
|
4
|
+
// FSM: "./inspect.fsm.js"; export: inspectMachine; strategies: shared defaults with labelled string relays and nested actors.
|
|
5
|
+
import { inspectMachine as machine } from "./inspect.fsm.js";
|
|
6
|
+
import type { PlayerInput as SourcePlayerInput } from "./inspect.fsm.js";
|
|
7
|
+
import {
|
|
8
|
+
createXStatePlaybookRuntime, snapshotJsonValue,
|
|
9
|
+
composePlayerContinuation, type XStatePromptIdentity,
|
|
10
|
+
type PlaybookPlayerInput,
|
|
11
|
+
type XStatePlaybookRuntimeConstruction,
|
|
12
|
+
type XStatePlaybookRuntimeFactory,
|
|
13
|
+
type XStatePlaybookRuntimeSpecV3,
|
|
14
|
+
} from '@sublang/playbook/xstate-runtime';
|
|
15
|
+
export type {
|
|
16
|
+
PlayerResult,
|
|
17
|
+
PlayerCallOptions,
|
|
18
|
+
PlayerSessionStore,
|
|
19
|
+
CaptainResult,
|
|
20
|
+
CaptainCallOptions,
|
|
21
|
+
JsonValue,
|
|
22
|
+
NormalizedError,
|
|
23
|
+
PlaybookCallRequest,
|
|
24
|
+
PlaybookCallResult,
|
|
25
|
+
PlaybookCallStart,
|
|
26
|
+
PlaybookStateValue,
|
|
27
|
+
PlaybookState,
|
|
28
|
+
PlaybookPendingCall,
|
|
29
|
+
PlaybookRunResult,
|
|
30
|
+
PlaybookRuntime,
|
|
31
|
+
PlaybookRuntimeFactory,
|
|
32
|
+
PlaybookRuntimeSnapshot,
|
|
33
|
+
PlaybookSession,
|
|
34
|
+
PlaybookPorts,
|
|
35
|
+
PlaybookTraceEvent,
|
|
36
|
+
PlaybookTraceType,
|
|
37
|
+
PlaybookControlReceipt,
|
|
38
|
+
PlaybookControlView,
|
|
39
|
+
} from '@sublang/playbook/runtime';
|
|
40
|
+
|
|
41
|
+
export interface PlaybookRuntimeOptions {
|
|
42
|
+
readonly "discussionContext"?: string;
|
|
43
|
+
}
|
|
44
|
+
export type PlaybookHostCapabilities = XStatePlaybookRuntimeConstruction<
|
|
45
|
+
PlaybookRuntimeOptions, { readonly authority: object }
|
|
46
|
+
>['hostCapabilities'];
|
|
47
|
+
|
|
48
|
+
const OPTION_SCHEMA = {
|
|
49
|
+
"discussionContext": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"required": false
|
|
52
|
+
}
|
|
53
|
+
} as const;
|
|
54
|
+
const INPUT_MAPPING = {
|
|
55
|
+
"discussionContext": "discussionContext"
|
|
56
|
+
} as const;
|
|
57
|
+
const RESUMABLE_STATE_IDS: ReadonlySet<string> = new Set([
|
|
58
|
+
"inspecting"
|
|
59
|
+
]);
|
|
60
|
+
const UNFINISHED_FINAL_STATE_IDS: ReadonlySet<string> = new Set([
|
|
61
|
+
"unavailable"
|
|
62
|
+
]);
|
|
63
|
+
const VERBATIM_PAYLOAD_FIELDS: ReadonlySet<string> = new Set([
|
|
64
|
+
"report"
|
|
65
|
+
]);
|
|
66
|
+
export function validateOptions(value: unknown): PlaybookRuntimeOptions {
|
|
67
|
+
const captured = snapshotJsonValue(value === undefined ? {} : value, "INSPECT runtime options");
|
|
68
|
+
if (captured === null || typeof captured !== 'object' || Array.isArray(captured)) {
|
|
69
|
+
throw new TypeError("INSPECT runtime options must be an object");
|
|
70
|
+
}
|
|
71
|
+
const fields = captured as Readonly<Record<string, unknown>>;
|
|
72
|
+
for (const key of Object.keys(captured)) {
|
|
73
|
+
if (!Object.hasOwn(OPTION_SCHEMA, key)) throw new TypeError("INSPECT runtime options." + key + ' is not declared');
|
|
74
|
+
}
|
|
75
|
+
for (const [key, schema] of Object.entries(OPTION_SCHEMA) as [string, { type: string; required: boolean }][]) {
|
|
76
|
+
if (!Object.hasOwn(captured, key)) {
|
|
77
|
+
if (schema.required) throw new TypeError("INSPECT runtime options." + key + ' is required');
|
|
78
|
+
} else if (typeof fields[key] !== schema.type || (schema.type === 'number' && !Number.isFinite(fields[key]))) {
|
|
79
|
+
throw new TypeError("INSPECT runtime options." + key + ' must be a ' + schema.type);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return captured as unknown as PlaybookRuntimeOptions;
|
|
83
|
+
}
|
|
84
|
+
function renderPlayerPrompt(input: SourcePlayerInput, promptIdentity: XStatePromptIdentity, resuming = false): string {
|
|
85
|
+
const fields = input as unknown as Readonly<Record<string, unknown>>;
|
|
86
|
+
const mapping: Readonly<Record<string, string>> = {};
|
|
87
|
+
const identities: Readonly<Record<string, string>> = {};
|
|
88
|
+
const omitted = new Set<string>(["> Discussion context: <discussion-context>"]);
|
|
89
|
+
const fieldFor = (token: string): string => Object.hasOwn(mapping, token) ? mapping[token]! : (token === '#' ? 'irNumber' : token.replace(/-([A-Za-z0-9_$])/g, (_match: string, next: string) => next.toUpperCase()));
|
|
90
|
+
const parts = input.prompt.split(/(\r?\n)/);
|
|
91
|
+
let body = '';
|
|
92
|
+
for (let index = 0; index < parts.length; index += 2) {
|
|
93
|
+
const line = parts[index]!;
|
|
94
|
+
if (omitted.has(line)) {
|
|
95
|
+
const token = /<(#|[A-Za-z_$][A-Za-z0-9_$-]*)>$/.exec(line)![1]!;
|
|
96
|
+
if (fields[fieldFor(token)] === '') continue;
|
|
97
|
+
}
|
|
98
|
+
body += line.replace(/<(#|[A-Za-z_$][A-Za-z0-9_$-]*)>/g, (match: string, token: string): string => {
|
|
99
|
+
const value = Object.hasOwn(identities, token) ? promptIdentity(identities[token]!) : fields[fieldFor(token)];
|
|
100
|
+
if (typeof value !== 'string') return match;
|
|
101
|
+
return line.startsWith('> ') ? value.replace(/\r?\n/g, (ending: string) => ending + '> ') : value;
|
|
102
|
+
}) + (parts[index + 1] ?? '');
|
|
103
|
+
}
|
|
104
|
+
return composePlayerContinuation(input, body, resuming);
|
|
105
|
+
}
|
|
106
|
+
const composePlayerPrompt = (input: PlaybookPlayerInput, promptIdentity: XStatePromptIdentity, resuming?: boolean): string =>
|
|
107
|
+
renderPlayerPrompt(input as SourcePlayerInput, promptIdentity, resuming);
|
|
108
|
+
const runtimeSpec = {
|
|
109
|
+
composePlayerPrompt,
|
|
110
|
+
...{
|
|
111
|
+
"label": "INSPECT",
|
|
112
|
+
"compat": {
|
|
113
|
+
"artifactSchema": 3,
|
|
114
|
+
"runtimeAbi": 1
|
|
115
|
+
},
|
|
116
|
+
"entryEvent": {
|
|
117
|
+
"type": "START",
|
|
118
|
+
"textField": "inspectionRequest",
|
|
119
|
+
"contextField": "inspectionRequest"
|
|
120
|
+
},
|
|
121
|
+
"bossEvents": [],
|
|
122
|
+
"roleStates": {
|
|
123
|
+
"inspecting": {
|
|
124
|
+
"role": "inspector",
|
|
125
|
+
"label": "Inspector investigates the requested material and gives an evidence-based explanation."
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
"outcomeAuthority": {
|
|
129
|
+
"governedPlayerStates": {
|
|
130
|
+
"inspecting": {
|
|
131
|
+
"completed": {
|
|
132
|
+
"fields": {
|
|
133
|
+
"status": "semantic",
|
|
134
|
+
"report": "presentation"
|
|
135
|
+
},
|
|
136
|
+
"repositoryDisposition": "unchanged"
|
|
137
|
+
},
|
|
138
|
+
"unavailable": {
|
|
139
|
+
"fields": {
|
|
140
|
+
"status": "semantic",
|
|
141
|
+
"report": "presentation"
|
|
142
|
+
},
|
|
143
|
+
"repositoryDisposition": "unchanged"
|
|
144
|
+
},
|
|
145
|
+
"needsBossReply": {
|
|
146
|
+
"fields": {
|
|
147
|
+
"question": "presentation"
|
|
148
|
+
},
|
|
149
|
+
"repositoryDisposition": "unchanged"
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
"placeholderFields": {},
|
|
155
|
+
"transitionEventFields": [
|
|
156
|
+
"inspectionRequest",
|
|
157
|
+
"discussionContext",
|
|
158
|
+
"answer",
|
|
159
|
+
"questionId"
|
|
160
|
+
],
|
|
161
|
+
"controlContextFields": [
|
|
162
|
+
"inspectionRequest"
|
|
163
|
+
]
|
|
164
|
+
},
|
|
165
|
+
snapshotOptions: validateOptions,
|
|
166
|
+
machineInput: (options: PlaybookRuntimeOptions) => Object.fromEntries(
|
|
167
|
+
Object.entries(INPUT_MAPPING).filter(([, key]) => options[key as keyof PlaybookRuntimeOptions] !== undefined)
|
|
168
|
+
.map(([field, key]) => [field, options[key as keyof PlaybookRuntimeOptions]]),
|
|
169
|
+
),
|
|
170
|
+
verbatimPayloadFields: VERBATIM_PAYLOAD_FIELDS,
|
|
171
|
+
resumableStateIds: RESUMABLE_STATE_IDS,
|
|
172
|
+
unfinishedFinalStateIds: UNFINISHED_FINAL_STATE_IDS,
|
|
173
|
+
} satisfies XStatePlaybookRuntimeSpecV3<PlaybookRuntimeOptions>;
|
|
174
|
+
|
|
175
|
+
export const _internal = {
|
|
176
|
+
composePlayerPrompt,
|
|
177
|
+
RESUMABLE_STATE_IDS,
|
|
178
|
+
UNFINISHED_FINAL_STATE_IDS,
|
|
179
|
+
VERBATIM_PAYLOAD_FIELDS,
|
|
180
|
+
};
|
|
181
|
+
const createPlaybookRuntime: XStatePlaybookRuntimeFactory<
|
|
182
|
+
XStatePlaybookRuntimeConstruction<PlaybookRuntimeOptions, PlaybookHostCapabilities>, 3
|
|
183
|
+
> = createXStatePlaybookRuntime<PlaybookRuntimeOptions, PlaybookHostCapabilities>(machine, runtimeSpec);
|
|
184
|
+
export default createPlaybookRuntime;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type PlaybookRuntimeOptions, type PlaybookHostCapabilities, type PlaybookRuntime } from './inspect.playbook.js';
|
|
2
|
+
import type { PlaybookHostConstructionCapabilities } from '../code.playbook/playbook-captain.js';
|
|
3
|
+
export interface PlaybookSummaryPolicy {
|
|
4
|
+
stateCountLabels: Readonly<Record<string, string>>;
|
|
5
|
+
copyPasteGuardNames: readonly string[];
|
|
6
|
+
savedCountsLine(counts: {
|
|
7
|
+
interruptions: number;
|
|
8
|
+
copyPastes: number;
|
|
9
|
+
}, rounds: number): string;
|
|
10
|
+
}
|
|
11
|
+
export type InspectOptions = PlaybookRuntimeOptions;
|
|
12
|
+
export interface InspectPlaybookRegistryEntry {
|
|
13
|
+
id: 'inspect';
|
|
14
|
+
command: 'inspect';
|
|
15
|
+
intent: string;
|
|
16
|
+
artifactSchema: 3;
|
|
17
|
+
runtimeProfile: {
|
|
18
|
+
readonly kind: 'shared-factory';
|
|
19
|
+
readonly compat: {
|
|
20
|
+
readonly artifactSchema: 3;
|
|
21
|
+
readonly runtimeAbi: number;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
requiredRoleIds: readonly ['inspector'];
|
|
25
|
+
concurrentRoleSets: readonly [];
|
|
26
|
+
summaryPolicy: PlaybookSummaryPolicy;
|
|
27
|
+
validateOptions(optionSlice: unknown): InspectOptions;
|
|
28
|
+
createRuntime(options: InspectOptions, hostCapabilities: PlaybookHostConstructionCapabilities & PlaybookHostCapabilities): PlaybookRuntime;
|
|
29
|
+
}
|
|
30
|
+
export declare const inspectStateCountLabels: {
|
|
31
|
+
readonly inspecting: "inspection round";
|
|
32
|
+
};
|
|
33
|
+
export declare const inspectCopyPasteGuardNames: readonly ["completed"];
|
|
34
|
+
export declare function inspectSavedCountsLine(counts: {
|
|
35
|
+
interruptions: number;
|
|
36
|
+
copyPastes: number;
|
|
37
|
+
}, rounds: number): string;
|
|
38
|
+
export declare const inspectSummaryPolicy: PlaybookSummaryPolicy;
|
|
39
|
+
export declare function validateInspectOptions(optionSlice: unknown): InspectOptions;
|
|
40
|
+
export declare const inspectPlaybookRegistryEntry: InspectPlaybookRegistryEntry;
|
|
41
|
+
export default inspectPlaybookRegistryEntry;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
|
|
3
|
+
import createPlaybookRuntime, { validateOptions, } from './inspect.playbook.js';
|
|
4
|
+
// INSPECT counts its delegated evidence-gathering calls as inspection rounds.
|
|
5
|
+
export const inspectStateCountLabels = {
|
|
6
|
+
inspecting: 'inspection round',
|
|
7
|
+
};
|
|
8
|
+
export const inspectCopyPasteGuardNames = ['completed'];
|
|
9
|
+
function countNoun(count, singular, plural = `${singular}s`) {
|
|
10
|
+
return `${count} ${count === 1 ? singular : plural}`;
|
|
11
|
+
}
|
|
12
|
+
export function inspectSavedCountsLine(counts, rounds) {
|
|
13
|
+
return [
|
|
14
|
+
'Saved you',
|
|
15
|
+
countNoun(counts.interruptions, 'interruption'),
|
|
16
|
+
'and',
|
|
17
|
+
countNoun(counts.copyPastes, 'copy-paste'),
|
|
18
|
+
'across',
|
|
19
|
+
countNoun(rounds, 'round'),
|
|
20
|
+
'of inspection.',
|
|
21
|
+
].join(' ');
|
|
22
|
+
}
|
|
23
|
+
export const inspectSummaryPolicy = {
|
|
24
|
+
stateCountLabels: inspectStateCountLabels,
|
|
25
|
+
copyPasteGuardNames: inspectCopyPasteGuardNames,
|
|
26
|
+
savedCountsLine: inspectSavedCountsLine,
|
|
27
|
+
};
|
|
28
|
+
export function validateInspectOptions(optionSlice) {
|
|
29
|
+
return validateOptions(optionSlice);
|
|
30
|
+
}
|
|
31
|
+
export const inspectPlaybookRegistryEntry = {
|
|
32
|
+
id: 'inspect',
|
|
33
|
+
command: 'inspect',
|
|
34
|
+
intent: 'inspect supplied material or a running web interface and explain observed evidence without changing the repository',
|
|
35
|
+
artifactSchema: 3,
|
|
36
|
+
runtimeProfile: Object.freeze({
|
|
37
|
+
kind: 'shared-factory',
|
|
38
|
+
compat: createPlaybookRuntime.compat,
|
|
39
|
+
}),
|
|
40
|
+
requiredRoleIds: ['inspector'],
|
|
41
|
+
concurrentRoleSets: [],
|
|
42
|
+
summaryPolicy: inspectSummaryPolicy,
|
|
43
|
+
validateOptions: validateInspectOptions,
|
|
44
|
+
createRuntime(options, hostCapabilities) {
|
|
45
|
+
return createPlaybookRuntime({
|
|
46
|
+
configuredOptions: options,
|
|
47
|
+
hostCapabilities,
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
export default inspectPlaybookRegistryEntry;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
|
|
3
|
+
|
|
4
|
+
import createPlaybookRuntime, {
|
|
5
|
+
validateOptions,
|
|
6
|
+
type PlaybookRuntimeOptions,
|
|
7
|
+
type PlaybookHostCapabilities,
|
|
8
|
+
type PlaybookRuntime,
|
|
9
|
+
} from './inspect.playbook.js';
|
|
10
|
+
import type { PlaybookHostConstructionCapabilities } from '../code.playbook/playbook-captain.js';
|
|
11
|
+
|
|
12
|
+
export interface PlaybookSummaryPolicy {
|
|
13
|
+
stateCountLabels: Readonly<Record<string, string>>;
|
|
14
|
+
copyPasteGuardNames: readonly string[];
|
|
15
|
+
savedCountsLine(
|
|
16
|
+
counts: { interruptions: number; copyPastes: number },
|
|
17
|
+
rounds: number,
|
|
18
|
+
): string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type InspectOptions = PlaybookRuntimeOptions;
|
|
22
|
+
|
|
23
|
+
export interface InspectPlaybookRegistryEntry {
|
|
24
|
+
id: 'inspect';
|
|
25
|
+
command: 'inspect';
|
|
26
|
+
intent: string;
|
|
27
|
+
artifactSchema: 3;
|
|
28
|
+
runtimeProfile: {
|
|
29
|
+
readonly kind: 'shared-factory';
|
|
30
|
+
readonly compat: {
|
|
31
|
+
readonly artifactSchema: 3;
|
|
32
|
+
readonly runtimeAbi: number;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
requiredRoleIds: readonly ['inspector'];
|
|
36
|
+
concurrentRoleSets: readonly [];
|
|
37
|
+
summaryPolicy: PlaybookSummaryPolicy;
|
|
38
|
+
validateOptions(optionSlice: unknown): InspectOptions;
|
|
39
|
+
// The linked module types live authority as opaque (link-materialization);
|
|
40
|
+
// the Captain entry binds its own construction capabilities here.
|
|
41
|
+
createRuntime(
|
|
42
|
+
options: InspectOptions,
|
|
43
|
+
hostCapabilities: PlaybookHostConstructionCapabilities &
|
|
44
|
+
PlaybookHostCapabilities,
|
|
45
|
+
): PlaybookRuntime;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// INSPECT counts its delegated evidence-gathering calls as inspection rounds.
|
|
49
|
+
export const inspectStateCountLabels = {
|
|
50
|
+
inspecting: 'inspection round',
|
|
51
|
+
} as const;
|
|
52
|
+
|
|
53
|
+
export const inspectCopyPasteGuardNames = ['completed'] as const;
|
|
54
|
+
|
|
55
|
+
function countNoun(
|
|
56
|
+
count: number,
|
|
57
|
+
singular: string,
|
|
58
|
+
plural = `${singular}s`,
|
|
59
|
+
): string {
|
|
60
|
+
return `${count} ${count === 1 ? singular : plural}`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function inspectSavedCountsLine(
|
|
64
|
+
counts: { interruptions: number; copyPastes: number },
|
|
65
|
+
rounds: number,
|
|
66
|
+
): string {
|
|
67
|
+
return [
|
|
68
|
+
'Saved you',
|
|
69
|
+
countNoun(counts.interruptions, 'interruption'),
|
|
70
|
+
'and',
|
|
71
|
+
countNoun(counts.copyPastes, 'copy-paste'),
|
|
72
|
+
'across',
|
|
73
|
+
countNoun(rounds, 'round'),
|
|
74
|
+
'of inspection.',
|
|
75
|
+
].join(' ');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export const inspectSummaryPolicy: PlaybookSummaryPolicy = {
|
|
79
|
+
stateCountLabels: inspectStateCountLabels,
|
|
80
|
+
copyPasteGuardNames: inspectCopyPasteGuardNames,
|
|
81
|
+
savedCountsLine: inspectSavedCountsLine,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export function validateInspectOptions(optionSlice: unknown): InspectOptions {
|
|
85
|
+
return validateOptions(optionSlice);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export const inspectPlaybookRegistryEntry: InspectPlaybookRegistryEntry = {
|
|
89
|
+
id: 'inspect',
|
|
90
|
+
command: 'inspect',
|
|
91
|
+
intent:
|
|
92
|
+
'inspect supplied material or a running web interface and explain observed evidence without changing the repository',
|
|
93
|
+
artifactSchema: 3,
|
|
94
|
+
runtimeProfile: Object.freeze({
|
|
95
|
+
kind: 'shared-factory',
|
|
96
|
+
compat: createPlaybookRuntime.compat,
|
|
97
|
+
}),
|
|
98
|
+
requiredRoleIds: ['inspector'],
|
|
99
|
+
concurrentRoleSets: [],
|
|
100
|
+
summaryPolicy: inspectSummaryPolicy,
|
|
101
|
+
validateOptions: validateInspectOptions,
|
|
102
|
+
createRuntime(options, hostCapabilities) {
|
|
103
|
+
return createPlaybookRuntime({
|
|
104
|
+
configuredOptions: options,
|
|
105
|
+
hostCapabilities,
|
|
106
|
+
});
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export default inspectPlaybookRegistryEntry;
|
package/slc/gears2fsm.md
CHANGED
|
@@ -602,6 +602,9 @@ safety beyond the guarded direct transition.
|
|
|
602
602
|
## Context and prompts
|
|
603
603
|
|
|
604
604
|
Context fields used to drive guards or compose prompts shall be **typed and named**.
|
|
605
|
+
Where Source owns array-valued retained discussion whose initial state is no history, initialize that context field to `[]` and reset it to `[]` only at its Source lifecycle boundaries.
|
|
606
|
+
Carry its declared array shape through ordinary and continuation `invoke.input`; do not leave the empty structural history absent so a prompt-contract probe mistakes it for a scalar.
|
|
607
|
+
This empty history is not a default caller intent, prerequisite report, domain evidence, approval, or prior-stage result; those remain unavailable until actually established.
|
|
605
608
|
The compiler shall not branch on untyped properties of `lastResult`; persistent routing decisions belong in typed context fields. (`lastResult` is for inspection only.)
|
|
606
609
|
Where Source declares a finite ordered plan, represent it as a typed readonly
|
|
607
610
|
JSON-safe array and validate that shape on the actor-output transition; an
|
|
@@ -835,8 +838,8 @@ Only
|
|
|
835
838
|
The canonical storage paths are `context.pendingBossQuestion` and `context.bossReply` for the scalar form, or `context.pendingBossQuestions[stateId]` and `context.bossReplies[stateId]` for the keyed form.
|
|
836
839
|
A private wrapper such as `context.continuation` shall not replace these fields directly on machine context.
|
|
837
840
|
|
|
838
|
-
A machine
|
|
839
|
-
|
|
841
|
+
A machine that declares no root parallel group shall use the scalar form;
|
|
842
|
+
keyed storage alone is not visible to the flat shared factory:
|
|
840
843
|
|
|
841
844
|
- An `awaitBossReply` state with stable `id: 'awaitBossReply'`, tag
|
|
842
845
|
`playbook.parked`, and description
|
|
@@ -847,7 +850,9 @@ form:
|
|
|
847
850
|
- `resumableStates(ids)`, `setPendingBossQuestion`, and
|
|
848
851
|
`clearBossReplyContext` helpers with the existing single-question behavior.
|
|
849
852
|
|
|
850
|
-
A machine
|
|
853
|
+
A machine that declares a root parallel group shall use the keyed form
|
|
854
|
+
throughout the machine, including any sequential working leaves and their
|
|
855
|
+
root reply wait:
|
|
851
856
|
|
|
852
857
|
- One local waiting leaf per branch, tagged `playbook.parked`.
|
|
853
858
|
- A `BOSS_REPLY` event carrying `{ questionId: string; answer: string }`.
|
|
@@ -884,6 +889,15 @@ pending question and reply selected for that working leaf as singular
|
|
|
884
889
|
`pendingBossQuestion` and `bossReply` fields, regardless of the scalar or keyed
|
|
885
890
|
context representation, so prompt composition has one stable contract.
|
|
886
891
|
When Source requires earlier discussion or constraints on a later invocation, the compiler shall persist that source-owned history in serializable machine context before replacing or clearing the pending Q/A fields.
|
|
892
|
+
Where that Source-owned value is the complete received Boss reply, retain it
|
|
893
|
+
directly from the current working leaf's canonical reply context at the
|
|
894
|
+
Source-authored accepted-outcome boundary, before clearing that leaf's Q/A.
|
|
895
|
+
Preserve its exact string, including surrounding whitespace, CRLF/LF separators,
|
|
896
|
+
blank lines and trailing separators; do not require a model-produced echo or
|
|
897
|
+
replace it with one. Acceptance remains the acting agent's semantic judgment,
|
|
898
|
+
guarded by the current matching question's state, Source-item and asker binding
|
|
899
|
+
and actual receipt of a nonempty reply. Neither stale question/reply context
|
|
900
|
+
nor a different actor-supplied value establishes that binding or approval.
|
|
887
901
|
The later `invoke.input` shall relay that persisted context on both resumed and fresh calls that Source says need it, preserving Source-owned relevance and format without imposing all-history semantics on sources that do not require it.
|
|
888
902
|
Shared Boss-reply continuation carries only the latest Q/A pair, and a backend continuation token is not durable Source history.
|
|
889
903
|
When both fields are present, the linked runtime shall compose the continuation preamble and labelled Q&A blocks per [link.md "Player prompt composition"](link.md#player-prompt-composition).
|
package/slc/text2gears.md
CHANGED
|
@@ -189,6 +189,13 @@ between the Source and the catalog: leave the Target unwritten and report it
|
|
|
189
189
|
as an incompatible compiler input rather than rename or invent.
|
|
190
190
|
A Source outside those ids is named from its own words as above.
|
|
191
191
|
|
|
192
|
+
A value Source assigns to the received Boss input or reply is already runtime
|
|
193
|
+
input, not a value the acting agent produces. Where Source requires that
|
|
194
|
+
complete value retained for later calls, preserve the exact input's retention
|
|
195
|
+
and the Source's acceptance condition in non-acting GEARS prose; do not declare
|
|
196
|
+
a Judge-extracted echo property for it. The semantic approval or refusal stays
|
|
197
|
+
in the acting result contract.
|
|
198
|
+
|
|
192
199
|
A produced value consumed later shall have a declared producer: where any
|
|
193
200
|
later item's blockquote reads a value through a `<placeholder>`, the item
|
|
194
201
|
whose behavior produces that value shall declare the `Results:` contract
|
|
@@ -359,6 +359,47 @@
|
|
|
359
359
|
}
|
|
360
360
|
]
|
|
361
361
|
}
|
|
362
|
+
},
|
|
363
|
+
"inspect": {
|
|
364
|
+
"callInput": "text",
|
|
365
|
+
"output": {
|
|
366
|
+
"anyOf": [
|
|
367
|
+
{
|
|
368
|
+
"type": "object",
|
|
369
|
+
"properties": {
|
|
370
|
+
"status": {
|
|
371
|
+
"const": "complete"
|
|
372
|
+
},
|
|
373
|
+
"report": {
|
|
374
|
+
"type": "string",
|
|
375
|
+
"description": "Inspector's complete explanation; presentation evidence, not independent effect authority."
|
|
376
|
+
}
|
|
377
|
+
},
|
|
378
|
+
"required": [
|
|
379
|
+
"status",
|
|
380
|
+
"report"
|
|
381
|
+
],
|
|
382
|
+
"additionalProperties": false
|
|
383
|
+
},
|
|
384
|
+
{
|
|
385
|
+
"type": "object",
|
|
386
|
+
"properties": {
|
|
387
|
+
"status": {
|
|
388
|
+
"const": "unavailable"
|
|
389
|
+
},
|
|
390
|
+
"report": {
|
|
391
|
+
"type": "string",
|
|
392
|
+
"description": "Inspector's complete explanation; presentation evidence, not independent effect authority."
|
|
393
|
+
}
|
|
394
|
+
},
|
|
395
|
+
"required": [
|
|
396
|
+
"status",
|
|
397
|
+
"report"
|
|
398
|
+
],
|
|
399
|
+
"additionalProperties": false
|
|
400
|
+
}
|
|
401
|
+
]
|
|
402
|
+
}
|
|
362
403
|
}
|
|
363
404
|
},
|
|
364
405
|
"literalTargetBindings": {
|
|
@@ -366,6 +407,7 @@
|
|
|
366
407
|
"decide": "decide",
|
|
367
408
|
"code": "code",
|
|
368
409
|
"branch": "branch",
|
|
369
|
-
"pr": "pr"
|
|
410
|
+
"pr": "pr",
|
|
411
|
+
"inspect": "inspect"
|
|
370
412
|
}
|
|
371
413
|
}
|
|
@@ -866,12 +866,16 @@ export function defaultExtractRequiredFields(description) {
|
|
|
866
866
|
fields.push(m[1]);
|
|
867
867
|
return fields;
|
|
868
868
|
}
|
|
869
|
+
const CURRENT_CALL_ADJUDICATION_GUIDANCE = "Classify the invoked role's current call by the result it reports at call end, using the full output and declared outcome meanings. " +
|
|
870
|
+
'An earlier interim question is not outstanding when later prose explicitly resolves or supersedes it for this call; a prerequisite only for a later workflow stage does not block an affirmatively completed current call. ' +
|
|
871
|
+
'A genuinely unanswered question needed to finish the current call remains outstanding. A commit statement alone does not establish semantic completion; do not force contradictory or insufficient evidence into a completed outcome.';
|
|
869
872
|
/** Default delegated-player adjudicator prompt. */
|
|
870
873
|
export function defaultBuildJudgePrompt(input, finalText) {
|
|
871
874
|
const lines = [];
|
|
872
875
|
lines.push('This is hidden control work. Do not call tools, inspect files, or ' +
|
|
873
876
|
'seek external evidence. Decide only from the supplied player output ' +
|
|
874
877
|
'and outcome descriptions. Reply with exactly one JSON object and no prose.');
|
|
878
|
+
lines.push(CURRENT_CALL_ADJUDICATION_GUIDANCE);
|
|
875
879
|
lines.push('');
|
|
876
880
|
lines.push(`The ${input.role} role just produced this output:`);
|
|
877
881
|
lines.push('');
|
|
@@ -957,6 +961,7 @@ function buildGovernedJudgePrompt(input, finalText, outcomes, correction) {
|
|
|
957
961
|
const lines = [
|
|
958
962
|
'This is hidden control work. Do not call tools, inspect files, or seek external evidence.',
|
|
959
963
|
'Decide only from the supplied player output and declared outcomes.',
|
|
964
|
+
CURRENT_CALL_ADJUDICATION_GUIDANCE,
|
|
960
965
|
'Reply with exactly one JSON object and no prose.',
|
|
961
966
|
'',
|
|
962
967
|
`The ${input.role} role just produced this output:`,
|
|
@@ -1706,6 +1706,11 @@ export function defaultExtractRequiredFields(description: string): string[] {
|
|
|
1706
1706
|
return fields;
|
|
1707
1707
|
}
|
|
1708
1708
|
|
|
1709
|
+
const CURRENT_CALL_ADJUDICATION_GUIDANCE =
|
|
1710
|
+
"Classify the invoked role's current call by the result it reports at call end, using the full output and declared outcome meanings. " +
|
|
1711
|
+
'An earlier interim question is not outstanding when later prose explicitly resolves or supersedes it for this call; a prerequisite only for a later workflow stage does not block an affirmatively completed current call. ' +
|
|
1712
|
+
'A genuinely unanswered question needed to finish the current call remains outstanding. A commit statement alone does not establish semantic completion; do not force contradictory or insufficient evidence into a completed outcome.';
|
|
1713
|
+
|
|
1709
1714
|
/** Default delegated-player adjudicator prompt. */
|
|
1710
1715
|
export function defaultBuildJudgePrompt(
|
|
1711
1716
|
input: PlaybookPlayerInput,
|
|
@@ -1717,6 +1722,7 @@ export function defaultBuildJudgePrompt(
|
|
|
1717
1722
|
'seek external evidence. Decide only from the supplied player output ' +
|
|
1718
1723
|
'and outcome descriptions. Reply with exactly one JSON object and no prose.',
|
|
1719
1724
|
);
|
|
1725
|
+
lines.push(CURRENT_CALL_ADJUDICATION_GUIDANCE);
|
|
1720
1726
|
lines.push('');
|
|
1721
1727
|
lines.push(`The ${input.role} role just produced this output:`);
|
|
1722
1728
|
lines.push('');
|
|
@@ -1822,6 +1828,7 @@ function buildGovernedJudgePrompt(
|
|
|
1822
1828
|
const lines = [
|
|
1823
1829
|
'This is hidden control work. Do not call tools, inspect files, or seek external evidence.',
|
|
1824
1830
|
'Decide only from the supplied player output and declared outcomes.',
|
|
1831
|
+
CURRENT_CALL_ADJUDICATION_GUIDANCE,
|
|
1825
1832
|
'Reply with exactly one JSON object and no prose.',
|
|
1826
1833
|
'',
|
|
1827
1834
|
`The ${input.role} role just produced this output:`,
|