@ai-agent-forge/plugin-workflow 0.86.4 → 0.86.5
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/dist/engine.d.ts +4 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +21 -12
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -6
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/validate.d.ts +11 -1
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +7 -1
- package/dist/validate.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -38,6 +38,8 @@ const WORKFLOW_EXECUTION_GUIDE = "After plan_set marks a stage's plan completed,
|
|
|
38
38
|
const WORKFLOW_CORRECTION_GUIDE = "On user corrections: run workflow_advance inspect first to confirm the current state, then route by what changed — amend the stage spec (active/awaiting_review stages, amendNote required), append a stage, skip, retreat, or cancel — and report the adjustment and its impact range back to the user.";
|
|
39
39
|
const WORKFLOW_REVIEW_GUIDE = "Stages declared advance: 'review' stop at awaiting_review. Before approve you must present the result and its evidence to the user and get explicit confirmation — never approve on your own (the engine does not authorize; the discipline lives here).";
|
|
40
40
|
const WORKFLOW_CONCURRENCY_GUIDE = "Do not send workflow_set in the same parallel batch as plan_set: amends and completion evaluation race (completed freezes first; if the amend loses, recover via retreat).";
|
|
41
|
+
const WORKFLOW_INCREMENTAL_DEMAND_GUIDE = "When a new batch of requirements arrives (incremental features on top of shipped work), default to creating a NEW workflow to carry it — reuse the same goalId and keep the completed workflow's history intact; never pull a completed workflow back into motion. Retreat or append a corrective stage only when the new requirements overturn already completed output.";
|
|
42
|
+
const WORKFLOW_EXECUTOR_GUIDE = "When delegating a stage to a subagent, pass that subagent's session/task id as the executor field of record-evidence — it is recorded on the stage (advisory) so /workflow log shows who drove it.";
|
|
41
43
|
const acceptanceSchema = Type.Object({
|
|
42
44
|
id: Type.String({ description: "Acceptance item id; evidence references this id" }),
|
|
43
45
|
statement: Type.String({ description: "Verifiable completion criterion for this item" }),
|
|
@@ -73,16 +75,24 @@ const stageSchema = Type.Object({
|
|
|
73
75
|
});
|
|
74
76
|
const workflowSetSchema = Type.Object({
|
|
75
77
|
id: Type.String({ description: "Stable id of the workflow to create or update" }),
|
|
76
|
-
title: Type.String({
|
|
78
|
+
title: Type.Optional(Type.String({
|
|
79
|
+
description: "Human-readable workflow title; required on create, omitting on update keeps the stored value",
|
|
80
|
+
})),
|
|
77
81
|
revision: Type.Integer({
|
|
78
82
|
description: "New revision counter; must be greater than the stored revision of an existing workflow",
|
|
79
83
|
minimum: 0,
|
|
80
84
|
}),
|
|
81
85
|
goalId: Type.Optional(Type.String({
|
|
82
|
-
description: "Soft reference to a goal id; the closure evidence summary is addressed to this goal",
|
|
86
|
+
description: "Soft reference to a goal id; the closure evidence summary is addressed to this goal. Omitting on update keeps the stored value",
|
|
87
|
+
})),
|
|
88
|
+
maxRetreats: Type.Optional(Type.Integer({
|
|
89
|
+
description: "Workflow lifetime retreat budget before failure, default 3. Omitting on update keeps the stored value",
|
|
90
|
+
minimum: 0,
|
|
91
|
+
})),
|
|
92
|
+
maxActiveStages: Type.Optional(Type.Integer({
|
|
93
|
+
description: "Parallel activation cap, default 4. Omitting on update keeps the stored value",
|
|
94
|
+
minimum: 1,
|
|
83
95
|
})),
|
|
84
|
-
maxRetreats: Type.Optional(Type.Integer({ description: "Workflow lifetime retreat budget before failure, default 3", minimum: 0 })),
|
|
85
|
-
maxActiveStages: Type.Optional(Type.Integer({ description: "Parallel activation cap, default 4", minimum: 1 })),
|
|
86
96
|
stages: Type.Array(stageSchema, {
|
|
87
97
|
description: "Full stage list (whole submit, not a patch); the engine aligns runtime by stage id",
|
|
88
98
|
}),
|
|
@@ -103,6 +113,9 @@ const workflowAdvanceSchema = Type.Object({
|
|
|
103
113
|
stageId: Type.Optional(Type.String({
|
|
104
114
|
description: "Stage id: the evidence/approve/reject/complete/skip target, or the retreat target stage to roll back to",
|
|
105
115
|
})),
|
|
116
|
+
executor: Type.Optional(Type.String({
|
|
117
|
+
description: "Advisory executor id (e.g. subagent session/task id) driving the stage; record-only, last-write-wins, never affects evaluation",
|
|
118
|
+
})),
|
|
106
119
|
evidence: Type.Optional(Type.Array(Type.Object({
|
|
107
120
|
acceptanceId: Type.Optional(Type.String({ description: "Acceptance item id; required in acceptance mode" })),
|
|
108
121
|
ref: Type.String({ description: "Evidence reference (tool output, file, artifact)" }),
|
|
@@ -135,6 +148,7 @@ function parseAdvanceInput(value) {
|
|
|
135
148
|
}
|
|
136
149
|
const stageId = value.stageId === undefined ? undefined : asText(value.stageId, "stageId");
|
|
137
150
|
const note = value.note === undefined ? undefined : asText(value.note, "note");
|
|
151
|
+
const executor = value.executor === undefined ? undefined : asText(value.executor, "executor");
|
|
138
152
|
let evidence;
|
|
139
153
|
if (value.evidence !== undefined) {
|
|
140
154
|
if (!Array.isArray(value.evidence))
|
|
@@ -152,6 +166,7 @@ function parseAdvanceInput(value) {
|
|
|
152
166
|
...(stageId !== undefined ? { stageId } : {}),
|
|
153
167
|
...(evidence !== undefined ? { evidence } : {}),
|
|
154
168
|
...(note !== undefined ? { note } : {}),
|
|
169
|
+
...(executor !== undefined ? { executor } : {}),
|
|
155
170
|
};
|
|
156
171
|
}
|
|
157
172
|
function loadState(api) {
|
|
@@ -166,12 +181,17 @@ function loadState(api) {
|
|
|
166
181
|
* Plan facts read from the current branch's LATEST `plan.state` snapshot (the
|
|
167
182
|
* same latest-snapshot semantics as the plan plugin's own loadState). The
|
|
168
183
|
* plan.changed payload is never trusted for state — only as a trigger.
|
|
184
|
+
*
|
|
185
|
+
* Uncached by design: identity-keyed caching collided across test hosts and
|
|
186
|
+
* hooking invalidation into appendEntry crosses the persistence boundary; the
|
|
187
|
+
* O(stages x entries) rescan is the price of snapshot-driven truth. Revisit
|
|
188
|
+
* only with a per-run cache channel if long-session profiling demands it.
|
|
169
189
|
*/
|
|
170
190
|
function loadPlansSnapshot(api) {
|
|
171
191
|
const entries = api.session?.getBranchEntries() ?? [];
|
|
172
192
|
for (let index = entries.length - 1; index >= 0; index -= 1) {
|
|
173
193
|
const entry = entries[index];
|
|
174
|
-
if (entry
|
|
194
|
+
if (entry?.customType !== planStateEntry)
|
|
175
195
|
continue;
|
|
176
196
|
const data = entry.data;
|
|
177
197
|
if (!data || typeof data !== "object" || Array.isArray(data))
|
|
@@ -348,8 +368,10 @@ export function createCapability(api) {
|
|
|
348
368
|
WORKFLOW_CORRECTION_GUIDE,
|
|
349
369
|
WORKFLOW_REVIEW_GUIDE,
|
|
350
370
|
WORKFLOW_CONCURRENCY_GUIDE,
|
|
371
|
+
WORKFLOW_INCREMENTAL_DEMAND_GUIDE,
|
|
372
|
+
WORKFLOW_EXECUTOR_GUIDE,
|
|
351
373
|
],
|
|
352
|
-
description: "Create or update a workflow: a stage dependency graph (DAG) with per-stage objectives, acceptance evidence, and soft goal/plan references",
|
|
374
|
+
description: "Create or update a workflow: a stage dependency graph (DAG) with per-stage objectives, acceptance evidence, and soft goal/plan references. On update, an omitted workflow-level optional field (title/goalId/maxRetreats/maxActiveStages) keeps its stored value; stages are always submitted in full",
|
|
353
375
|
parameters: workflowSetSchema,
|
|
354
376
|
execute: async (first, second) => {
|
|
355
377
|
const parsed = parseWorkflowSetInput(objectInput(first, second));
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Workflow orchestration capability plugin (M1 of\n * `docs/design/工作流编排插件设计.md`): a fourth self-contained state machine\n * orchestrating a stage dependency graph on top of the goal/plan/todo layers.\n *\n * Persistence protocol, structurally identical to the goal/plan/todo plugins:\n * append-only `workflow.state` full snapshots (the single rebuild source) plus\n * one `workflow.transition` audit entry per conversion, announced as\n * `workflow.changed` (version 1, correlationId \"workflow.state\", data = the\n * complete WorkflowState snapshot).\n *\n * This plugin is the repository's FIRST event subscriber (§7): `plan.changed`\n * is used as a trigger signal only — its in-memory data may be misaligned\n * with the current branch, so every reevaluation reads the plan facts from\n * the current branch entries. The handler is fully isolated (§5 总则 3): any\n * failure lands in diagnostics + a `handler.error` transition and never\n * rethrows at the publisher (an unisolated throw would pierce plan_set's tool\n * return). Soft references (goalId / planId / role) never fail a write (#10):\n * they surface as response warnings; a dangling planId additionally holds the\n * stage's activation until a reevaluation finds the plan.\n */\n\nimport type { CapabilityAPI, DisposableRegistration } from \"@agent-forge/plugin-sdk\";\nimport { Type } from \"typebox\";\nimport {\n\ttype AdvanceAction,\n\ttype AdvanceInput,\n\tapplyAdvance,\n\tapplyWorkflowSet,\n\ttype EngineDeps,\n\ttype EngineRun,\n\ttype EvidenceItem,\n\tinspectWorkflow,\n\ttype PlanFacts,\n\treevaluateAll,\n\ttype WorkflowClosure,\n\ttype WorkflowInspection,\n} from \"./engine.ts\";\nimport { renderLog, renderPanorama, renderWhy } from \"./render.ts\";\nimport {\n\ttype TransitionReasonCode,\n\tWORKFLOW_STATE_ENTRY,\n\tWORKFLOW_TRANSITION_ENTRY,\n\ttype WorkflowState,\n\ttype WorkflowTransitionEntry,\n\ttype WorkflowTransitionTrigger,\n} from \"./types.ts\";\nimport { asObject, asText, parseWorkflowSetInput, planWorkflowSpecUpdate, validateStageGraph } from \"./validate.ts\";\n\nexport type {\n\tAcceptanceCoverage,\n\tAdvanceAction,\n\tAdvanceInput,\n\tClosureEvidenceItem,\n\tEngineDeps,\n\tEngineRun,\n\tEvidenceItem,\n\tPlanFacts,\n\tStageInspection,\n\tWorkflowClosure,\n\tWorkflowInspection,\n} from \"./engine.ts\";\nexport { cascadeLimitFor, computeWaitingOn, reevaluateAll } from \"./engine.ts\";\nexport type {\n\tStageRuntime,\n\tStageSpec,\n\tTransitionReason,\n\tTransitionReasonCode,\n\tWorkflowRecord,\n\tWorkflowState,\n\tWorkflowTransitionEntry,\n\tWorkflowTransitionTrigger,\n} from \"./types.ts\";\nexport { WORKFLOW_STATE_ENTRY, WORKFLOW_TRANSITION_ENTRY } from \"./types.ts\";\n\n/** Session protocol key of the plan plugin's snapshot entry (plugins/plan). */\nconst planStateEntry = \"plan.state\";\n/** Session protocol key of the goal plugin's snapshot entry (plugins/goal). */\nconst goalStateEntry = \"goal.state\";\nconst DIAGNOSTICS_CAP = 50;\n\n/** §3.1 applicability, verbatim scope (when to use / not to use a workflow). */\nconst WORKFLOW_APPLICABILITY_GUIDE =\n\t\"Workflow applicability — use a workflow only when ALL of these hold: (1) the goal needs at least 3 stages that can be accepted independently (you can write each stage's objective/acceptance); (2) the stages have a real dependency structure (branching or joins), not a plain sequence; (3) independent branches can be pushed in parallel — parallelism is a core payoff, purely linear multi-stage work belongs to goal/plan/todo; (4) the task spans multiple turns/days and is valuable enough to justify process overhead (definition, evidence recording, stage gates). Counterexamples that keep goal/plan/todo or direct execution: single-step tasks; two- or three-step linear tasks; exploratory work with no presettable dependency graph; one-shot questions. A workflow does not exclude the three layers — each stage still uses plan/todo for its execution checklist. Never escalate a small task to a workflow by default.\";\n\nconst WORKFLOW_AUTHORING_GUIDE =\n\t\"Define each stage by a verifiable end state, not by a work list or a role: objective.statement says what must be achieved; acceptance items list the evidence that proves it, referenced from real tool output. Stop splitting at the first verifiable boundary — finer handoffs lose more to interface drift than they gain in drift protection.\";\n\nconst WORKFLOW_EXECUTION_GUIDE =\n\t\"After plan_set marks a stage's plan completed, run workflow_advance inspect to see unlocked stages and acceptance coverage. Record evidence (workflow_advance record-evidence) before completion is evaluated; lower-bound stages (no acceptance declared) need no record-evidence. When multiple stages are active, delegate one subagent per stage following stage.role and push them in parallel.\";\n\nconst WORKFLOW_CORRECTION_GUIDE =\n\t\"On user corrections: run workflow_advance inspect first to confirm the current state, then route by what changed — amend the stage spec (active/awaiting_review stages, amendNote required), append a stage, skip, retreat, or cancel — and report the adjustment and its impact range back to the user.\";\n\nconst WORKFLOW_REVIEW_GUIDE =\n\t\"Stages declared advance: 'review' stop at awaiting_review. Before approve you must present the result and its evidence to the user and get explicit confirmation — never approve on your own (the engine does not authorize; the discipline lives here).\";\n\nconst WORKFLOW_CONCURRENCY_GUIDE =\n\t\"Do not send workflow_set in the same parallel batch as plan_set: amends and completion evaluation race (completed freezes first; if the amend loses, recover via retreat).\";\n\nconst acceptanceSchema = Type.Object({\n\tid: Type.String({ description: \"Acceptance item id; evidence references this id\" }),\n\tstatement: Type.String({ description: \"Verifiable completion criterion for this item\" }),\n});\n\nconst stageSchema = Type.Object({\n\tid: Type.String({ description: \"Stable stage id, unique within the workflow\" }),\n\ttitle: Type.String({ description: \"Human-readable stage title\" }),\n\tobjective: Type.Object({\n\t\tstatement: Type.String({\n\t\t\tdescription: \"Verifiable end state this stage must reach (required, non-empty)\",\n\t\t}),\n\t\tacceptance: Type.Optional(\n\t\t\tType.Array(acceptanceSchema, {\n\t\t\t\tdescription:\n\t\t\t\t\t\"Completion criteria items; when empty (or omitted) the lower bound is the referenced plan's completion evidence\",\n\t\t\t}),\n\t\t),\n\t}),\n\tdependsOn: Type.Optional(\n\t\tType.Array(Type.String(), { description: \"Hard prerequisite stage ids; empty array = root stage\" }),\n\t),\n\tplanId: Type.Optional(Type.String({ description: \"Soft reference to a plan id; missing = pure checkpoint stage\" })),\n\tkind: Type.Optional(\n\t\tType.Union([Type.Literal(\"read\"), Type.Literal(\"write\")], {\n\t\t\tdescription: 'Stage kind; write stages are scope-checked, default \"write\"',\n\t\t}),\n\t),\n\tscope: Type.Optional(\n\t\tType.Array(Type.String(), {\n\t\t\tdescription: \"Write scope tags (modules/dirs); missing = global (intersects every other write stage)\",\n\t\t}),\n\t),\n\trole: Type.Optional(\n\t\tType.String({ description: \"Delegation advice: role id for the subagent recommended to drive this stage\" }),\n\t),\n\tadvance: Type.Optional(\n\t\tType.Union([Type.Literal(\"auto\"), Type.Literal(\"review\")], {\n\t\t\tdescription:\n\t\t\t\t'\"auto\" completes on evaluation, \"review\" stops at awaiting_review (planId stages only), default \"auto\"',\n\t\t}),\n\t),\n\tretryLimit: Type.Optional(\n\t\tType.Integer({ description: \"In-place retry limit before onFail/workflow failure, default 2\", minimum: 0 }),\n\t),\n\tonFail: Type.Optional(\n\t\tType.String({ description: \"Explicit cross-stage retreat target (a topologically earlier stage id)\" }),\n\t),\n\tamendNote: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Correction reason; required when an active/awaiting_review stage's spec changes\",\n\t\t}),\n\t),\n});\n\nconst workflowSetSchema = Type.Object({\n\tid: Type.String({ description: \"Stable id of the workflow to create or update\" }),\n\ttitle: Type.String({ description: \"Human-readable workflow title\" }),\n\trevision: Type.Integer({\n\t\tdescription: \"New revision counter; must be greater than the stored revision of an existing workflow\",\n\t\tminimum: 0,\n\t}),\n\tgoalId: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Soft reference to a goal id; the closure evidence summary is addressed to this goal\",\n\t\t}),\n\t),\n\tmaxRetreats: Type.Optional(\n\t\tType.Integer({ description: \"Workflow lifetime retreat budget before failure, default 3\", minimum: 0 }),\n\t),\n\tmaxActiveStages: Type.Optional(Type.Integer({ description: \"Parallel activation cap, default 4\", minimum: 1 })),\n\tstages: Type.Array(stageSchema, {\n\t\tdescription: \"Full stage list (whole submit, not a patch); the engine aligns runtime by stage id\",\n\t}),\n});\n\nconst workflowAdvanceSchema = Type.Object({\n\tworkflowId: Type.String({ description: \"Target workflow id\" }),\n\taction: Type.Union(\n\t\t[\n\t\t\tType.Literal(\"start\"),\n\t\t\tType.Literal(\"record-evidence\"),\n\t\t\tType.Literal(\"inspect\"),\n\t\t\tType.Literal(\"approve\"),\n\t\t\tType.Literal(\"reject\"),\n\t\t\tType.Literal(\"retreat\"),\n\t\t\tType.Literal(\"complete\"),\n\t\t\tType.Literal(\"skip\"),\n\t\t\tType.Literal(\"cancel\"),\n\t\t],\n\t\t{ description: \"Explicit action to perform\" },\n\t),\n\tstageId: Type.Optional(\n\t\tType.String({\n\t\t\tdescription:\n\t\t\t\t\"Stage id: the evidence/approve/reject/complete/skip target, or the retreat target stage to roll back to\",\n\t\t}),\n\t),\n\tevidence: Type.Optional(\n\t\tType.Array(\n\t\t\tType.Object({\n\t\t\t\tacceptanceId: Type.Optional(\n\t\t\t\t\tType.String({ description: \"Acceptance item id; required in acceptance mode\" }),\n\t\t\t\t),\n\t\t\t\tref: Type.String({ description: \"Evidence reference (tool output, file, artifact)\" }),\n\t\t\t}),\n\t\t\t{ description: \"Evidence items for record-evidence/approve/complete\" },\n\t\t),\n\t),\n\tnote: Type.Optional(\n\t\tType.String({ description: \"Optional note recorded in the transition detail (reject/retreat/skip/cancel)\" }),\n\t),\n});\n\nconst ADVANCE_ACTIONS: readonly string[] = [\n\t\"start\",\n\t\"record-evidence\",\n\t\"inspect\",\n\t\"approve\",\n\t\"reject\",\n\t\"retreat\",\n\t\"complete\",\n\t\"skip\",\n\t\"cancel\",\n];\n\nfunction objectInput(first: unknown, second: unknown): Record<string, unknown> {\n\tconst value = second === undefined ? first : second;\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new Error(\"Workflow input must be an object\");\n\t}\n\treturn value as Record<string, unknown>;\n}\n\nfunction parseAdvanceInput(value: Record<string, unknown>): AdvanceInput {\n\tconst workflowId = asText(value.workflowId, \"workflowId\");\n\tconst action = value.action;\n\tif (typeof action !== \"string\" || !ADVANCE_ACTIONS.includes(action)) {\n\t\tthrow new Error(`action must be one of ${ADVANCE_ACTIONS.join(\", \")}`);\n\t}\n\tconst stageId = value.stageId === undefined ? undefined : asText(value.stageId, \"stageId\");\n\tconst note = value.note === undefined ? undefined : asText(value.note, \"note\");\n\tlet evidence: EvidenceItem[] | undefined;\n\tif (value.evidence !== undefined) {\n\t\tif (!Array.isArray(value.evidence)) throw new Error(\"evidence must be an array of {acceptanceId?, ref}\");\n\t\tevidence = value.evidence.map((item) => {\n\t\t\tconst entry = asObject(item, \"evidence item\");\n\t\t\tconst ref = asText(entry.ref, \"evidence item ref\");\n\t\t\tconst acceptanceId =\n\t\t\t\tentry.acceptanceId === undefined ? undefined : asText(entry.acceptanceId, \"evidence item acceptanceId\");\n\t\t\treturn acceptanceId === undefined ? { ref } : { acceptanceId, ref };\n\t\t});\n\t}\n\treturn {\n\t\tworkflowId,\n\t\taction: action as AdvanceAction,\n\t\t...(stageId !== undefined ? { stageId } : {}),\n\t\t...(evidence !== undefined ? { evidence } : {}),\n\t\t...(note !== undefined ? { note } : {}),\n\t};\n}\n\nfunction loadState(api: CapabilityAPI): WorkflowState {\n\tconst entries = api.session?.getBranchEntries() ?? [];\n\tconst entry = [...entries].reverse().find((item) => item.customType === WORKFLOW_STATE_ENTRY);\n\tif (!entry?.data || typeof entry.data !== \"object\") return { workflows: [] };\n\tconst data = entry.data as Partial<WorkflowState>;\n\treturn { workflows: Array.isArray(data.workflows) ? [...data.workflows] : [] };\n}\n\n/**\n * Plan facts read from the current branch's LATEST `plan.state` snapshot (the\n * same latest-snapshot semantics as the plan plugin's own loadState). The\n * plan.changed payload is never trusted for state — only as a trigger.\n */\nfunction loadPlansSnapshot(api: CapabilityAPI): Map<string, PlanFacts> {\n\tconst entries = api.session?.getBranchEntries() ?? [];\n\tfor (let index = entries.length - 1; index >= 0; index -= 1) {\n\t\tconst entry = entries[index];\n\t\tif (entry.customType !== planStateEntry) continue;\n\t\tconst data = entry.data;\n\t\tif (!data || typeof data !== \"object\" || Array.isArray(data)) return new Map();\n\t\tconst plans = (data as { plans?: unknown }).plans;\n\t\tif (!Array.isArray(plans)) return new Map();\n\t\tconst facts = new Map<string, PlanFacts>();\n\t\tfor (const plan of plans) {\n\t\t\tif (!plan || typeof plan !== \"object\") continue;\n\t\t\tconst record = plan as { id?: unknown; status?: unknown; evidence?: unknown };\n\t\t\tif (typeof record.id !== \"string\") continue;\n\t\t\tconst status =\n\t\t\t\trecord.status === \"draft\" ||\n\t\t\t\trecord.status === \"active\" ||\n\t\t\t\trecord.status === \"completed\" ||\n\t\t\t\trecord.status === \"cancelled\"\n\t\t\t\t\t? record.status\n\t\t\t\t\t: \"draft\";\n\t\t\tconst evidence = Array.isArray(record.evidence)\n\t\t\t\t? record.evidence.filter((item): item is string => typeof item === \"string\")\n\t\t\t\t: [];\n\t\t\tfacts.set(record.id, { id: record.id, status, evidence });\n\t\t}\n\t\treturn facts;\n\t}\n\treturn new Map();\n}\n\n/** Whether the latest `<entryType>` snapshot on the branch knows `id` in its `idsField` array (advisory, #10). */\nfunction idKnownToSession(api: CapabilityAPI, entryType: string, idsField: string, id: string): boolean {\n\tconst entries = api.session?.getBranchEntries() ?? [];\n\tfor (let index = entries.length - 1; index >= 0; index -= 1) {\n\t\tconst entry = entries[index];\n\t\tif (entry.customType !== entryType) continue;\n\t\tconst data = entry.data;\n\t\tif (!data || typeof data !== \"object\" || Array.isArray(data)) return false;\n\t\tconst records = (data as Record<string, unknown>)[idsField];\n\t\tif (!Array.isArray(records)) return false;\n\t\treturn records.some(\n\t\t\t(record) => record !== null && typeof record === \"object\" && (record as { id?: unknown }).id === id,\n\t\t);\n\t}\n\treturn false;\n}\n\n/**\n * Seeds the held-dedup view (§5 总则 5) from the branch audit stream: the\n * last transition per stage, whatever its code — a repeat held emission is\n * dropped only when it matches that last code and detail.\n */\nfunction buildLastStageTransition(api: CapabilityAPI): Map<string, { code: TransitionReasonCode; detail?: string }> {\n\tconst map = new Map<string, { code: TransitionReasonCode; detail?: string }>();\n\tfor (const entry of api.session?.getBranchEntries() ?? []) {\n\t\tif (entry.customType !== WORKFLOW_TRANSITION_ENTRY) continue;\n\t\tconst data = entry.data;\n\t\tif (!data || typeof data !== \"object\" || Array.isArray(data)) continue;\n\t\tconst record = data as Partial<WorkflowTransitionEntry>;\n\t\tif (typeof record.workflowId !== \"string\" || typeof record.stageId !== \"string\") continue;\n\t\tconst reason = record.reason as { code?: unknown; detail?: unknown } | undefined;\n\t\tif (!reason || typeof reason !== \"object\" || typeof reason.code !== \"string\") continue;\n\t\tmap.set(`${record.workflowId}::${record.stageId}`, {\n\t\t\tcode: reason.code as TransitionReasonCode,\n\t\t\tdetail: typeof reason.detail === \"string\" ? reason.detail : undefined,\n\t\t});\n\t}\n\treturn map;\n}\n\n/** Soft-reference warnings for the tool response only (never the persisted state, #10). */\nfunction collectSoftReferenceWarnings(\n\tapi: CapabilityAPI,\n\tgoalId: string | undefined,\n\tplanIds: { stageId: string; planId: string }[],\n\troles: { stageId: string; role: string }[],\n): string[] {\n\tconst warnings: string[] = [];\n\tif (goalId !== undefined && !idKnownToSession(api, goalStateEntry, \"goals\", goalId)) {\n\t\twarnings.push(\n\t\t\t`goalId \"${goalId}\" does not match any goal in this session's goal state; the workflow keeps the soft reference`,\n\t\t);\n\t}\n\tfor (const item of planIds) {\n\t\tif (!idKnownToSession(api, planStateEntry, \"plans\", item.planId)) {\n\t\t\twarnings.push(\n\t\t\t\t`stage ${item.stageId}: planId \"${item.planId}\" does not match any plan in this session's plan state; ` +\n\t\t\t\t\t\"the stage stays held until a reevaluation finds the plan\",\n\t\t\t);\n\t\t}\n\t}\n\tfor (const item of roles) {\n\t\t// The host's suite role associations are the only verifiable role face;\n\t\t// hosts without the listing leave the advice unverified (no warning).\n\t\tconst associated = api.host?.roleAssociations;\n\t\tif (associated !== undefined && !associated.includes(item.role)) {\n\t\t\twarnings.push(\n\t\t\t\t`stage ${item.stageId}: role \"${item.role}\" is not associated with the active suite; delegation advice treated as unspecified`,\n\t\t\t);\n\t\t}\n\t}\n\treturn warnings;\n}\n\ninterface WorkflowToolResponse extends WorkflowState {\n\tclosures?: WorkflowClosure[];\n\tinspections?: WorkflowInspection[];\n\twarning?: string;\n}\n\nexport function createCapability(\n\tapi: CapabilityAPI,\n): Promise<readonly DisposableRegistration[]> | readonly DisposableRegistration[] {\n\tlet state = loadState(api);\n\tconst deps: EngineDeps = {\n\t\tgetPlan: (planId) => loadPlansSnapshot(api).get(planId),\n\t\tlastStageTransition: buildLastStageTransition(api),\n\t};\n\n\t// Persistence boundary (§4): audit entries first, then the full snapshot —\n\t// a crash mid-batch replays from the older snapshot while the audit stays\n\t// intact. appendEntry failures propagate unchanged (§5 总则 5: no swallow);\n\t// publish rejections surface to the tool caller (or are contained on the\n\t// load/subscriber paths below).\n\tconst persistRun = (run: EngineRun): void => {\n\t\tfor (const transition of run.transitions) {\n\t\t\tapi.session?.appendEntry(WORKFLOW_TRANSITION_ENTRY, transition);\n\t\t}\n\t\tapi.session?.appendEntry(WORKFLOW_STATE_ENTRY, run.state);\n\t};\n\tconst announce = (run: EngineRun): Promise<unknown> =>\n\t\tapi.publish({ type: \"workflow.changed\", version: 1, correlationId: WORKFLOW_STATE_ENTRY, data: run.state });\n\n\t/**\n\t * §5 总则 3 containment: land the failure in diagnostics + a handler.error\n\t * transition (detail = original error text) and never rethrow. Best-effort\n\t * — an already-failing boundary must not turn isolation into a second crash.\n\t */\n\tconst quarantineEngineError = (error: unknown, trigger: WorkflowTransitionTrigger): void => {\n\t\ttry {\n\t\t\tif (state.workflows.length === 0) return;\n\t\t\tconst original = error instanceof Error ? error.message : String(error);\n\t\t\tconst text = `${trigger} handler failed: ${original}`;\n\t\t\tconst workflows = state.workflows.map((workflow) => structuredClone(workflow));\n\t\t\tconst transitions: WorkflowTransitionEntry[] = [];\n\t\t\tfor (const workflow of workflows) {\n\t\t\t\tif (workflow.diagnostics.length >= DIAGNOSTICS_CAP) workflow.diagnostics.shift();\n\t\t\t\tworkflow.diagnostics.push(text);\n\t\t\t\tworkflow.revision += 1;\n\t\t\t\ttransitions.push({\n\t\t\t\t\tworkflowId: workflow.id,\n\t\t\t\t\tfrom: workflow.status,\n\t\t\t\t\tto: workflow.status,\n\t\t\t\t\ttrigger,\n\t\t\t\t\treason: { code: \"handler.error\", message: text, detail: original },\n\t\t\t\t\trevision: workflow.revision,\n\t\t\t\t});\n\t\t\t}\n\t\t\tstate = { workflows };\n\t\t\tfor (const transition of transitions) {\n\t\t\t\tapi.session?.appendEntry(WORKFLOW_TRANSITION_ENTRY, transition);\n\t\t\t}\n\t\t\tapi.session?.appendEntry(WORKFLOW_STATE_ENTRY, state);\n\t\t\tvoid api\n\t\t\t\t.publish({ type: \"workflow.changed\", version: 1, correlationId: WORKFLOW_STATE_ENTRY, data: state })\n\t\t\t\t.catch(() => undefined);\n\t\t} catch {\n\t\t\t// Containment is best-effort by design.\n\t\t}\n\t};\n\n\t// §5 rule 8 recovery: state replayed from workflow.state, then the\n\t// load-time reevaluation (总则 1 fallback moment #1). Runs synchronously at\n\t// factory time; failures are contained, never blocking plugin load.\n\ttry {\n\t\tconst run = reevaluateAll(state, deps, \"load-reeval\");\n\t\tif (run.transitions.length > 0) {\n\t\t\tstate = run.state;\n\t\t\tpersistRun(run);\n\t\t\tvoid announce(run).catch(() => undefined);\n\t\t}\n\t} catch (error) {\n\t\tquarantineEngineError(error, \"load-reeval\");\n\t}\n\n\tconst setTool = api.registerTool({\n\t\tname: \"workflow_set\",\n\t\tlabel: \"Set workflow\",\n\t\tpromptGuidelines: [\n\t\t\tWORKFLOW_APPLICABILITY_GUIDE,\n\t\t\tWORKFLOW_AUTHORING_GUIDE,\n\t\t\tWORKFLOW_EXECUTION_GUIDE,\n\t\t\tWORKFLOW_CORRECTION_GUIDE,\n\t\t\tWORKFLOW_REVIEW_GUIDE,\n\t\t\tWORKFLOW_CONCURRENCY_GUIDE,\n\t\t],\n\t\tdescription:\n\t\t\t\"Create or update a workflow: a stage dependency graph (DAG) with per-stage objectives, acceptance evidence, and soft goal/plan references\",\n\t\tparameters: workflowSetSchema,\n\t\texecute: async (first: unknown, second?: unknown) => {\n\t\t\tconst parsed = parseWorkflowSetInput(objectInput(first, second));\n\t\t\tvalidateStageGraph(parsed.stages);\n\t\t\tconst current = state.workflows.find((workflow) => workflow.id === parsed.id);\n\t\t\tif (current !== undefined && parsed.revision <= current.revision) {\n\t\t\t\tthrow new Error(`stale workflow revision: ${parsed.id}`);\n\t\t\t}\n\t\t\tif (\n\t\t\t\tcurrent !== undefined &&\n\t\t\t\t(current.status === \"completed\" || current.status === \"failed\" || current.status === \"cancelled\")\n\t\t\t) {\n\t\t\t\tthrow new Error(`workflow is terminal and cannot be updated: ${parsed.id}`);\n\t\t\t}\n\t\t\tconst diff = planWorkflowSpecUpdate(current, parsed);\n\t\t\tconst run = applyWorkflowSet(state, parsed, diff, deps);\n\t\t\tstate = run.state;\n\t\t\tif (run.transitions.length > 0 || diff.created) persistRun(run);\n\t\t\tif (run.transitions.length > 0 || diff.created) await announce(run);\n\t\t\tconst response: WorkflowToolResponse = { ...state };\n\t\t\tif (run.closures.length > 0) response.closures = run.closures;\n\t\t\tconst warnings = collectSoftReferenceWarnings(\n\t\t\t\tapi,\n\t\t\t\tparsed.goalId,\n\t\t\t\tparsed.stages.flatMap((stage) =>\n\t\t\t\t\tstage.planId !== undefined ? [{ stageId: stage.id, planId: stage.planId }] : [],\n\t\t\t\t),\n\t\t\t\tparsed.stages.flatMap((stage) =>\n\t\t\t\t\tstage.role !== undefined ? [{ stageId: stage.id, role: stage.role }] : [],\n\t\t\t\t),\n\t\t\t);\n\t\t\tif (warnings.length > 0) response.warning = warnings.join(\"; \");\n\t\t\treturn response;\n\t\t},\n\t});\n\n\tconst advanceTool = api.registerTool({\n\t\tname: \"workflow_advance\",\n\t\tlabel: \"Advance workflow\",\n\t\tdescription:\n\t\t\t\"Drive a workflow: start it, record acceptance evidence, inspect waiting conditions and coverage, approve/reject reviews, retreat, complete checkpoints, skip stages, or cancel\",\n\t\tparameters: workflowAdvanceSchema,\n\t\texecute: async (first: unknown, second?: unknown) => {\n\t\t\tconst parsed = parseAdvanceInput(objectInput(first, second));\n\t\t\t// Illegal conversions throw structured errors (§5 rule 6) surfaced\n\t\t\t// as tool errors unchanged; legal ones return the full snapshot\n\t\t\t// (the goal_set full-state response pattern).\n\t\t\tconst run = applyAdvance(state, parsed, deps);\n\t\t\tstate = run.state;\n\t\t\tif (run.transitions.length > 0) {\n\t\t\t\tpersistRun(run);\n\t\t\t\tawait announce(run);\n\t\t\t}\n\t\t\tconst response: WorkflowToolResponse = { ...state };\n\t\t\tif (parsed.action === \"inspect\") {\n\t\t\t\t// §5 rule 6 single-workflow semantics: applyAdvance has already\n\t\t\t\t// rejected unknown ids, so the target always resolves here.\n\t\t\t\tconst target = state.workflows.find((workflow) => workflow.id === parsed.workflowId);\n\t\t\t\tif (target !== undefined) response.inspections = [inspectWorkflow(target, deps)];\n\t\t\t}\n\t\t\tif (run.closures.length > 0) response.closures = run.closures;\n\t\t\treturn response;\n\t\t},\n\t});\n\n\tconst workflowCommand = api.registerCommand({\n\t\tname: \"workflow\",\n\t\tdescription: \"Workflow overview: dependency tree and status (default), why it is stopped, or the transition log\",\n\t\targumentHint: \"[view | why | log [N]]\",\n\t\texecute: async (args: string) => {\n\t\t\ttry {\n\t\t\t\tconst trimmed = args.trim();\n\t\t\t\tif (trimmed === \"\" || trimmed === \"view\") {\n\t\t\t\t\treturn { status: \"success\" as const, message: renderPanorama(state, deps) };\n\t\t\t\t}\n\t\t\t\tif (trimmed === \"why\") {\n\t\t\t\t\treturn { status: \"success\" as const, message: renderWhy(state, deps) };\n\t\t\t\t}\n\t\t\t\tconst logMatch = /^log(?:\\s+(\\d+))?$/.exec(trimmed);\n\t\t\t\tif (logMatch !== null) {\n\t\t\t\t\tconst limit = logMatch[1] === undefined ? 20 : Math.max(1, Number.parseInt(logMatch[1], 10));\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: \"success\" as const,\n\t\t\t\t\t\tmessage: renderLog(api.session?.getBranchEntries() ?? [], limit),\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn { status: \"error\" as const, message: \"Usage: /workflow [view | why | log [N]]\" };\n\t\t\t} catch (error) {\n\t\t\t\t// A slash command must not crash the host (memory /promote precedent).\n\t\t\t\treturn { status: \"error\" as const, message: error instanceof Error ? error.message : String(error) };\n\t\t\t}\n\t\t},\n\t});\n\n\t// The repository's first event subscription (§7). The payload is ignored:\n\t// reevaluation always reads the current branch entries (§5 总则 1).\n\tconst planChanged = api.subscribe(\"plan.changed\", async () => {\n\t\ttry {\n\t\t\tconst run = reevaluateAll(state, deps, \"plan.changed\");\n\t\t\tif (run.transitions.length === 0) return;\n\t\t\tstate = run.state;\n\t\t\tpersistRun(run);\n\t\t\tawait announce(run);\n\t\t} catch (error) {\n\t\t\tquarantineEngineError(error, \"plan.changed\");\n\t\t}\n\t});\n\n\treturn [setTool, advanceTool, workflowCommand, planChanged];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Workflow orchestration capability plugin (M1 of\n * `docs/design/工作流编排插件设计.md`): a fourth self-contained state machine\n * orchestrating a stage dependency graph on top of the goal/plan/todo layers.\n *\n * Persistence protocol, structurally identical to the goal/plan/todo plugins:\n * append-only `workflow.state` full snapshots (the single rebuild source) plus\n * one `workflow.transition` audit entry per conversion, announced as\n * `workflow.changed` (version 1, correlationId \"workflow.state\", data = the\n * complete WorkflowState snapshot).\n *\n * This plugin is the repository's FIRST event subscriber (§7): `plan.changed`\n * is used as a trigger signal only — its in-memory data may be misaligned\n * with the current branch, so every reevaluation reads the plan facts from\n * the current branch entries. The handler is fully isolated (§5 总则 3): any\n * failure lands in diagnostics + a `handler.error` transition and never\n * rethrows at the publisher (an unisolated throw would pierce plan_set's tool\n * return). Soft references (goalId / planId / role) never fail a write (#10):\n * they surface as response warnings; a dangling planId additionally holds the\n * stage's activation until a reevaluation finds the plan.\n */\n\nimport type { CapabilityAPI, DisposableRegistration } from \"@agent-forge/plugin-sdk\";\nimport { Type } from \"typebox\";\nimport {\n\ttype AdvanceAction,\n\ttype AdvanceInput,\n\tapplyAdvance,\n\tapplyWorkflowSet,\n\ttype EngineDeps,\n\ttype EngineRun,\n\ttype EvidenceItem,\n\tinspectWorkflow,\n\ttype PlanFacts,\n\treevaluateAll,\n\ttype WorkflowClosure,\n\ttype WorkflowInspection,\n} from \"./engine.ts\";\nimport { renderLog, renderPanorama, renderWhy } from \"./render.ts\";\nimport {\n\ttype TransitionReasonCode,\n\tWORKFLOW_STATE_ENTRY,\n\tWORKFLOW_TRANSITION_ENTRY,\n\ttype WorkflowState,\n\ttype WorkflowTransitionEntry,\n\ttype WorkflowTransitionTrigger,\n} from \"./types.ts\";\nimport { asObject, asText, parseWorkflowSetInput, planWorkflowSpecUpdate, validateStageGraph } from \"./validate.ts\";\n\nexport type {\n\tAcceptanceCoverage,\n\tAdvanceAction,\n\tAdvanceInput,\n\tClosureEvidenceItem,\n\tEngineDeps,\n\tEngineRun,\n\tEvidenceItem,\n\tPlanFacts,\n\tStageInspection,\n\tWorkflowClosure,\n\tWorkflowInspection,\n} from \"./engine.ts\";\nexport { cascadeLimitFor, computeWaitingOn, reevaluateAll } from \"./engine.ts\";\nexport type {\n\tStageRuntime,\n\tStageSpec,\n\tTransitionReason,\n\tTransitionReasonCode,\n\tWorkflowRecord,\n\tWorkflowState,\n\tWorkflowTransitionEntry,\n\tWorkflowTransitionTrigger,\n} from \"./types.ts\";\nexport { WORKFLOW_STATE_ENTRY, WORKFLOW_TRANSITION_ENTRY } from \"./types.ts\";\n\n/** Session protocol key of the plan plugin's snapshot entry (plugins/plan). */\nconst planStateEntry = \"plan.state\";\n/** Session protocol key of the goal plugin's snapshot entry (plugins/goal). */\nconst goalStateEntry = \"goal.state\";\nconst DIAGNOSTICS_CAP = 50;\n\n/** §3.1 applicability, verbatim scope (when to use / not to use a workflow). */\nconst WORKFLOW_APPLICABILITY_GUIDE =\n\t\"Workflow applicability — use a workflow only when ALL of these hold: (1) the goal needs at least 3 stages that can be accepted independently (you can write each stage's objective/acceptance); (2) the stages have a real dependency structure (branching or joins), not a plain sequence; (3) independent branches can be pushed in parallel — parallelism is a core payoff, purely linear multi-stage work belongs to goal/plan/todo; (4) the task spans multiple turns/days and is valuable enough to justify process overhead (definition, evidence recording, stage gates). Counterexamples that keep goal/plan/todo or direct execution: single-step tasks; two- or three-step linear tasks; exploratory work with no presettable dependency graph; one-shot questions. A workflow does not exclude the three layers — each stage still uses plan/todo for its execution checklist. Never escalate a small task to a workflow by default.\";\n\nconst WORKFLOW_AUTHORING_GUIDE =\n\t\"Define each stage by a verifiable end state, not by a work list or a role: objective.statement says what must be achieved; acceptance items list the evidence that proves it, referenced from real tool output. Stop splitting at the first verifiable boundary — finer handoffs lose more to interface drift than they gain in drift protection.\";\n\nconst WORKFLOW_EXECUTION_GUIDE =\n\t\"After plan_set marks a stage's plan completed, run workflow_advance inspect to see unlocked stages and acceptance coverage. Record evidence (workflow_advance record-evidence) before completion is evaluated; lower-bound stages (no acceptance declared) need no record-evidence. When multiple stages are active, delegate one subagent per stage following stage.role and push them in parallel.\";\n\nconst WORKFLOW_CORRECTION_GUIDE =\n\t\"On user corrections: run workflow_advance inspect first to confirm the current state, then route by what changed — amend the stage spec (active/awaiting_review stages, amendNote required), append a stage, skip, retreat, or cancel — and report the adjustment and its impact range back to the user.\";\n\nconst WORKFLOW_REVIEW_GUIDE =\n\t\"Stages declared advance: 'review' stop at awaiting_review. Before approve you must present the result and its evidence to the user and get explicit confirmation — never approve on your own (the engine does not authorize; the discipline lives here).\";\n\nconst WORKFLOW_CONCURRENCY_GUIDE =\n\t\"Do not send workflow_set in the same parallel batch as plan_set: amends and completion evaluation race (completed freezes first; if the amend loses, recover via retreat).\";\n\nconst WORKFLOW_INCREMENTAL_DEMAND_GUIDE =\n\t\"When a new batch of requirements arrives (incremental features on top of shipped work), default to creating a NEW workflow to carry it — reuse the same goalId and keep the completed workflow's history intact; never pull a completed workflow back into motion. Retreat or append a corrective stage only when the new requirements overturn already completed output.\";\n\nconst WORKFLOW_EXECUTOR_GUIDE =\n\t\"When delegating a stage to a subagent, pass that subagent's session/task id as the executor field of record-evidence — it is recorded on the stage (advisory) so /workflow log shows who drove it.\";\n\nconst acceptanceSchema = Type.Object({\n\tid: Type.String({ description: \"Acceptance item id; evidence references this id\" }),\n\tstatement: Type.String({ description: \"Verifiable completion criterion for this item\" }),\n});\n\nconst stageSchema = Type.Object({\n\tid: Type.String({ description: \"Stable stage id, unique within the workflow\" }),\n\ttitle: Type.String({ description: \"Human-readable stage title\" }),\n\tobjective: Type.Object({\n\t\tstatement: Type.String({\n\t\t\tdescription: \"Verifiable end state this stage must reach (required, non-empty)\",\n\t\t}),\n\t\tacceptance: Type.Optional(\n\t\t\tType.Array(acceptanceSchema, {\n\t\t\t\tdescription:\n\t\t\t\t\t\"Completion criteria items; when empty (or omitted) the lower bound is the referenced plan's completion evidence\",\n\t\t\t}),\n\t\t),\n\t}),\n\tdependsOn: Type.Optional(\n\t\tType.Array(Type.String(), { description: \"Hard prerequisite stage ids; empty array = root stage\" }),\n\t),\n\tplanId: Type.Optional(Type.String({ description: \"Soft reference to a plan id; missing = pure checkpoint stage\" })),\n\tkind: Type.Optional(\n\t\tType.Union([Type.Literal(\"read\"), Type.Literal(\"write\")], {\n\t\t\tdescription: 'Stage kind; write stages are scope-checked, default \"write\"',\n\t\t}),\n\t),\n\tscope: Type.Optional(\n\t\tType.Array(Type.String(), {\n\t\t\tdescription: \"Write scope tags (modules/dirs); missing = global (intersects every other write stage)\",\n\t\t}),\n\t),\n\trole: Type.Optional(\n\t\tType.String({ description: \"Delegation advice: role id for the subagent recommended to drive this stage\" }),\n\t),\n\tadvance: Type.Optional(\n\t\tType.Union([Type.Literal(\"auto\"), Type.Literal(\"review\")], {\n\t\t\tdescription:\n\t\t\t\t'\"auto\" completes on evaluation, \"review\" stops at awaiting_review (planId stages only), default \"auto\"',\n\t\t}),\n\t),\n\tretryLimit: Type.Optional(\n\t\tType.Integer({ description: \"In-place retry limit before onFail/workflow failure, default 2\", minimum: 0 }),\n\t),\n\tonFail: Type.Optional(\n\t\tType.String({ description: \"Explicit cross-stage retreat target (a topologically earlier stage id)\" }),\n\t),\n\tamendNote: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Correction reason; required when an active/awaiting_review stage's spec changes\",\n\t\t}),\n\t),\n});\n\nconst workflowSetSchema = Type.Object({\n\tid: Type.String({ description: \"Stable id of the workflow to create or update\" }),\n\ttitle: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Human-readable workflow title; required on create, omitting on update keeps the stored value\",\n\t\t}),\n\t),\n\trevision: Type.Integer({\n\t\tdescription: \"New revision counter; must be greater than the stored revision of an existing workflow\",\n\t\tminimum: 0,\n\t}),\n\tgoalId: Type.Optional(\n\t\tType.String({\n\t\t\tdescription:\n\t\t\t\t\"Soft reference to a goal id; the closure evidence summary is addressed to this goal. Omitting on update keeps the stored value\",\n\t\t}),\n\t),\n\tmaxRetreats: Type.Optional(\n\t\tType.Integer({\n\t\t\tdescription:\n\t\t\t\t\"Workflow lifetime retreat budget before failure, default 3. Omitting on update keeps the stored value\",\n\t\t\tminimum: 0,\n\t\t}),\n\t),\n\tmaxActiveStages: Type.Optional(\n\t\tType.Integer({\n\t\t\tdescription: \"Parallel activation cap, default 4. Omitting on update keeps the stored value\",\n\t\t\tminimum: 1,\n\t\t}),\n\t),\n\tstages: Type.Array(stageSchema, {\n\t\tdescription: \"Full stage list (whole submit, not a patch); the engine aligns runtime by stage id\",\n\t}),\n});\n\nconst workflowAdvanceSchema = Type.Object({\n\tworkflowId: Type.String({ description: \"Target workflow id\" }),\n\taction: Type.Union(\n\t\t[\n\t\t\tType.Literal(\"start\"),\n\t\t\tType.Literal(\"record-evidence\"),\n\t\t\tType.Literal(\"inspect\"),\n\t\t\tType.Literal(\"approve\"),\n\t\t\tType.Literal(\"reject\"),\n\t\t\tType.Literal(\"retreat\"),\n\t\t\tType.Literal(\"complete\"),\n\t\t\tType.Literal(\"skip\"),\n\t\t\tType.Literal(\"cancel\"),\n\t\t],\n\t\t{ description: \"Explicit action to perform\" },\n\t),\n\tstageId: Type.Optional(\n\t\tType.String({\n\t\t\tdescription:\n\t\t\t\t\"Stage id: the evidence/approve/reject/complete/skip target, or the retreat target stage to roll back to\",\n\t\t}),\n\t),\n\texecutor: Type.Optional(\n\t\tType.String({\n\t\t\tdescription:\n\t\t\t\t\"Advisory executor id (e.g. subagent session/task id) driving the stage; record-only, last-write-wins, never affects evaluation\",\n\t\t}),\n\t),\n\tevidence: Type.Optional(\n\t\tType.Array(\n\t\t\tType.Object({\n\t\t\t\tacceptanceId: Type.Optional(\n\t\t\t\t\tType.String({ description: \"Acceptance item id; required in acceptance mode\" }),\n\t\t\t\t),\n\t\t\t\tref: Type.String({ description: \"Evidence reference (tool output, file, artifact)\" }),\n\t\t\t}),\n\t\t\t{ description: \"Evidence items for record-evidence/approve/complete\" },\n\t\t),\n\t),\n\tnote: Type.Optional(\n\t\tType.String({ description: \"Optional note recorded in the transition detail (reject/retreat/skip/cancel)\" }),\n\t),\n});\n\nconst ADVANCE_ACTIONS: readonly string[] = [\n\t\"start\",\n\t\"record-evidence\",\n\t\"inspect\",\n\t\"approve\",\n\t\"reject\",\n\t\"retreat\",\n\t\"complete\",\n\t\"skip\",\n\t\"cancel\",\n];\n\nfunction objectInput(first: unknown, second: unknown): Record<string, unknown> {\n\tconst value = second === undefined ? first : second;\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new Error(\"Workflow input must be an object\");\n\t}\n\treturn value as Record<string, unknown>;\n}\n\nfunction parseAdvanceInput(value: Record<string, unknown>): AdvanceInput {\n\tconst workflowId = asText(value.workflowId, \"workflowId\");\n\tconst action = value.action;\n\tif (typeof action !== \"string\" || !ADVANCE_ACTIONS.includes(action)) {\n\t\tthrow new Error(`action must be one of ${ADVANCE_ACTIONS.join(\", \")}`);\n\t}\n\tconst stageId = value.stageId === undefined ? undefined : asText(value.stageId, \"stageId\");\n\tconst note = value.note === undefined ? undefined : asText(value.note, \"note\");\n\tconst executor = value.executor === undefined ? undefined : asText(value.executor, \"executor\");\n\tlet evidence: EvidenceItem[] | undefined;\n\tif (value.evidence !== undefined) {\n\t\tif (!Array.isArray(value.evidence)) throw new Error(\"evidence must be an array of {acceptanceId?, ref}\");\n\t\tevidence = value.evidence.map((item) => {\n\t\t\tconst entry = asObject(item, \"evidence item\");\n\t\t\tconst ref = asText(entry.ref, \"evidence item ref\");\n\t\t\tconst acceptanceId =\n\t\t\t\tentry.acceptanceId === undefined ? undefined : asText(entry.acceptanceId, \"evidence item acceptanceId\");\n\t\t\treturn acceptanceId === undefined ? { ref } : { acceptanceId, ref };\n\t\t});\n\t}\n\treturn {\n\t\tworkflowId,\n\t\taction: action as AdvanceAction,\n\t\t...(stageId !== undefined ? { stageId } : {}),\n\t\t...(evidence !== undefined ? { evidence } : {}),\n\t\t...(note !== undefined ? { note } : {}),\n\t\t...(executor !== undefined ? { executor } : {}),\n\t};\n}\n\nfunction loadState(api: CapabilityAPI): WorkflowState {\n\tconst entries = api.session?.getBranchEntries() ?? [];\n\tconst entry = [...entries].reverse().find((item) => item.customType === WORKFLOW_STATE_ENTRY);\n\tif (!entry?.data || typeof entry.data !== \"object\") return { workflows: [] };\n\tconst data = entry.data as Partial<WorkflowState>;\n\treturn { workflows: Array.isArray(data.workflows) ? [...data.workflows] : [] };\n}\n\n/**\n * Plan facts read from the current branch's LATEST `plan.state` snapshot (the\n * same latest-snapshot semantics as the plan plugin's own loadState). The\n * plan.changed payload is never trusted for state — only as a trigger.\n *\n * Uncached by design: identity-keyed caching collided across test hosts and\n * hooking invalidation into appendEntry crosses the persistence boundary; the\n * O(stages x entries) rescan is the price of snapshot-driven truth. Revisit\n * only with a per-run cache channel if long-session profiling demands it.\n */\nfunction loadPlansSnapshot(api: CapabilityAPI): Map<string, PlanFacts> {\n\tconst entries = api.session?.getBranchEntries() ?? [];\n\tfor (let index = entries.length - 1; index >= 0; index -= 1) {\n\t\tconst entry = entries[index] as { customType?: string; data?: unknown } | undefined;\n\t\tif (entry?.customType !== planStateEntry) continue;\n\t\tconst data = entry.data;\n\t\tif (!data || typeof data !== \"object\" || Array.isArray(data)) return new Map();\n\t\tconst plans = (data as { plans?: unknown }).plans;\n\t\tif (!Array.isArray(plans)) return new Map();\n\t\tconst facts = new Map<string, PlanFacts>();\n\t\tfor (const plan of plans) {\n\t\t\tif (!plan || typeof plan !== \"object\") continue;\n\t\t\tconst record = plan as { id?: unknown; status?: unknown; evidence?: unknown };\n\t\t\tif (typeof record.id !== \"string\") continue;\n\t\t\tconst status =\n\t\t\t\trecord.status === \"draft\" ||\n\t\t\t\trecord.status === \"active\" ||\n\t\t\t\trecord.status === \"completed\" ||\n\t\t\t\trecord.status === \"cancelled\"\n\t\t\t\t\t? record.status\n\t\t\t\t\t: \"draft\";\n\t\t\tconst evidence = Array.isArray(record.evidence)\n\t\t\t\t? record.evidence.filter((item): item is string => typeof item === \"string\")\n\t\t\t\t: [];\n\t\t\tfacts.set(record.id, { id: record.id, status, evidence });\n\t\t}\n\t\treturn facts;\n\t}\n\treturn new Map();\n}\n\n/** Whether the latest `<entryType>` snapshot on the branch knows `id` in its `idsField` array (advisory, #10). */\nfunction idKnownToSession(api: CapabilityAPI, entryType: string, idsField: string, id: string): boolean {\n\tconst entries = api.session?.getBranchEntries() ?? [];\n\tfor (let index = entries.length - 1; index >= 0; index -= 1) {\n\t\tconst entry = entries[index];\n\t\tif (entry.customType !== entryType) continue;\n\t\tconst data = entry.data;\n\t\tif (!data || typeof data !== \"object\" || Array.isArray(data)) return false;\n\t\tconst records = (data as Record<string, unknown>)[idsField];\n\t\tif (!Array.isArray(records)) return false;\n\t\treturn records.some(\n\t\t\t(record) => record !== null && typeof record === \"object\" && (record as { id?: unknown }).id === id,\n\t\t);\n\t}\n\treturn false;\n}\n\n/**\n * Seeds the held-dedup view (§5 总则 5) from the branch audit stream: the\n * last transition per stage, whatever its code — a repeat held emission is\n * dropped only when it matches that last code and detail.\n */\nfunction buildLastStageTransition(api: CapabilityAPI): Map<string, { code: TransitionReasonCode; detail?: string }> {\n\tconst map = new Map<string, { code: TransitionReasonCode; detail?: string }>();\n\tfor (const entry of api.session?.getBranchEntries() ?? []) {\n\t\tif (entry.customType !== WORKFLOW_TRANSITION_ENTRY) continue;\n\t\tconst data = entry.data;\n\t\tif (!data || typeof data !== \"object\" || Array.isArray(data)) continue;\n\t\tconst record = data as Partial<WorkflowTransitionEntry>;\n\t\tif (typeof record.workflowId !== \"string\" || typeof record.stageId !== \"string\") continue;\n\t\tconst reason = record.reason as { code?: unknown; detail?: unknown } | undefined;\n\t\tif (!reason || typeof reason !== \"object\" || typeof reason.code !== \"string\") continue;\n\t\tmap.set(`${record.workflowId}::${record.stageId}`, {\n\t\t\tcode: reason.code as TransitionReasonCode,\n\t\t\tdetail: typeof reason.detail === \"string\" ? reason.detail : undefined,\n\t\t});\n\t}\n\treturn map;\n}\n\n/** Soft-reference warnings for the tool response only (never the persisted state, #10). */\nfunction collectSoftReferenceWarnings(\n\tapi: CapabilityAPI,\n\tgoalId: string | undefined,\n\tplanIds: { stageId: string; planId: string }[],\n\troles: { stageId: string; role: string }[],\n): string[] {\n\tconst warnings: string[] = [];\n\tif (goalId !== undefined && !idKnownToSession(api, goalStateEntry, \"goals\", goalId)) {\n\t\twarnings.push(\n\t\t\t`goalId \"${goalId}\" does not match any goal in this session's goal state; the workflow keeps the soft reference`,\n\t\t);\n\t}\n\tfor (const item of planIds) {\n\t\tif (!idKnownToSession(api, planStateEntry, \"plans\", item.planId)) {\n\t\t\twarnings.push(\n\t\t\t\t`stage ${item.stageId}: planId \"${item.planId}\" does not match any plan in this session's plan state; ` +\n\t\t\t\t\t\"the stage stays held until a reevaluation finds the plan\",\n\t\t\t);\n\t\t}\n\t}\n\tfor (const item of roles) {\n\t\t// The host's suite role associations are the only verifiable role face;\n\t\t// hosts without the listing leave the advice unverified (no warning).\n\t\tconst associated = api.host?.roleAssociations;\n\t\tif (associated !== undefined && !associated.includes(item.role)) {\n\t\t\twarnings.push(\n\t\t\t\t`stage ${item.stageId}: role \"${item.role}\" is not associated with the active suite; delegation advice treated as unspecified`,\n\t\t\t);\n\t\t}\n\t}\n\treturn warnings;\n}\n\ninterface WorkflowToolResponse extends WorkflowState {\n\tclosures?: WorkflowClosure[];\n\tinspections?: WorkflowInspection[];\n\twarning?: string;\n}\n\nexport function createCapability(\n\tapi: CapabilityAPI,\n): Promise<readonly DisposableRegistration[]> | readonly DisposableRegistration[] {\n\tlet state = loadState(api);\n\tconst deps: EngineDeps = {\n\t\tgetPlan: (planId) => loadPlansSnapshot(api).get(planId),\n\t\tlastStageTransition: buildLastStageTransition(api),\n\t};\n\n\t// Persistence boundary (§4): audit entries first, then the full snapshot —\n\t// a crash mid-batch replays from the older snapshot while the audit stays\n\t// intact. appendEntry failures propagate unchanged (§5 总则 5: no swallow);\n\t// publish rejections surface to the tool caller (or are contained on the\n\t// load/subscriber paths below).\n\tconst persistRun = (run: EngineRun): void => {\n\t\tfor (const transition of run.transitions) {\n\t\t\tapi.session?.appendEntry(WORKFLOW_TRANSITION_ENTRY, transition);\n\t\t}\n\t\tapi.session?.appendEntry(WORKFLOW_STATE_ENTRY, run.state);\n\t};\n\tconst announce = (run: EngineRun): Promise<unknown> =>\n\t\tapi.publish({ type: \"workflow.changed\", version: 1, correlationId: WORKFLOW_STATE_ENTRY, data: run.state });\n\n\t/**\n\t * §5 总则 3 containment: land the failure in diagnostics + a handler.error\n\t * transition (detail = original error text) and never rethrow. Best-effort\n\t * — an already-failing boundary must not turn isolation into a second crash.\n\t */\n\tconst quarantineEngineError = (error: unknown, trigger: WorkflowTransitionTrigger): void => {\n\t\ttry {\n\t\t\tif (state.workflows.length === 0) return;\n\t\t\tconst original = error instanceof Error ? error.message : String(error);\n\t\t\tconst text = `${trigger} handler failed: ${original}`;\n\t\t\tconst workflows = state.workflows.map((workflow) => structuredClone(workflow));\n\t\t\tconst transitions: WorkflowTransitionEntry[] = [];\n\t\t\tfor (const workflow of workflows) {\n\t\t\t\tif (workflow.diagnostics.length >= DIAGNOSTICS_CAP) workflow.diagnostics.shift();\n\t\t\t\tworkflow.diagnostics.push(text);\n\t\t\t\tworkflow.revision += 1;\n\t\t\t\ttransitions.push({\n\t\t\t\t\tworkflowId: workflow.id,\n\t\t\t\t\tfrom: workflow.status,\n\t\t\t\t\tto: workflow.status,\n\t\t\t\t\ttrigger,\n\t\t\t\t\treason: { code: \"handler.error\", message: text, detail: original },\n\t\t\t\t\trevision: workflow.revision,\n\t\t\t\t});\n\t\t\t}\n\t\t\tstate = { workflows };\n\t\t\tfor (const transition of transitions) {\n\t\t\t\tapi.session?.appendEntry(WORKFLOW_TRANSITION_ENTRY, transition);\n\t\t\t}\n\t\t\tapi.session?.appendEntry(WORKFLOW_STATE_ENTRY, state);\n\t\t\tvoid api\n\t\t\t\t.publish({ type: \"workflow.changed\", version: 1, correlationId: WORKFLOW_STATE_ENTRY, data: state })\n\t\t\t\t.catch(() => undefined);\n\t\t} catch {\n\t\t\t// Containment is best-effort by design.\n\t\t}\n\t};\n\n\t// §5 rule 8 recovery: state replayed from workflow.state, then the\n\t// load-time reevaluation (总则 1 fallback moment #1). Runs synchronously at\n\t// factory time; failures are contained, never blocking plugin load.\n\ttry {\n\t\tconst run = reevaluateAll(state, deps, \"load-reeval\");\n\t\tif (run.transitions.length > 0) {\n\t\t\tstate = run.state;\n\t\t\tpersistRun(run);\n\t\t\tvoid announce(run).catch(() => undefined);\n\t\t}\n\t} catch (error) {\n\t\tquarantineEngineError(error, \"load-reeval\");\n\t}\n\n\tconst setTool = api.registerTool({\n\t\tname: \"workflow_set\",\n\t\tlabel: \"Set workflow\",\n\t\tpromptGuidelines: [\n\t\t\tWORKFLOW_APPLICABILITY_GUIDE,\n\t\t\tWORKFLOW_AUTHORING_GUIDE,\n\t\t\tWORKFLOW_EXECUTION_GUIDE,\n\t\t\tWORKFLOW_CORRECTION_GUIDE,\n\t\t\tWORKFLOW_REVIEW_GUIDE,\n\t\t\tWORKFLOW_CONCURRENCY_GUIDE,\n\t\t\tWORKFLOW_INCREMENTAL_DEMAND_GUIDE,\n\t\t\tWORKFLOW_EXECUTOR_GUIDE,\n\t\t],\n\t\tdescription:\n\t\t\t\"Create or update a workflow: a stage dependency graph (DAG) with per-stage objectives, acceptance evidence, and soft goal/plan references. On update, an omitted workflow-level optional field (title/goalId/maxRetreats/maxActiveStages) keeps its stored value; stages are always submitted in full\",\n\t\tparameters: workflowSetSchema,\n\t\texecute: async (first: unknown, second?: unknown) => {\n\t\t\tconst parsed = parseWorkflowSetInput(objectInput(first, second));\n\t\t\tvalidateStageGraph(parsed.stages);\n\t\t\tconst current = state.workflows.find((workflow) => workflow.id === parsed.id);\n\t\t\tif (current !== undefined && parsed.revision <= current.revision) {\n\t\t\t\tthrow new Error(`stale workflow revision: ${parsed.id}`);\n\t\t\t}\n\t\t\tif (\n\t\t\t\tcurrent !== undefined &&\n\t\t\t\t(current.status === \"completed\" || current.status === \"failed\" || current.status === \"cancelled\")\n\t\t\t) {\n\t\t\t\tthrow new Error(`workflow is terminal and cannot be updated: ${parsed.id}`);\n\t\t\t}\n\t\t\tconst diff = planWorkflowSpecUpdate(current, parsed);\n\t\t\tconst run = applyWorkflowSet(state, parsed, diff, deps);\n\t\t\tstate = run.state;\n\t\t\tif (run.transitions.length > 0 || diff.created) persistRun(run);\n\t\t\tif (run.transitions.length > 0 || diff.created) await announce(run);\n\t\t\tconst response: WorkflowToolResponse = { ...state };\n\t\t\tif (run.closures.length > 0) response.closures = run.closures;\n\t\t\tconst warnings = collectSoftReferenceWarnings(\n\t\t\t\tapi,\n\t\t\t\tparsed.goalId,\n\t\t\t\tparsed.stages.flatMap((stage) =>\n\t\t\t\t\tstage.planId !== undefined ? [{ stageId: stage.id, planId: stage.planId }] : [],\n\t\t\t\t),\n\t\t\t\tparsed.stages.flatMap((stage) =>\n\t\t\t\t\tstage.role !== undefined ? [{ stageId: stage.id, role: stage.role }] : [],\n\t\t\t\t),\n\t\t\t);\n\t\t\tif (warnings.length > 0) response.warning = warnings.join(\"; \");\n\t\t\treturn response;\n\t\t},\n\t});\n\n\tconst advanceTool = api.registerTool({\n\t\tname: \"workflow_advance\",\n\t\tlabel: \"Advance workflow\",\n\t\tdescription:\n\t\t\t\"Drive a workflow: start it, record acceptance evidence, inspect waiting conditions and coverage, approve/reject reviews, retreat, complete checkpoints, skip stages, or cancel\",\n\t\tparameters: workflowAdvanceSchema,\n\t\texecute: async (first: unknown, second?: unknown) => {\n\t\t\tconst parsed = parseAdvanceInput(objectInput(first, second));\n\t\t\t// Illegal conversions throw structured errors (§5 rule 6) surfaced\n\t\t\t// as tool errors unchanged; legal ones return the full snapshot\n\t\t\t// (the goal_set full-state response pattern).\n\t\t\tconst run = applyAdvance(state, parsed, deps);\n\t\t\tstate = run.state;\n\t\t\tif (run.transitions.length > 0) {\n\t\t\t\tpersistRun(run);\n\t\t\t\tawait announce(run);\n\t\t\t}\n\t\t\tconst response: WorkflowToolResponse = { ...state };\n\t\t\tif (parsed.action === \"inspect\") {\n\t\t\t\t// §5 rule 6 single-workflow semantics: applyAdvance has already\n\t\t\t\t// rejected unknown ids, so the target always resolves here.\n\t\t\t\tconst target = state.workflows.find((workflow) => workflow.id === parsed.workflowId);\n\t\t\t\tif (target !== undefined) response.inspections = [inspectWorkflow(target, deps)];\n\t\t\t}\n\t\t\tif (run.closures.length > 0) response.closures = run.closures;\n\t\t\treturn response;\n\t\t},\n\t});\n\n\tconst workflowCommand = api.registerCommand({\n\t\tname: \"workflow\",\n\t\tdescription: \"Workflow overview: dependency tree and status (default), why it is stopped, or the transition log\",\n\t\targumentHint: \"[view | why | log [N]]\",\n\t\texecute: async (args: string) => {\n\t\t\ttry {\n\t\t\t\tconst trimmed = args.trim();\n\t\t\t\tif (trimmed === \"\" || trimmed === \"view\") {\n\t\t\t\t\treturn { status: \"success\" as const, message: renderPanorama(state, deps) };\n\t\t\t\t}\n\t\t\t\tif (trimmed === \"why\") {\n\t\t\t\t\treturn { status: \"success\" as const, message: renderWhy(state, deps) };\n\t\t\t\t}\n\t\t\t\tconst logMatch = /^log(?:\\s+(\\d+))?$/.exec(trimmed);\n\t\t\t\tif (logMatch !== null) {\n\t\t\t\t\tconst limit = logMatch[1] === undefined ? 20 : Math.max(1, Number.parseInt(logMatch[1], 10));\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: \"success\" as const,\n\t\t\t\t\t\tmessage: renderLog(api.session?.getBranchEntries() ?? [], limit),\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn { status: \"error\" as const, message: \"Usage: /workflow [view | why | log [N]]\" };\n\t\t\t} catch (error) {\n\t\t\t\t// A slash command must not crash the host (memory /promote precedent).\n\t\t\t\treturn { status: \"error\" as const, message: error instanceof Error ? error.message : String(error) };\n\t\t\t}\n\t\t},\n\t});\n\n\t// The repository's first event subscription (§7). The payload is ignored:\n\t// reevaluation always reads the current branch entries (§5 总则 1).\n\tconst planChanged = api.subscribe(\"plan.changed\", async () => {\n\t\ttry {\n\t\t\tconst run = reevaluateAll(state, deps, \"plan.changed\");\n\t\t\tif (run.transitions.length === 0) return;\n\t\t\tstate = run.state;\n\t\t\tpersistRun(run);\n\t\t\tawait announce(run);\n\t\t} catch (error) {\n\t\t\tquarantineEngineError(error, \"plan.changed\");\n\t\t}\n\t});\n\n\treturn [setTool, advanceTool, workflowCommand, planChanged];\n}\n"]}
|
package/dist/types.d.ts
CHANGED
|
@@ -63,6 +63,8 @@ export interface StageRuntime {
|
|
|
63
63
|
acceptanceId: string;
|
|
64
64
|
ref: string;
|
|
65
65
|
}[];
|
|
66
|
+
/** Advisory: who is currently driving this stage (e.g. a subagent session/task id). Record-only — never validated and never consulted by activation or evaluation; last-write-wins via record-evidence's executor parameter. */
|
|
67
|
+
executor?: string;
|
|
66
68
|
}
|
|
67
69
|
/** Audit stream: exactly one entry per state conversion, including held/rejected attempts (§5 总则 5). */
|
|
68
70
|
export interface WorkflowTransitionEntry {
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,uEAAuE;AACvE,eAAO,MAAM,oBAAoB,mBAAmB,CAAC;AACrD,wEAAwE;AACxE,eAAO,MAAM,yBAAyB,wBAAwB,CAAC;AAE/D,MAAM,WAAW,aAAa;IAC7B,SAAS,EAAE,cAAc,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;IACnE,mGAAkG;IAClG,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oFAAoF;IACpF,WAAW,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE;QACV,4EAA4E;QAC5E,SAAS,EAAE,MAAM,CAAC;QAClB,4FAA4F;QAC5F,UAAU,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;KAChD,CAAC;IACF,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,8FAA8F;IAC9F,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kGAAiG;IACjG,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,iBAAiB,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;IACtF,4FAA2F;IAC3F,QAAQ,EAAE,MAAM,CAAC;IACjB,iGAAiG;IACjG,QAAQ,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,uEAAuE;AACvE,eAAO,MAAM,oBAAoB,mBAAmB,CAAC;AACrD,wEAAwE;AACxE,eAAO,MAAM,yBAAyB,wBAAwB,CAAC;AAE/D,MAAM,WAAW,aAAa;IAC7B,SAAS,EAAE,cAAc,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;IACnE,mGAAkG;IAClG,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oFAAoF;IACpF,WAAW,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE;QACV,4EAA4E;QAC5E,SAAS,EAAE,MAAM,CAAC;QAClB,4FAA4F;QAC5F,UAAU,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;KAChD,CAAC;IACF,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,8FAA8F;IAC9F,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kGAAiG;IACjG,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,iBAAiB,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;IACtF,4FAA2F;IAC3F,QAAQ,EAAE,MAAM,CAAC;IACjB,iGAAiG;IACjG,QAAQ,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAClD,kOAAgO;IAChO,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,6GAAwG;AACxG,MAAM,WAAW,uBAAuB;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,yBAAyB,CAAC;IACnC,MAAM,EAAE,gBAAgB,CAAC;IACzB,0DAAyD;IACzD,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,yBAAyB,GAAG,MAAM,GAAG,cAAc,GAAG,aAAa,GAAG,mBAAmB,CAAC;AAEtG,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAE7B,iBAAiB,GACjB,oCAAoC,GACpC,4BAA4B,GAC5B,iCAAiC,GACjC,yBAAyB,GACzB,uBAAuB,GAEvB,iBAAiB,GACjB,oCAAoC,GACpC,eAAe,GACf,mBAAmB,GAEnB,iCAAiC,GACjC,6BAA6B,GAC7B,oBAAoB,GACpB,iBAAiB,GACjB,+BAA+B,GAC/B,gCAAgC,GAEhC,kBAAkB,GAClB,oBAAoB,GACpB,oBAAoB,GAEpB,oBAAoB,GAEpB,uBAAuB,GACvB,eAAe,CAAC","sourcesContent":["/**\n * Workflow data model — the verbatim §4 contract of\n * `docs/design/工作流编排插件设计.md` plus the closed reason-code catalog\n * (§8.2) and the session entry keys shared across modules.\n *\n * Persisted as append-only custom entries: `workflow.state` (full snapshot,\n * the single rebuild source) and `workflow.transition` (per-conversion audit\n * stream; §8's primary data source, never used for state rebuild).\n */\n\n/** Session protocol key of this plugin's full-state snapshot entry. */\nexport const WORKFLOW_STATE_ENTRY = \"workflow.state\";\n/** Session protocol key of this plugin's per-conversion audit entry. */\nexport const WORKFLOW_TRANSITION_ENTRY = \"workflow.transition\";\n\nexport interface WorkflowState {\n\tworkflows: WorkflowRecord[];\n}\n\nexport interface WorkflowRecord {\n\tid: string;\n\ttitle: string;\n\tgoalId?: string; // soft reference to goal.state\n\tstatus: \"draft\" | \"running\" | \"completed\" | \"failed\" | \"cancelled\";\n\t/** Caller-supplied on workflow_set (monotonic); engine conversions auto-increment (§5 rule 8). */\n\trevision: number;\n\tstages: StageSpec[];\n\truntime: StageRuntime[];\n\tretreatCount: number; // total cross-stage retreats over the workflow lifetime\n\tmaxRetreats?: number; // default 3; reaching the cap -> workflow failed\n\tmaxActiveStages?: number; // parallel activation cap, default 4\n\t/** Current alerts, FIFO capped at 50; full history lives in workflow.transition. */\n\tdiagnostics: string[];\n}\n\nexport interface StageSpec {\n\tid: string; // stable stage id, unique within the workflow\n\ttitle: string;\n\tobjective: {\n\t\t/** The verifiable end state this stage must reach (required, non-empty). */\n\t\tstatement: string;\n\t\t/** Completion criteria; empty array = lower bound is the plan's own completion evidence. */\n\t\tacceptance: { id: string; statement: string }[];\n\t};\n\tdependsOn: string[]; // hard prerequisites; empty array = root stage\n\tplanId?: string; // soft reference to plan.state; missing = pure checkpoint stage; unique per workflow\n\tkind: \"read\" | \"write\"; // default \"write\"\n\t/** Write scope tags (modules/dirs); missing = global (intersects every other write stage). */\n\tscope?: string[];\n\trole?: string; // soft reference to <agentDir>/roles/<id>.json; delegation advice only\n\tadvance: \"auto\" | \"review\"; // default \"auto\"; \"review\" only affects stages with a planId\n\tretryLimit?: number; // in-place retry cap, default 2; exhaust routes to onFail or workflow failure\n\tonFail?: string; // explicit cross-stage retreat target (a topologically earlier stage id)\n\t/** Required correction reason when an active/awaiting_review stage's spec changes (§6 amend). */\n\tamendNote?: string;\n}\n\nexport interface StageRuntime {\n\tstageId: string;\n\tstatus: \"pending\" | \"active\" | \"awaiting_review\" | \"completed\" | \"failed\" | \"skipped\";\n\t/** Failure-retry count; preserved across in-place retry and retreat re-activation (§4). */\n\tattempts: number;\n\t/** Appended via record-evidence / approve / complete; coverage is derived at evaluation time. */\n\tevidence: { acceptanceId: string; ref: string }[];\n\t/** Advisory: who is currently driving this stage (e.g. a subagent session/task id). Record-only — never validated and never consulted by activation or evaluation; last-write-wins via record-evidence's executor parameter. */\n\texecutor?: string;\n}\n\n/** Audit stream: exactly one entry per state conversion, including held/rejected attempts (§5 总则 5). */\nexport interface WorkflowTransitionEntry {\n\tworkflowId: string;\n\tstageId?: string; // absent on workflow-level conversions (start/closure/burnout)\n\tfrom: string;\n\tto: string;\n\ttrigger: WorkflowTransitionTrigger;\n\treason: TransitionReason; // codes: §8.2 closed catalog\n\t/** Anchors the adjacent workflow.state snapshot (§4). */\n\trevision: number;\n}\n\nexport type WorkflowTransitionTrigger = \"tool\" | \"plan.changed\" | \"load-reeval\" | \"activation-reeval\";\n\nexport interface TransitionReason {\n\tcode: TransitionReasonCode;\n\tmessage: string;\n\tdetail?: string;\n}\n\n/**\n * Closed reason-code catalog (§8.2). Tests must cover every code; do not add\n * codes without amending the design document first.\n */\nexport type TransitionReasonCode =\n\t// Activation and unlocking\n\t| \"stage.activated\"\n\t| \"stage.activated.held-plan-dangling\"\n\t| \"stage.held.deps-incomplete\"\n\t| \"stage.held.write-scope-conflict\"\n\t| \"stage.held.active-limit\"\n\t| \"stage.awaiting-review\"\n\t// Completion\n\t| \"stage.completed\"\n\t| \"stage.completed.acceptance-covered\"\n\t| \"stage.skipped\"\n\t| \"evidence.recorded\"\n\t// Failure and retreat\n\t| \"stage.failed.acceptance-missing\"\n\t| \"stage.failed.plan-cancelled\"\n\t| \"stage.retry.queued\"\n\t| \"stage.retreated\"\n\t| \"workflow.failed.stage-retries\"\n\t| \"workflow.failed.retreat-budget\"\n\t// Workflow level\n\t| \"workflow.started\"\n\t| \"workflow.completed\"\n\t| \"workflow.cancelled\"\n\t// Human-in-the-loop correction\n\t| \"stage.spec-amended\"\n\t// Engine itself\n\t| \"cascade.limit-reached\"\n\t| \"handler.error\";\n"]}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,uEAAuE;AACvE,MAAM,CAAC,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AACrD,wEAAwE;AACxE,MAAM,CAAC,MAAM,yBAAyB,GAAG,qBAAqB,CAAC","sourcesContent":["/**\n * Workflow data model — the verbatim §4 contract of\n * `docs/design/工作流编排插件设计.md` plus the closed reason-code catalog\n * (§8.2) and the session entry keys shared across modules.\n *\n * Persisted as append-only custom entries: `workflow.state` (full snapshot,\n * the single rebuild source) and `workflow.transition` (per-conversion audit\n * stream; §8's primary data source, never used for state rebuild).\n */\n\n/** Session protocol key of this plugin's full-state snapshot entry. */\nexport const WORKFLOW_STATE_ENTRY = \"workflow.state\";\n/** Session protocol key of this plugin's per-conversion audit entry. */\nexport const WORKFLOW_TRANSITION_ENTRY = \"workflow.transition\";\n\nexport interface WorkflowState {\n\tworkflows: WorkflowRecord[];\n}\n\nexport interface WorkflowRecord {\n\tid: string;\n\ttitle: string;\n\tgoalId?: string; // soft reference to goal.state\n\tstatus: \"draft\" | \"running\" | \"completed\" | \"failed\" | \"cancelled\";\n\t/** Caller-supplied on workflow_set (monotonic); engine conversions auto-increment (§5 rule 8). */\n\trevision: number;\n\tstages: StageSpec[];\n\truntime: StageRuntime[];\n\tretreatCount: number; // total cross-stage retreats over the workflow lifetime\n\tmaxRetreats?: number; // default 3; reaching the cap -> workflow failed\n\tmaxActiveStages?: number; // parallel activation cap, default 4\n\t/** Current alerts, FIFO capped at 50; full history lives in workflow.transition. */\n\tdiagnostics: string[];\n}\n\nexport interface StageSpec {\n\tid: string; // stable stage id, unique within the workflow\n\ttitle: string;\n\tobjective: {\n\t\t/** The verifiable end state this stage must reach (required, non-empty). */\n\t\tstatement: string;\n\t\t/** Completion criteria; empty array = lower bound is the plan's own completion evidence. */\n\t\tacceptance: { id: string; statement: string }[];\n\t};\n\tdependsOn: string[]; // hard prerequisites; empty array = root stage\n\tplanId?: string; // soft reference to plan.state; missing = pure checkpoint stage; unique per workflow\n\tkind: \"read\" | \"write\"; // default \"write\"\n\t/** Write scope tags (modules/dirs); missing = global (intersects every other write stage). */\n\tscope?: string[];\n\trole?: string; // soft reference to <agentDir>/roles/<id>.json; delegation advice only\n\tadvance: \"auto\" | \"review\"; // default \"auto\"; \"review\" only affects stages with a planId\n\tretryLimit?: number; // in-place retry cap, default 2; exhaust routes to onFail or workflow failure\n\tonFail?: string; // explicit cross-stage retreat target (a topologically earlier stage id)\n\t/** Required correction reason when an active/awaiting_review stage's spec changes (§6 amend). */\n\tamendNote?: string;\n}\n\nexport interface StageRuntime {\n\tstageId: string;\n\tstatus: \"pending\" | \"active\" | \"awaiting_review\" | \"completed\" | \"failed\" | \"skipped\";\n\t/** Failure-retry count; preserved across in-place retry and retreat re-activation (§4). */\n\tattempts: number;\n\t/** Appended via record-evidence / approve / complete; coverage is derived at evaluation time. */\n\tevidence: { acceptanceId: string; ref: string }[];\n}\n\n/** Audit stream: exactly one entry per state conversion, including held/rejected attempts (§5 总则 5). */\nexport interface WorkflowTransitionEntry {\n\tworkflowId: string;\n\tstageId?: string; // absent on workflow-level conversions (start/closure/burnout)\n\tfrom: string;\n\tto: string;\n\ttrigger: WorkflowTransitionTrigger;\n\treason: TransitionReason; // codes: §8.2 closed catalog\n\t/** Anchors the adjacent workflow.state snapshot (§4). */\n\trevision: number;\n}\n\nexport type WorkflowTransitionTrigger = \"tool\" | \"plan.changed\" | \"load-reeval\" | \"activation-reeval\";\n\nexport interface TransitionReason {\n\tcode: TransitionReasonCode;\n\tmessage: string;\n\tdetail?: string;\n}\n\n/**\n * Closed reason-code catalog (§8.2). Tests must cover every code; do not add\n * codes without amending the design document first.\n */\nexport type TransitionReasonCode =\n\t// Activation and unlocking\n\t| \"stage.activated\"\n\t| \"stage.activated.held-plan-dangling\"\n\t| \"stage.held.deps-incomplete\"\n\t| \"stage.held.write-scope-conflict\"\n\t| \"stage.held.active-limit\"\n\t| \"stage.awaiting-review\"\n\t// Completion\n\t| \"stage.completed\"\n\t| \"stage.completed.acceptance-covered\"\n\t| \"stage.skipped\"\n\t| \"evidence.recorded\"\n\t// Failure and retreat\n\t| \"stage.failed.acceptance-missing\"\n\t| \"stage.failed.plan-cancelled\"\n\t| \"stage.retry.queued\"\n\t| \"stage.retreated\"\n\t| \"workflow.failed.stage-retries\"\n\t| \"workflow.failed.retreat-budget\"\n\t// Workflow level\n\t| \"workflow.started\"\n\t| \"workflow.completed\"\n\t| \"workflow.cancelled\"\n\t// Human-in-the-loop correction\n\t| \"stage.spec-amended\"\n\t// Engine itself\n\t| \"cascade.limit-reached\"\n\t| \"handler.error\";\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,uEAAuE;AACvE,MAAM,CAAC,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AACrD,wEAAwE;AACxE,MAAM,CAAC,MAAM,yBAAyB,GAAG,qBAAqB,CAAC","sourcesContent":["/**\n * Workflow data model — the verbatim §4 contract of\n * `docs/design/工作流编排插件设计.md` plus the closed reason-code catalog\n * (§8.2) and the session entry keys shared across modules.\n *\n * Persisted as append-only custom entries: `workflow.state` (full snapshot,\n * the single rebuild source) and `workflow.transition` (per-conversion audit\n * stream; §8's primary data source, never used for state rebuild).\n */\n\n/** Session protocol key of this plugin's full-state snapshot entry. */\nexport const WORKFLOW_STATE_ENTRY = \"workflow.state\";\n/** Session protocol key of this plugin's per-conversion audit entry. */\nexport const WORKFLOW_TRANSITION_ENTRY = \"workflow.transition\";\n\nexport interface WorkflowState {\n\tworkflows: WorkflowRecord[];\n}\n\nexport interface WorkflowRecord {\n\tid: string;\n\ttitle: string;\n\tgoalId?: string; // soft reference to goal.state\n\tstatus: \"draft\" | \"running\" | \"completed\" | \"failed\" | \"cancelled\";\n\t/** Caller-supplied on workflow_set (monotonic); engine conversions auto-increment (§5 rule 8). */\n\trevision: number;\n\tstages: StageSpec[];\n\truntime: StageRuntime[];\n\tretreatCount: number; // total cross-stage retreats over the workflow lifetime\n\tmaxRetreats?: number; // default 3; reaching the cap -> workflow failed\n\tmaxActiveStages?: number; // parallel activation cap, default 4\n\t/** Current alerts, FIFO capped at 50; full history lives in workflow.transition. */\n\tdiagnostics: string[];\n}\n\nexport interface StageSpec {\n\tid: string; // stable stage id, unique within the workflow\n\ttitle: string;\n\tobjective: {\n\t\t/** The verifiable end state this stage must reach (required, non-empty). */\n\t\tstatement: string;\n\t\t/** Completion criteria; empty array = lower bound is the plan's own completion evidence. */\n\t\tacceptance: { id: string; statement: string }[];\n\t};\n\tdependsOn: string[]; // hard prerequisites; empty array = root stage\n\tplanId?: string; // soft reference to plan.state; missing = pure checkpoint stage; unique per workflow\n\tkind: \"read\" | \"write\"; // default \"write\"\n\t/** Write scope tags (modules/dirs); missing = global (intersects every other write stage). */\n\tscope?: string[];\n\trole?: string; // soft reference to <agentDir>/roles/<id>.json; delegation advice only\n\tadvance: \"auto\" | \"review\"; // default \"auto\"; \"review\" only affects stages with a planId\n\tretryLimit?: number; // in-place retry cap, default 2; exhaust routes to onFail or workflow failure\n\tonFail?: string; // explicit cross-stage retreat target (a topologically earlier stage id)\n\t/** Required correction reason when an active/awaiting_review stage's spec changes (§6 amend). */\n\tamendNote?: string;\n}\n\nexport interface StageRuntime {\n\tstageId: string;\n\tstatus: \"pending\" | \"active\" | \"awaiting_review\" | \"completed\" | \"failed\" | \"skipped\";\n\t/** Failure-retry count; preserved across in-place retry and retreat re-activation (§4). */\n\tattempts: number;\n\t/** Appended via record-evidence / approve / complete; coverage is derived at evaluation time. */\n\tevidence: { acceptanceId: string; ref: string }[];\n\t/** Advisory: who is currently driving this stage (e.g. a subagent session/task id). Record-only — never validated and never consulted by activation or evaluation; last-write-wins via record-evidence's executor parameter. */\n\texecutor?: string;\n}\n\n/** Audit stream: exactly one entry per state conversion, including held/rejected attempts (§5 总则 5). */\nexport interface WorkflowTransitionEntry {\n\tworkflowId: string;\n\tstageId?: string; // absent on workflow-level conversions (start/closure/burnout)\n\tfrom: string;\n\tto: string;\n\ttrigger: WorkflowTransitionTrigger;\n\treason: TransitionReason; // codes: §8.2 closed catalog\n\t/** Anchors the adjacent workflow.state snapshot (§4). */\n\trevision: number;\n}\n\nexport type WorkflowTransitionTrigger = \"tool\" | \"plan.changed\" | \"load-reeval\" | \"activation-reeval\";\n\nexport interface TransitionReason {\n\tcode: TransitionReasonCode;\n\tmessage: string;\n\tdetail?: string;\n}\n\n/**\n * Closed reason-code catalog (§8.2). Tests must cover every code; do not add\n * codes without amending the design document first.\n */\nexport type TransitionReasonCode =\n\t// Activation and unlocking\n\t| \"stage.activated\"\n\t| \"stage.activated.held-plan-dangling\"\n\t| \"stage.held.deps-incomplete\"\n\t| \"stage.held.write-scope-conflict\"\n\t| \"stage.held.active-limit\"\n\t| \"stage.awaiting-review\"\n\t// Completion\n\t| \"stage.completed\"\n\t| \"stage.completed.acceptance-covered\"\n\t| \"stage.skipped\"\n\t| \"evidence.recorded\"\n\t// Failure and retreat\n\t| \"stage.failed.acceptance-missing\"\n\t| \"stage.failed.plan-cancelled\"\n\t| \"stage.retry.queued\"\n\t| \"stage.retreated\"\n\t| \"workflow.failed.stage-retries\"\n\t| \"workflow.failed.retreat-budget\"\n\t// Workflow level\n\t| \"workflow.started\"\n\t| \"workflow.completed\"\n\t| \"workflow.cancelled\"\n\t// Human-in-the-loop correction\n\t| \"stage.spec-amended\"\n\t// Engine itself\n\t| \"cascade.limit-reached\"\n\t| \"handler.error\";\n"]}
|
package/dist/validate.d.ts
CHANGED
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
* active/awaiting_review amend with a mandatory amendNote, completed/skipped
|
|
5
5
|
* are frozen history).
|
|
6
6
|
*
|
|
7
|
+
* Since v8 the parsed workflow-level optional fields (title/goalId/
|
|
8
|
+
* maxRetreats/maxActiveStages) may be omitted on updates — the keep-stored-
|
|
9
|
+
* value merge lives in applyWorkflowSet (engine.ts); creation still requires
|
|
10
|
+
* a title.
|
|
11
|
+
*
|
|
7
12
|
* All failures are structured errors (thrown Error with a field-specific
|
|
8
13
|
* message), matching the goal_set/plan_set validation style: the original
|
|
9
14
|
* error always reaches the caller; nothing is silently coerced.
|
|
@@ -11,7 +16,12 @@
|
|
|
11
16
|
import type { StageSpec, WorkflowRecord } from "./types.ts";
|
|
12
17
|
export interface ParsedWorkflowSet {
|
|
13
18
|
id: string;
|
|
14
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Optional since v8 (§6): on the update path an omitted title keeps the
|
|
21
|
+
* stored value (like goalId/maxRetreats/maxActiveStages); on the create
|
|
22
|
+
* path a title is still required (guarded in applyWorkflowSet).
|
|
23
|
+
*/
|
|
24
|
+
title?: string;
|
|
15
25
|
goalId?: string;
|
|
16
26
|
revision: number;
|
|
17
27
|
maxRetreats?: number;
|
package/dist/validate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5D,MAAM,WAAW,iBAAiB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,SAAS,EAAE,CAAC;CACpB;AAED,0GAAyG;AACzG,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB,kGAAiG;IACjG,cAAc,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,mEAAmE;IACnE,YAAY,EAAE,eAAe,EAAE,CAAC;IAChC,6FAA4F;IAC5F,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC3B;AAMD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAG9E;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG3D;AA0FD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,iBAAiB,CAiBrE;AAMD,yFAAyF;AACzF,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAa9F;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAuD5D;AAsCD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,cAAc,GAAG,SAAS,EAAE,IAAI,EAAE,iBAAiB,GAAG,eAAe,CAuDrH","sourcesContent":["/**\n * workflow_set input parsing and structural validation (§6), including the\n * running-modification grading rules (§6 分级 / principle 9: pending is free,\n * active/awaiting_review amend with a mandatory amendNote, completed/skipped\n * are frozen history).\n *\n * All failures are structured errors (thrown Error with a field-specific\n * message), matching the goal_set/plan_set validation style: the original\n * error always reaches the caller; nothing is silently coerced.\n */\n\nimport type { StageSpec, WorkflowRecord } from \"./types.ts\";\n\nexport interface ParsedWorkflowSet {\n\tid: string;\n\ttitle: string;\n\tgoalId?: string;\n\trevision: number;\n\tmaxRetreats?: number;\n\tmaxActiveStages?: number;\n\tstages: StageSpec[];\n}\n\n/** One active/awaiting_review stage that changed spec and must leave a stage.spec-amended audit (§6). */\nexport interface StageChangePlan {\n\tstageId: string;\n\t/** Amendable field names that differ from the stored spec. */\n\tfields: string[];\n\t/** Correction reason; required non-empty on the amend path. */\n\tamendNote: string;\n\t/** Acceptance ids removed by the amend that still had evidence attached (linkage detail, §6). */\n\tprunedEvidence: string[];\n}\n\nexport interface WorkflowSetDiff {\n\tcreated: boolean;\n\t/** Amend-path changes (one stage.spec-amended transition each). */\n\tamendChanges: StageChangePlan[];\n\t/** Stage ids appended after the existing stage sequence (append-only structure ops, §6). */\n\tappendedStageIds: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Primitive parsers (goal_set/plan_set style)\n// ---------------------------------------------------------------------------\n\nexport function asObject(value: unknown, name: string): Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(`${name} must be an object`);\n\treturn value as Record<string, unknown>;\n}\n\nexport function asText(value: unknown, name: string): string {\n\tif (typeof value !== \"string\" || value.trim() === \"\") throw new Error(`${name} must be a non-empty string`);\n\treturn value;\n}\n\nfunction optionalText(value: unknown, name: string): string | undefined {\n\tif (value === undefined) return undefined;\n\treturn asText(value, name);\n}\n\nfunction intAtLeast(value: unknown, minimum: number, name: string): number {\n\tif (typeof value !== \"number\" || !Number.isInteger(value) || value < minimum) {\n\t\tthrow new Error(`${name} must be an integer >= ${minimum}`);\n\t}\n\treturn value;\n}\n\nfunction stringArray(value: unknown, name: string): string[] {\n\tif (value === undefined) return [];\n\tif (!Array.isArray(value) || value.some((item) => typeof item !== \"string\" || item.trim() === \"\")) {\n\t\tthrow new Error(`${name} must be an array of non-empty strings`);\n\t}\n\treturn [...(value as string[])];\n}\n\n// ---------------------------------------------------------------------------\n// workflow_set input parsing\n// ---------------------------------------------------------------------------\n\nfunction parseStage(raw: unknown, index: number): StageSpec {\n\tconst stage = asObject(raw, `stages[${index}]`);\n\tconst id = asText(stage.id, `stages[${index}].id`);\n\tconst field = (name: string) => `stage ${id}: ${name}`;\n\tconst title = asText(stage.title, field(\"title\"));\n\n\tconst objectiveRaw = asObject(stage.objective, field(\"objective\"));\n\tconst statement = asText(objectiveRaw.statement, field(\"objective.statement\"));\n\tlet acceptance: { id: string; statement: string }[] = [];\n\tif (objectiveRaw.acceptance !== undefined) {\n\t\tif (!Array.isArray(objectiveRaw.acceptance)) {\n\t\t\tthrow new Error(field(\"objective.acceptance must be an array\"));\n\t\t}\n\t\tacceptance = objectiveRaw.acceptance.map((item, itemIndex) => {\n\t\t\tconst entry = asObject(item, field(`objective.acceptance[${itemIndex}]`));\n\t\t\treturn {\n\t\t\t\tid: asText(entry.id, field(`objective.acceptance[${itemIndex}].id`)),\n\t\t\t\tstatement: asText(entry.statement, field(`objective.acceptance[${itemIndex}].statement`)),\n\t\t\t};\n\t\t});\n\t\tconst seen = new Set<string>();\n\t\tfor (const item of acceptance) {\n\t\t\tif (seen.has(item.id)) throw new Error(field(`duplicate acceptance id ${item.id}`));\n\t\t\tseen.add(item.id);\n\t\t}\n\t}\n\n\tlet kind: StageSpec[\"kind\"] = \"write\";\n\tif (stage.kind !== undefined) {\n\t\tif (stage.kind !== \"read\" && stage.kind !== \"write\") {\n\t\t\tthrow new Error(field('kind must be \"read\" or \"write\"'));\n\t\t}\n\t\tkind = stage.kind;\n\t}\n\tlet advance: StageSpec[\"advance\"] = \"auto\";\n\tif (stage.advance !== undefined) {\n\t\tif (stage.advance !== \"auto\" && stage.advance !== \"review\") {\n\t\t\tthrow new Error(field('advance must be \"auto\" or \"review\"'));\n\t\t}\n\t\tadvance = stage.advance;\n\t}\n\tconst scopeRaw = stringArray(stage.scope, field(\"scope\"));\n\tconst retryLimit = stage.retryLimit === undefined ? undefined : intAtLeast(stage.retryLimit, 0, field(\"retryLimit\"));\n\tconst planId = optionalText(stage.planId, field(\"planId\"));\n\tconst role = optionalText(stage.role, field(\"role\"));\n\tconst onFail = optionalText(stage.onFail, field(\"onFail\"));\n\tconst amendNote = optionalText(stage.amendNote, field(\"amendNote\"));\n\n\treturn {\n\t\tid,\n\t\ttitle,\n\t\tobjective: { statement, acceptance },\n\t\tdependsOn: stringArray(stage.dependsOn, field(\"dependsOn\")),\n\t\t...(planId !== undefined ? { planId } : {}),\n\t\tkind,\n\t\t...(scopeRaw.length > 0 ? { scope: scopeRaw } : {}),\n\t\t...(role !== undefined ? { role } : {}),\n\t\tadvance,\n\t\t...(retryLimit !== undefined ? { retryLimit } : {}),\n\t\t...(onFail !== undefined ? { onFail } : {}),\n\t\t...(amendNote !== undefined ? { amendNote } : {}),\n\t};\n}\n\nexport function parseWorkflowSetInput(raw: unknown): ParsedWorkflowSet {\n\tconst value = asObject(raw, \"workflow input\");\n\tif (!Array.isArray(value.stages) || value.stages.length === 0) {\n\t\tthrow new Error(\"stages must be a non-empty array\");\n\t}\n\tconst goalId = optionalText(value.goalId, \"goalId\");\n\treturn {\n\t\tid: asText(value.id, \"id\"),\n\t\ttitle: asText(value.title, \"title\"),\n\t\trevision: intAtLeast(value.revision, 0, \"revision\"),\n\t\t...(goalId !== undefined ? { goalId } : {}),\n\t\t...(value.maxRetreats === undefined ? {} : { maxRetreats: intAtLeast(value.maxRetreats, 0, \"maxRetreats\") }),\n\t\t...(value.maxActiveStages === undefined\n\t\t\t? {}\n\t\t\t: { maxActiveStages: intAtLeast(value.maxActiveStages, 1, \"maxActiveStages\") }),\n\t\tstages: value.stages.map((stage, index) => parseStage(stage, index)),\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Structural graph validation (§6 workflow_set)\n// ---------------------------------------------------------------------------\n\n/** Whether `targetId` is transitively reachable from `startId` along dependsOn edges. */\nexport function dependsOnReach(stages: StageSpec[], startId: string, targetId: string): boolean {\n\tconst byId = new Map(stages.map((stage) => [stage.id, stage]));\n\tconst visited = new Set<string>();\n\tconst queue = [startId];\n\twhile (queue.length > 0) {\n\t\tconst current = queue.pop();\n\t\tif (current === undefined || visited.has(current)) continue;\n\t\tvisited.add(current);\n\t\tif (current === targetId) return true;\n\t\tconst spec = byId.get(current);\n\t\tif (spec !== undefined) queue.push(...spec.dependsOn);\n\t}\n\treturn false;\n}\n\n/**\n * Full structural validation: stage id uniqueness, reference existence,\n * workflow-internal planId uniqueness (cross-workflow sharing is allowed),\n * onFail pointing topologically earlier, and combined dependsOn+onFail cycle\n * detection (DFS over the mixed edge set — §6 names mixed cycles explicitly).\n */\nexport function validateStageGraph(stages: StageSpec[]): void {\n\tif (stages.length === 0) throw new Error(\"stages must not be empty\");\n\tconst byId = new Map<string, StageSpec>();\n\tfor (const stage of stages) {\n\t\tif (byId.has(stage.id)) throw new Error(`duplicate stage id: ${stage.id}`);\n\t\tbyId.set(stage.id, stage);\n\t}\n\tconst planOwner = new Map<string, string>();\n\tfor (const stage of stages) {\n\t\tif (stage.planId === undefined) continue;\n\t\tconst owner = planOwner.get(stage.planId);\n\t\tif (owner !== undefined) {\n\t\t\tthrow new Error(\n\t\t\t\t`stage ${stage.id}: planId ${stage.planId} is already referenced by stage ${owner} ` +\n\t\t\t\t\t\"(planId uniqueness applies within a workflow; cross-workflow references are allowed)\",\n\t\t\t);\n\t\t}\n\t\tplanOwner.set(stage.planId, stage.id);\n\t}\n\tfor (const stage of stages) {\n\t\tfor (const dep of stage.dependsOn) {\n\t\t\tif (!byId.has(dep)) throw new Error(`stage ${stage.id}: dependsOn references unknown stage ${dep}`);\n\t\t}\n\t\tif (stage.onFail !== undefined) {\n\t\t\tif (!byId.has(stage.onFail)) {\n\t\t\t\tthrow new Error(`stage ${stage.id}: onFail references unknown stage ${stage.onFail}`);\n\t\t\t}\n\t\t\tif (stage.onFail === stage.id) {\n\t\t\t\tthrow new Error(`stage ${stage.id}: onFail must target a different stage`);\n\t\t\t}\n\t\t\tif (dependsOnReach(stages, stage.onFail, stage.id)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`stage ${stage.id}: onFail target ${stage.onFail} is topologically later ` +\n\t\t\t\t\t\t`(it transitively depends on ${stage.id})`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\t// DFS cycle detection over dependsOn + onFail edges (mixed cycles included).\n\tconst state = new Map<string, \"visiting\" | \"done\">();\n\tconst visit = (id: string, path: string[]): void => {\n\t\tconst mark = state.get(id);\n\t\tif (mark === \"done\") return;\n\t\tif (mark === \"visiting\") {\n\t\t\tthrow new Error(`dependency graph has a cycle: ${[...path, id].join(\" -> \")} (dependsOn/onFail edges)`);\n\t\t}\n\t\tstate.set(id, \"visiting\");\n\t\tconst spec = byId.get(id);\n\t\tif (spec !== undefined) {\n\t\t\tfor (const next of spec.dependsOn) visit(next, [...path, id]);\n\t\t\tif (spec.onFail !== undefined) visit(spec.onFail, [...path, id]);\n\t\t}\n\t\tstate.set(id, \"done\");\n\t};\n\tfor (const stage of stages) visit(stage.id, []);\n}\n\n// ---------------------------------------------------------------------------\n// Running-modification grading (§6 分级 / principle 9)\n// ---------------------------------------------------------------------------\n\n/** Fields an active/awaiting_review stage may NOT change (§6 amend list is the complement). */\nconst FROZEN_STAGE_FIELDS: readonly string[] = [\"title\", \"dependsOn\", \"kind\", \"advance\", \"retryLimit\", \"onFail\"];\n\nfunction acceptanceEqual(a: { id: string; statement: string }[], b: { id: string; statement: string }[]): boolean {\n\treturn (\n\t\ta.length === b.length &&\n\t\ta.every((item, index) => item.id === b[index].id && item.statement === b[index].statement)\n\t);\n}\n\nfunction stringArrayEqual(a: string[] | undefined, b: string[] | undefined): boolean {\n\tconst left = a ?? [];\n\tconst right = b ?? [];\n\treturn left.length === right.length && left.every((item, index) => item === right[index]);\n}\n\nfunction changedStageFields(previous: StageSpec, next: StageSpec): string[] {\n\tconst fields: string[] = [];\n\tif (previous.title !== next.title) fields.push(\"title\");\n\tif (previous.objective.statement !== next.objective.statement) fields.push(\"objective.statement\");\n\tif (!acceptanceEqual(previous.objective.acceptance, next.objective.acceptance)) fields.push(\"acceptance\");\n\tif (!stringArrayEqual(previous.dependsOn, next.dependsOn)) fields.push(\"dependsOn\");\n\tif ((previous.planId ?? \"\") !== (next.planId ?? \"\")) fields.push(\"planId\");\n\tif (!stringArrayEqual(previous.scope, next.scope)) fields.push(\"scope\");\n\tif ((previous.role ?? \"\") !== (next.role ?? \"\")) fields.push(\"role\");\n\tif (previous.kind !== next.kind) fields.push(\"kind\");\n\tif (previous.advance !== next.advance) fields.push(\"advance\");\n\tif ((previous.retryLimit ?? -1) !== (next.retryLimit ?? -1)) fields.push(\"retryLimit\");\n\tif ((previous.onFail ?? \"\") !== (next.onFail ?? \"\")) fields.push(\"onFail\");\n\treturn fields;\n}\n\n/**\n * Grades a full-submit update against the stored record: append-only stage\n * sequence (no mid-insert, reorder, id change, or removal — removal is `skip`\n * by design), pending stages freely modifiable, active/awaiting_review stages\n * amendable only within the §6 field list and only with a non-empty\n * amendNote, completed/skipped specs frozen. Throws structured errors on\n * violation; completed-wins race semantics (§6: amend vs completion\n * evaluation) fall out naturally because a completed stage is frozen.\n */\nexport function planWorkflowSpecUpdate(existing: WorkflowRecord | undefined, next: ParsedWorkflowSet): WorkflowSetDiff {\n\tif (existing === undefined) {\n\t\treturn { created: true, amendChanges: [], appendedStageIds: next.stages.map((stage) => stage.id) };\n\t}\n\tconst oldIds = existing.stages.map((stage) => stage.id);\n\tconst nextIds = next.stages.map((stage) => stage.id);\n\tfor (let index = 0; index < oldIds.length; index += 1) {\n\t\tif (nextIds[index] !== oldIds[index]) {\n\t\t\tthrow new Error(\n\t\t\t\t`stage sequence changed at position ${index} (expected ${oldIds[index]}, found ${nextIds[index] ?? \"end\"}): ` +\n\t\t\t\t\t\"stages may only be appended; inserting, reordering, changing ids, and removing stages are not allowed \" +\n\t\t\t\t\t\"(drop a stage with workflow_advance skip instead)\",\n\t\t\t);\n\t\t}\n\t}\n\tconst nextById = new Map(next.stages.map((stage) => [stage.id, stage]));\n\tconst amendChanges: StageChangePlan[] = [];\n\tfor (const previous of existing.stages) {\n\t\tconst updated = nextById.get(previous.id);\n\t\tif (updated === undefined) continue; // covered by the sequence check above\n\t\tconst runtime = existing.runtime.find((item) => item.stageId === previous.id);\n\t\tconst status = runtime?.status ?? \"pending\";\n\t\tconst fields = changedStageFields(previous, updated);\n\t\tif (fields.length === 0) continue;\n\t\tif (status === \"completed\" || status === \"skipped\") {\n\t\t\tthrow new Error(\n\t\t\t\t`stage ${previous.id} is ${status} and its spec is frozen (history must stay interpretable); ` +\n\t\t\t\t\t\"use workflow_advance retreat or append a corrective stage instead\",\n\t\t\t);\n\t\t}\n\t\tif (status === \"pending\") continue; // free modification (§6)\n\t\t// active / awaiting_review / failed: amend path (§6). `failed` is unreachable\n\t\t// in a non-terminal workflow (failure disposal resets to pending) but graded\n\t\t// as amend defensively.\n\t\tconst frozen = fields.filter((name) => FROZEN_STAGE_FIELDS.includes(name));\n\t\tif (frozen.length > 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`stage ${previous.id} is ${status}; only objective/acceptance/scope/role/planId may be amended ` +\n\t\t\t\t\t`(changed frozen fields: ${frozen.join(\", \")})`,\n\t\t\t);\n\t\t}\n\t\tconst amendNote = updated.amendNote ?? \"\";\n\t\tif (amendNote.trim() === \"\") {\n\t\t\tthrow new Error(`stage ${previous.id} is ${status} and changed; amendNote must carry the correction reason`);\n\t\t}\n\t\tconst prunedEvidence = previous.objective.acceptance\n\t\t\t.filter(\n\t\t\t\t(item) =>\n\t\t\t\t\t!updated.objective.acceptance.some((candidate) => candidate.id === item.id) &&\n\t\t\t\t\t(runtime?.evidence.some((entry) => entry.acceptanceId === item.id) ?? false),\n\t\t\t)\n\t\t\t.map((item) => item.id);\n\t\tamendChanges.push({ stageId: previous.id, fields, amendNote, prunedEvidence });\n\t}\n\treturn { created: false, amendChanges, appendedStageIds: nextIds.slice(oldIds.length) };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5D,MAAM,WAAW,iBAAiB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,SAAS,EAAE,CAAC;CACpB;AAED,0GAAyG;AACzG,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB,kGAAiG;IACjG,cAAc,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,mEAAmE;IACnE,YAAY,EAAE,eAAe,EAAE,CAAC;IAChC,6FAA4F;IAC5F,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC3B;AAMD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAG9E;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG3D;AA0FD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,iBAAiB,CAkBrE;AAMD,yFAAyF;AACzF,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAa9F;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAuD5D;AAsCD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,cAAc,GAAG,SAAS,EAAE,IAAI,EAAE,iBAAiB,GAAG,eAAe,CAuDrH","sourcesContent":["/**\n * workflow_set input parsing and structural validation (§6), including the\n * running-modification grading rules (§6 分级 / principle 9: pending is free,\n * active/awaiting_review amend with a mandatory amendNote, completed/skipped\n * are frozen history).\n *\n * Since v8 the parsed workflow-level optional fields (title/goalId/\n * maxRetreats/maxActiveStages) may be omitted on updates — the keep-stored-\n * value merge lives in applyWorkflowSet (engine.ts); creation still requires\n * a title.\n *\n * All failures are structured errors (thrown Error with a field-specific\n * message), matching the goal_set/plan_set validation style: the original\n * error always reaches the caller; nothing is silently coerced.\n */\n\nimport type { StageSpec, WorkflowRecord } from \"./types.ts\";\n\nexport interface ParsedWorkflowSet {\n\tid: string;\n\t/**\n\t * Optional since v8 (§6): on the update path an omitted title keeps the\n\t * stored value (like goalId/maxRetreats/maxActiveStages); on the create\n\t * path a title is still required (guarded in applyWorkflowSet).\n\t */\n\ttitle?: string;\n\tgoalId?: string;\n\trevision: number;\n\tmaxRetreats?: number;\n\tmaxActiveStages?: number;\n\tstages: StageSpec[];\n}\n\n/** One active/awaiting_review stage that changed spec and must leave a stage.spec-amended audit (§6). */\nexport interface StageChangePlan {\n\tstageId: string;\n\t/** Amendable field names that differ from the stored spec. */\n\tfields: string[];\n\t/** Correction reason; required non-empty on the amend path. */\n\tamendNote: string;\n\t/** Acceptance ids removed by the amend that still had evidence attached (linkage detail, §6). */\n\tprunedEvidence: string[];\n}\n\nexport interface WorkflowSetDiff {\n\tcreated: boolean;\n\t/** Amend-path changes (one stage.spec-amended transition each). */\n\tamendChanges: StageChangePlan[];\n\t/** Stage ids appended after the existing stage sequence (append-only structure ops, §6). */\n\tappendedStageIds: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Primitive parsers (goal_set/plan_set style)\n// ---------------------------------------------------------------------------\n\nexport function asObject(value: unknown, name: string): Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(`${name} must be an object`);\n\treturn value as Record<string, unknown>;\n}\n\nexport function asText(value: unknown, name: string): string {\n\tif (typeof value !== \"string\" || value.trim() === \"\") throw new Error(`${name} must be a non-empty string`);\n\treturn value;\n}\n\nfunction optionalText(value: unknown, name: string): string | undefined {\n\tif (value === undefined) return undefined;\n\treturn asText(value, name);\n}\n\nfunction intAtLeast(value: unknown, minimum: number, name: string): number {\n\tif (typeof value !== \"number\" || !Number.isInteger(value) || value < minimum) {\n\t\tthrow new Error(`${name} must be an integer >= ${minimum}`);\n\t}\n\treturn value;\n}\n\nfunction stringArray(value: unknown, name: string): string[] {\n\tif (value === undefined) return [];\n\tif (!Array.isArray(value) || value.some((item) => typeof item !== \"string\" || item.trim() === \"\")) {\n\t\tthrow new Error(`${name} must be an array of non-empty strings`);\n\t}\n\treturn [...(value as string[])];\n}\n\n// ---------------------------------------------------------------------------\n// workflow_set input parsing\n// ---------------------------------------------------------------------------\n\nfunction parseStage(raw: unknown, index: number): StageSpec {\n\tconst stage = asObject(raw, `stages[${index}]`);\n\tconst id = asText(stage.id, `stages[${index}].id`);\n\tconst field = (name: string) => `stage ${id}: ${name}`;\n\tconst title = asText(stage.title, field(\"title\"));\n\n\tconst objectiveRaw = asObject(stage.objective, field(\"objective\"));\n\tconst statement = asText(objectiveRaw.statement, field(\"objective.statement\"));\n\tlet acceptance: { id: string; statement: string }[] = [];\n\tif (objectiveRaw.acceptance !== undefined) {\n\t\tif (!Array.isArray(objectiveRaw.acceptance)) {\n\t\t\tthrow new Error(field(\"objective.acceptance must be an array\"));\n\t\t}\n\t\tacceptance = objectiveRaw.acceptance.map((item, itemIndex) => {\n\t\t\tconst entry = asObject(item, field(`objective.acceptance[${itemIndex}]`));\n\t\t\treturn {\n\t\t\t\tid: asText(entry.id, field(`objective.acceptance[${itemIndex}].id`)),\n\t\t\t\tstatement: asText(entry.statement, field(`objective.acceptance[${itemIndex}].statement`)),\n\t\t\t};\n\t\t});\n\t\tconst seen = new Set<string>();\n\t\tfor (const item of acceptance) {\n\t\t\tif (seen.has(item.id)) throw new Error(field(`duplicate acceptance id ${item.id}`));\n\t\t\tseen.add(item.id);\n\t\t}\n\t}\n\n\tlet kind: StageSpec[\"kind\"] = \"write\";\n\tif (stage.kind !== undefined) {\n\t\tif (stage.kind !== \"read\" && stage.kind !== \"write\") {\n\t\t\tthrow new Error(field('kind must be \"read\" or \"write\"'));\n\t\t}\n\t\tkind = stage.kind;\n\t}\n\tlet advance: StageSpec[\"advance\"] = \"auto\";\n\tif (stage.advance !== undefined) {\n\t\tif (stage.advance !== \"auto\" && stage.advance !== \"review\") {\n\t\t\tthrow new Error(field('advance must be \"auto\" or \"review\"'));\n\t\t}\n\t\tadvance = stage.advance;\n\t}\n\tconst scopeRaw = stringArray(stage.scope, field(\"scope\"));\n\tconst retryLimit = stage.retryLimit === undefined ? undefined : intAtLeast(stage.retryLimit, 0, field(\"retryLimit\"));\n\tconst planId = optionalText(stage.planId, field(\"planId\"));\n\tconst role = optionalText(stage.role, field(\"role\"));\n\tconst onFail = optionalText(stage.onFail, field(\"onFail\"));\n\tconst amendNote = optionalText(stage.amendNote, field(\"amendNote\"));\n\n\treturn {\n\t\tid,\n\t\ttitle,\n\t\tobjective: { statement, acceptance },\n\t\tdependsOn: stringArray(stage.dependsOn, field(\"dependsOn\")),\n\t\t...(planId !== undefined ? { planId } : {}),\n\t\tkind,\n\t\t...(scopeRaw.length > 0 ? { scope: scopeRaw } : {}),\n\t\t...(role !== undefined ? { role } : {}),\n\t\tadvance,\n\t\t...(retryLimit !== undefined ? { retryLimit } : {}),\n\t\t...(onFail !== undefined ? { onFail } : {}),\n\t\t...(amendNote !== undefined ? { amendNote } : {}),\n\t};\n}\n\nexport function parseWorkflowSetInput(raw: unknown): ParsedWorkflowSet {\n\tconst value = asObject(raw, \"workflow input\");\n\tif (!Array.isArray(value.stages) || value.stages.length === 0) {\n\t\tthrow new Error(\"stages must be a non-empty array\");\n\t}\n\tconst goalId = optionalText(value.goalId, \"goalId\");\n\tconst title = optionalText(value.title, \"title\");\n\treturn {\n\t\tid: asText(value.id, \"id\"),\n\t\t...(title !== undefined ? { title } : {}),\n\t\trevision: intAtLeast(value.revision, 0, \"revision\"),\n\t\t...(goalId !== undefined ? { goalId } : {}),\n\t\t...(value.maxRetreats === undefined ? {} : { maxRetreats: intAtLeast(value.maxRetreats, 0, \"maxRetreats\") }),\n\t\t...(value.maxActiveStages === undefined\n\t\t\t? {}\n\t\t\t: { maxActiveStages: intAtLeast(value.maxActiveStages, 1, \"maxActiveStages\") }),\n\t\tstages: value.stages.map((stage, index) => parseStage(stage, index)),\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Structural graph validation (§6 workflow_set)\n// ---------------------------------------------------------------------------\n\n/** Whether `targetId` is transitively reachable from `startId` along dependsOn edges. */\nexport function dependsOnReach(stages: StageSpec[], startId: string, targetId: string): boolean {\n\tconst byId = new Map(stages.map((stage) => [stage.id, stage]));\n\tconst visited = new Set<string>();\n\tconst queue = [startId];\n\twhile (queue.length > 0) {\n\t\tconst current = queue.pop();\n\t\tif (current === undefined || visited.has(current)) continue;\n\t\tvisited.add(current);\n\t\tif (current === targetId) return true;\n\t\tconst spec = byId.get(current);\n\t\tif (spec !== undefined) queue.push(...spec.dependsOn);\n\t}\n\treturn false;\n}\n\n/**\n * Full structural validation: stage id uniqueness, reference existence,\n * workflow-internal planId uniqueness (cross-workflow sharing is allowed),\n * onFail pointing topologically earlier, and combined dependsOn+onFail cycle\n * detection (DFS over the mixed edge set — §6 names mixed cycles explicitly).\n */\nexport function validateStageGraph(stages: StageSpec[]): void {\n\tif (stages.length === 0) throw new Error(\"stages must not be empty\");\n\tconst byId = new Map<string, StageSpec>();\n\tfor (const stage of stages) {\n\t\tif (byId.has(stage.id)) throw new Error(`duplicate stage id: ${stage.id}`);\n\t\tbyId.set(stage.id, stage);\n\t}\n\tconst planOwner = new Map<string, string>();\n\tfor (const stage of stages) {\n\t\tif (stage.planId === undefined) continue;\n\t\tconst owner = planOwner.get(stage.planId);\n\t\tif (owner !== undefined) {\n\t\t\tthrow new Error(\n\t\t\t\t`stage ${stage.id}: planId ${stage.planId} is already referenced by stage ${owner} ` +\n\t\t\t\t\t\"(planId uniqueness applies within a workflow; cross-workflow references are allowed)\",\n\t\t\t);\n\t\t}\n\t\tplanOwner.set(stage.planId, stage.id);\n\t}\n\tfor (const stage of stages) {\n\t\tfor (const dep of stage.dependsOn) {\n\t\t\tif (!byId.has(dep)) throw new Error(`stage ${stage.id}: dependsOn references unknown stage ${dep}`);\n\t\t}\n\t\tif (stage.onFail !== undefined) {\n\t\t\tif (!byId.has(stage.onFail)) {\n\t\t\t\tthrow new Error(`stage ${stage.id}: onFail references unknown stage ${stage.onFail}`);\n\t\t\t}\n\t\t\tif (stage.onFail === stage.id) {\n\t\t\t\tthrow new Error(`stage ${stage.id}: onFail must target a different stage`);\n\t\t\t}\n\t\t\tif (dependsOnReach(stages, stage.onFail, stage.id)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`stage ${stage.id}: onFail target ${stage.onFail} is topologically later ` +\n\t\t\t\t\t\t`(it transitively depends on ${stage.id})`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\t// DFS cycle detection over dependsOn + onFail edges (mixed cycles included).\n\tconst state = new Map<string, \"visiting\" | \"done\">();\n\tconst visit = (id: string, path: string[]): void => {\n\t\tconst mark = state.get(id);\n\t\tif (mark === \"done\") return;\n\t\tif (mark === \"visiting\") {\n\t\t\tthrow new Error(`dependency graph has a cycle: ${[...path, id].join(\" -> \")} (dependsOn/onFail edges)`);\n\t\t}\n\t\tstate.set(id, \"visiting\");\n\t\tconst spec = byId.get(id);\n\t\tif (spec !== undefined) {\n\t\t\tfor (const next of spec.dependsOn) visit(next, [...path, id]);\n\t\t\tif (spec.onFail !== undefined) visit(spec.onFail, [...path, id]);\n\t\t}\n\t\tstate.set(id, \"done\");\n\t};\n\tfor (const stage of stages) visit(stage.id, []);\n}\n\n// ---------------------------------------------------------------------------\n// Running-modification grading (§6 分级 / principle 9)\n// ---------------------------------------------------------------------------\n\n/** Fields an active/awaiting_review stage may NOT change (§6 amend list is the complement). */\nconst FROZEN_STAGE_FIELDS: readonly string[] = [\"title\", \"dependsOn\", \"kind\", \"advance\", \"retryLimit\", \"onFail\"];\n\nfunction acceptanceEqual(a: { id: string; statement: string }[], b: { id: string; statement: string }[]): boolean {\n\treturn (\n\t\ta.length === b.length &&\n\t\ta.every((item, index) => item.id === b[index].id && item.statement === b[index].statement)\n\t);\n}\n\nfunction stringArrayEqual(a: string[] | undefined, b: string[] | undefined): boolean {\n\tconst left = a ?? [];\n\tconst right = b ?? [];\n\treturn left.length === right.length && left.every((item, index) => item === right[index]);\n}\n\nfunction changedStageFields(previous: StageSpec, next: StageSpec): string[] {\n\tconst fields: string[] = [];\n\tif (previous.title !== next.title) fields.push(\"title\");\n\tif (previous.objective.statement !== next.objective.statement) fields.push(\"objective.statement\");\n\tif (!acceptanceEqual(previous.objective.acceptance, next.objective.acceptance)) fields.push(\"acceptance\");\n\tif (!stringArrayEqual(previous.dependsOn, next.dependsOn)) fields.push(\"dependsOn\");\n\tif ((previous.planId ?? \"\") !== (next.planId ?? \"\")) fields.push(\"planId\");\n\tif (!stringArrayEqual(previous.scope, next.scope)) fields.push(\"scope\");\n\tif ((previous.role ?? \"\") !== (next.role ?? \"\")) fields.push(\"role\");\n\tif (previous.kind !== next.kind) fields.push(\"kind\");\n\tif (previous.advance !== next.advance) fields.push(\"advance\");\n\tif ((previous.retryLimit ?? -1) !== (next.retryLimit ?? -1)) fields.push(\"retryLimit\");\n\tif ((previous.onFail ?? \"\") !== (next.onFail ?? \"\")) fields.push(\"onFail\");\n\treturn fields;\n}\n\n/**\n * Grades a full-submit update against the stored record: append-only stage\n * sequence (no mid-insert, reorder, id change, or removal — removal is `skip`\n * by design), pending stages freely modifiable, active/awaiting_review stages\n * amendable only within the §6 field list and only with a non-empty\n * amendNote, completed/skipped specs frozen. Throws structured errors on\n * violation; completed-wins race semantics (§6: amend vs completion\n * evaluation) fall out naturally because a completed stage is frozen.\n */\nexport function planWorkflowSpecUpdate(existing: WorkflowRecord | undefined, next: ParsedWorkflowSet): WorkflowSetDiff {\n\tif (existing === undefined) {\n\t\treturn { created: true, amendChanges: [], appendedStageIds: next.stages.map((stage) => stage.id) };\n\t}\n\tconst oldIds = existing.stages.map((stage) => stage.id);\n\tconst nextIds = next.stages.map((stage) => stage.id);\n\tfor (let index = 0; index < oldIds.length; index += 1) {\n\t\tif (nextIds[index] !== oldIds[index]) {\n\t\t\tthrow new Error(\n\t\t\t\t`stage sequence changed at position ${index} (expected ${oldIds[index]}, found ${nextIds[index] ?? \"end\"}): ` +\n\t\t\t\t\t\"stages may only be appended; inserting, reordering, changing ids, and removing stages are not allowed \" +\n\t\t\t\t\t\"(drop a stage with workflow_advance skip instead)\",\n\t\t\t);\n\t\t}\n\t}\n\tconst nextById = new Map(next.stages.map((stage) => [stage.id, stage]));\n\tconst amendChanges: StageChangePlan[] = [];\n\tfor (const previous of existing.stages) {\n\t\tconst updated = nextById.get(previous.id);\n\t\tif (updated === undefined) continue; // covered by the sequence check above\n\t\tconst runtime = existing.runtime.find((item) => item.stageId === previous.id);\n\t\tconst status = runtime?.status ?? \"pending\";\n\t\tconst fields = changedStageFields(previous, updated);\n\t\tif (fields.length === 0) continue;\n\t\tif (status === \"completed\" || status === \"skipped\") {\n\t\t\tthrow new Error(\n\t\t\t\t`stage ${previous.id} is ${status} and its spec is frozen (history must stay interpretable); ` +\n\t\t\t\t\t\"use workflow_advance retreat or append a corrective stage instead\",\n\t\t\t);\n\t\t}\n\t\tif (status === \"pending\") continue; // free modification (§6)\n\t\t// active / awaiting_review / failed: amend path (§6). `failed` is unreachable\n\t\t// in a non-terminal workflow (failure disposal resets to pending) but graded\n\t\t// as amend defensively.\n\t\tconst frozen = fields.filter((name) => FROZEN_STAGE_FIELDS.includes(name));\n\t\tif (frozen.length > 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`stage ${previous.id} is ${status}; only objective/acceptance/scope/role/planId may be amended ` +\n\t\t\t\t\t`(changed frozen fields: ${frozen.join(\", \")})`,\n\t\t\t);\n\t\t}\n\t\tconst amendNote = updated.amendNote ?? \"\";\n\t\tif (amendNote.trim() === \"\") {\n\t\t\tthrow new Error(`stage ${previous.id} is ${status} and changed; amendNote must carry the correction reason`);\n\t\t}\n\t\tconst prunedEvidence = previous.objective.acceptance\n\t\t\t.filter(\n\t\t\t\t(item) =>\n\t\t\t\t\t!updated.objective.acceptance.some((candidate) => candidate.id === item.id) &&\n\t\t\t\t\t(runtime?.evidence.some((entry) => entry.acceptanceId === item.id) ?? false),\n\t\t\t)\n\t\t\t.map((item) => item.id);\n\t\tamendChanges.push({ stageId: previous.id, fields, amendNote, prunedEvidence });\n\t}\n\treturn { created: false, amendChanges, appendedStageIds: nextIds.slice(oldIds.length) };\n}\n"]}
|
package/dist/validate.js
CHANGED
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
* active/awaiting_review amend with a mandatory amendNote, completed/skipped
|
|
5
5
|
* are frozen history).
|
|
6
6
|
*
|
|
7
|
+
* Since v8 the parsed workflow-level optional fields (title/goalId/
|
|
8
|
+
* maxRetreats/maxActiveStages) may be omitted on updates — the keep-stored-
|
|
9
|
+
* value merge lives in applyWorkflowSet (engine.ts); creation still requires
|
|
10
|
+
* a title.
|
|
11
|
+
*
|
|
7
12
|
* All failures are structured errors (thrown Error with a field-specific
|
|
8
13
|
* message), matching the goal_set/plan_set validation style: the original
|
|
9
14
|
* error always reaches the caller; nothing is silently coerced.
|
|
@@ -110,9 +115,10 @@ export function parseWorkflowSetInput(raw) {
|
|
|
110
115
|
throw new Error("stages must be a non-empty array");
|
|
111
116
|
}
|
|
112
117
|
const goalId = optionalText(value.goalId, "goalId");
|
|
118
|
+
const title = optionalText(value.title, "title");
|
|
113
119
|
return {
|
|
114
120
|
id: asText(value.id, "id"),
|
|
115
|
-
title
|
|
121
|
+
...(title !== undefined ? { title } : {}),
|
|
116
122
|
revision: intAtLeast(value.revision, 0, "revision"),
|
|
117
123
|
...(goalId !== undefined ? { goalId } : {}),
|
|
118
124
|
...(value.maxRetreats === undefined ? {} : { maxRetreats: intAtLeast(value.maxRetreats, 0, "maxRetreats") }),
|