@ai-agent-forge/plugin-workflow 0.88.19 → 0.88.20

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/agent-forge.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "packageFormatVersion": 1,
3
3
  "id": "agent-forge.plugin.workflow",
4
- "pluginVersion": "0.88.19",
4
+ "pluginVersion": "0.88.20",
5
5
  "apiVersion": "1",
6
6
  "minHostVersion": "0.84.4",
7
7
  "platform": {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AA2BrF,YAAY,EACX,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,UAAU,EACV,SAAS,EACT,YAAY,EACZ,SAAS,EACT,eAAe,EACf,eAAe,EACf,kBAAkB,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC/E,YAAY,EACX,YAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,aAAa,EACb,uBAAuB,EACvB,yBAAyB,GACzB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAoa7E,wBAAgB,gBAAgB,CAC/B,GAAG,EAAE,aAAa,GAChB,OAAO,CAAC,SAAS,sBAAsB,EAAE,CAAC,GAAG,SAAS,sBAAsB,EAAE,CA0MhF","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 { createWorkflowToolResultRenderer, 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\";\n/**\n * Session protocol key of the subagent-delegate plugin's session role snapshot\n * (plugins/subagent-delegate, D-081 item 7: `{ version: 1, roles: [{ id, ... }] }`\n * append-only full snapshots). Same literal-coupling precedent as plan/goal\n * above: the workflow plugin never imports the owning plugin.\n */\nconst subagentRoleStateEntry = \"subagent.roles.state\";\n/**\n * Role id shape: the same expression as the authoritative reader's\n * ROLE_ID_PATTERN (plugins/subagent-delegate `readSessionRoles`). Same\n * cross-plugin literal-coupling precedent as the entry keys above — the\n * workflow plugin never imports the owning plugin. The residual difference is\n * field-level only: subagent-delegate validates the whole role record and drops\n * invalid entries, while this side reads the id alone — so the divergence can\n * only under-warn, never false-warn.\n */\nconst roleIdPattern = /^[a-z0-9][a-z0-9_-]{0,31}$/;\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. When the user explicitly asks for workflow orchestration, still run this weighing: if the task genuinely misses the bar, skipping is fine — but say so in one line why you stayed on goal/plan/todo (an unexplained skip reads as ignoring the request); conversely, do not build one just because it was asked when the task is small (over-orchestration costs more than it saves).\";\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(\n\t\tType.String({\n\t\t\tdescription:\n\t\t\t\t\"Soft reference to a plan id; missing = pure checkpoint stage. One plan can back at most one stage in a workflow (unique within the workflow; cross-workflow reuse is allowed)\",\n\t\t}),\n\t),\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:\n\t\t\t\t\"Correction reason; required when an active/awaiting_review stage's spec changes. Only objective/acceptance/scope/role/planId are amendable in place — title, dependsOn, kind, advance, retryLimit and onFail are frozen once a stage leaves pending\",\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:\n\t\t\t\t\"Human-readable workflow title. Required when creating a new workflow; on update, omitting it 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 8. Omitting on update keeps the stored value\",\n\t\t\tminimum: 1,\n\t\t}),\n\t),\n\tstages: Type.Array(stageSchema, {\n\t\tminItems: 1,\n\t\tdescription:\n\t\t\t\"Full stage list (whole submit, not a patch). Existing stages must keep their stored order and ids — appending at the end is the only structural change allowed; inserting, reordering, renaming and removing stages are rejected (drop a stage with workflow_advance skip instead). Completed and skipped stage specs are frozen; a completed, failed or cancelled workflow cannot be updated at all\",\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{\n\t\t\tdescription:\n\t\t\t\t\"Explicit action to perform. Prerequisites: start requires a draft workflow; inspect is accepted on any status; skip and cancel also work on a draft. All other actions require a running workflow. record-evidence and complete require non-empty `evidence`; record-evidence applies only to stages that declare acceptance items (lower-bound stages take the plan's completion evidence); approve/reject require an awaiting_review stage; retreat requires a previously activated stage; complete applies only to checkpoint stages without planId; skip applies only to pending stages; cancel cancels the WHOLE workflow and takes no stageId\",\n\t\t},\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; required by every action except start, inspect and cancel (cancel is workflow-wide and takes no stageId)\",\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. Only record-evidence records it; other actions drop it\",\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{\n\t\t\t\tdescription:\n\t\t\t\t\t\"Evidence items for record-evidence/approve/complete. record-evidence applies only to stages that declare acceptance items (lower-bound stages take the plan's completion evidence). record-evidence and complete require at least one item; when the stage declares acceptance items, every item must carry an acceptanceId that exists in the current spec, and complete must cover all of them\",\n\t\t\t},\n\t\t),\n\t),\n\tnote: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Optional note recorded in the transition detail (approve/reject/retreat/skip/cancel)\",\n\t\t}),\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/**\n * Role ids from the current branch's latest READABLE `subagent.roles.state`\n * snapshot (D-081 item 7). Fallback is symmetric with the authoritative reader\n * (subagent-delegate `readSessionRoles`): a snapshot-level corruption (data not\n * an object / version mismatch / roles not an array) steps back to the previous\n * readable snapshot, and only a fully unreadable table degrades to the empty\n * set. Individual malformed role records are skipped — including ids that do\n * not match `roleIdPattern` — keeping the remaining ids of an otherwise\n * readable snapshot. Silent by contract: the\n * subagent-delegate plugin owns the degradation warning on its side, and a\n * second report here would double-warn for the same fact — this side only\n * tolerates.\n */\nfunction loadSessionRoleIds(api: CapabilityAPI): Set<string> {\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 !== subagentRoleStateEntry) continue;\n\t\tconst data = entry.data;\n\t\tif (!data || typeof data !== \"object\" || Array.isArray(data)) continue;\n\t\tconst snapshot = data as { version?: unknown; roles?: unknown };\n\t\tif (snapshot.version !== 1 || !Array.isArray(snapshot.roles)) continue;\n\t\tconst known = new Set<string>();\n\t\tfor (const role of snapshot.roles) {\n\t\t\tif (!role || typeof role !== \"object\" || Array.isArray(role)) continue;\n\t\t\tconst id = (role as { id?: unknown }).id;\n\t\t\tif (typeof id === \"string\" && roleIdPattern.test(id)) known.add(id);\n\t\t}\n\t\treturn known;\n\t}\n\treturn new Set();\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\t// Two verifiable role sources (D-081 item 7): the host's suite role\n\t// associations (disk roles) plus this branch's session role table. A host\n\t// without the listing AND an empty session table verifies nothing, so the\n\t// advice stays unverified — no warning (缺面不告警). An explicitly empty\n\t// association face ([]) still warns for every role.\n\tconst associated = api.host?.roleAssociations;\n\tconst sessionRoleIds = roles.length > 0 ? loadSessionRoleIds(api) : new Set<string>();\n\tconst merged = new Set([...(associated ?? []), ...sessionRoleIds]);\n\tfor (const item of roles) {\n\t\tif ((associated !== undefined || sessionRoleIds.size > 0) && !merged.has(item.role)) {\n\t\t\twarnings.push(\n\t\t\t\t`stage ${item.stageId}: role \"${item.role}\" is neither associated with the active suite nor ` +\n\t\t\t\t\t\"registered in this session; delegation advice treated as unspecified — register it with \" +\n\t\t\t\t\t'subagent_role (type \"set\") or add it to the suite\\'s roles associations',\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\t// Shared structural renderResult (render.ts): the host TUI gets the\n\t// panorama face for both tools' JSON-serialized responses.\n\tconst toolResultRenderer = createWorkflowToolResultRenderer(deps);\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. Creating a workflow requires `title`; on update, an omitted optional field (title/goalId/maxRetreats/maxActiveStages) keeps its stored value. Stages are always submitted in full\",\n\t\tparameters: workflowSetSchema,\n\t\trenderResult: toolResultRenderer,\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. Every action except start, inspect and cancel needs stageId; record-evidence and complete need non-empty evidence, and complete requires an active checkpoint stage with no planId; skip applies only to pending stages; cancel cancels the whole workflow\",\n\t\tparameters: workflowAdvanceSchema,\n\t\trenderResult: toolResultRenderer,\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.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AA2BrF,YAAY,EACX,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,UAAU,EACV,SAAS,EACT,YAAY,EACZ,SAAS,EACT,eAAe,EACf,eAAe,EACf,kBAAkB,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC/E,YAAY,EACX,YAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,aAAa,EACb,uBAAuB,EACvB,yBAAyB,GACzB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAoa7E,wBAAgB,gBAAgB,CAC/B,GAAG,EAAE,aAAa,GAChB,OAAO,CAAC,SAAS,sBAAsB,EAAE,CAAC,GAAG,SAAS,sBAAsB,EAAE,CA0MhF","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 { createWorkflowToolResultRenderer, 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\";\n/**\n * Session protocol key of the subagent-delegate plugin's session role snapshot\n * (plugins/subagent-delegate, D-081 item 7: `{ version: 1, roles: [{ id, ... }] }`\n * append-only full snapshots). Same literal-coupling precedent as plan/goal\n * above: the workflow plugin never imports the owning plugin.\n */\nconst subagentRoleStateEntry = \"subagent.roles.state\";\n/**\n * Role id shape: the same expression as the authoritative reader's\n * ROLE_ID_PATTERN (plugins/subagent-delegate `readSessionRoles`). Same\n * cross-plugin literal-coupling precedent as the entry keys above — the\n * workflow plugin never imports the owning plugin. The residual difference is\n * field-level only: subagent-delegate validates the whole role record and drops\n * invalid entries, while this side reads the id alone — so the divergence can\n * only under-warn, never false-warn.\n */\nconst roleIdPattern = /^[a-z0-9][a-z0-9_-]{0,31}$/;\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. When the user explicitly asks for workflow orchestration, still run this weighing: if the task genuinely misses the bar, say so in one line why you stayed on goal/plan/todo (an unexplained skip reads as ignoring the request); do not build one just because it was asked when the task is small (over-orchestration costs more than it saves).\";\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(\n\t\tType.String({\n\t\t\tdescription:\n\t\t\t\t\"Soft reference to a plan id; missing = pure checkpoint stage. One plan can back at most one stage in a workflow (unique within the workflow; cross-workflow reuse is allowed)\",\n\t\t}),\n\t),\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:\n\t\t\t\t\"Correction reason; required when an active/awaiting_review stage's spec changes. Only objective/acceptance/scope/role/planId are amendable in place — title, dependsOn, kind, advance, retryLimit and onFail are frozen once a stage leaves pending\",\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:\n\t\t\t\t\"Human-readable workflow title. Required when creating a new workflow; on update, omitting it 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 8. Omitting on update keeps the stored value\",\n\t\t\tminimum: 1,\n\t\t}),\n\t),\n\tstages: Type.Array(stageSchema, {\n\t\tminItems: 1,\n\t\tdescription:\n\t\t\t\"Full stage list (whole submit, not a patch). Existing stages must keep their stored order and ids — appending at the end is the only structural change allowed; inserting, reordering, renaming and removing stages are rejected (drop a stage with workflow_advance skip instead). Completed and skipped stage specs are frozen; a completed, failed or cancelled workflow cannot be updated at all\",\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{\n\t\t\tdescription:\n\t\t\t\t\"Explicit action to perform. Prerequisites: start requires a draft workflow; inspect is accepted on any status; skip and cancel also work on a draft. All other actions require a running workflow. record-evidence and complete require non-empty `evidence`; record-evidence applies only to stages that declare acceptance items (lower-bound stages take the plan's completion evidence); approve/reject require an awaiting_review stage; retreat requires a previously activated stage; complete applies only to checkpoint stages without planId; skip applies only to pending stages; cancel cancels the WHOLE workflow and takes no stageId\",\n\t\t},\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; required by every action except start, inspect and cancel (cancel is workflow-wide and takes no stageId)\",\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. Only record-evidence records it; other actions drop it\",\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{\n\t\t\t\tdescription:\n\t\t\t\t\t\"Evidence items for record-evidence/approve/complete. record-evidence applies only to stages that declare acceptance items (lower-bound stages take the plan's completion evidence). record-evidence and complete require at least one item; when the stage declares acceptance items, every item must carry an acceptanceId that exists in the current spec, and complete must cover all of them\",\n\t\t\t},\n\t\t),\n\t),\n\tnote: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Optional note recorded in the transition detail (approve/reject/retreat/skip/cancel)\",\n\t\t}),\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/**\n * Role ids from the current branch's latest READABLE `subagent.roles.state`\n * snapshot (D-081 item 7). Fallback is symmetric with the authoritative reader\n * (subagent-delegate `readSessionRoles`): a snapshot-level corruption (data not\n * an object / version mismatch / roles not an array) steps back to the previous\n * readable snapshot, and only a fully unreadable table degrades to the empty\n * set. Individual malformed role records are skipped — including ids that do\n * not match `roleIdPattern` — keeping the remaining ids of an otherwise\n * readable snapshot. Silent by contract: the\n * subagent-delegate plugin owns the degradation warning on its side, and a\n * second report here would double-warn for the same fact — this side only\n * tolerates.\n */\nfunction loadSessionRoleIds(api: CapabilityAPI): Set<string> {\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 !== subagentRoleStateEntry) continue;\n\t\tconst data = entry.data;\n\t\tif (!data || typeof data !== \"object\" || Array.isArray(data)) continue;\n\t\tconst snapshot = data as { version?: unknown; roles?: unknown };\n\t\tif (snapshot.version !== 1 || !Array.isArray(snapshot.roles)) continue;\n\t\tconst known = new Set<string>();\n\t\tfor (const role of snapshot.roles) {\n\t\t\tif (!role || typeof role !== \"object\" || Array.isArray(role)) continue;\n\t\t\tconst id = (role as { id?: unknown }).id;\n\t\t\tif (typeof id === \"string\" && roleIdPattern.test(id)) known.add(id);\n\t\t}\n\t\treturn known;\n\t}\n\treturn new Set();\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\t// Two verifiable role sources (D-081 item 7): the host's suite role\n\t// associations (disk roles) plus this branch's session role table. A host\n\t// without the listing AND an empty session table verifies nothing, so the\n\t// advice stays unverified — no warning (缺面不告警). An explicitly empty\n\t// association face ([]) still warns for every role.\n\tconst associated = api.host?.roleAssociations;\n\tconst sessionRoleIds = roles.length > 0 ? loadSessionRoleIds(api) : new Set<string>();\n\tconst merged = new Set([...(associated ?? []), ...sessionRoleIds]);\n\tfor (const item of roles) {\n\t\tif ((associated !== undefined || sessionRoleIds.size > 0) && !merged.has(item.role)) {\n\t\t\twarnings.push(\n\t\t\t\t`stage ${item.stageId}: role \"${item.role}\" is neither associated with the active suite nor ` +\n\t\t\t\t\t\"registered in this session; delegation advice treated as unspecified — register it with \" +\n\t\t\t\t\t'subagent_role (type \"set\") or add it to the suite\\'s roles associations',\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\t// Shared structural renderResult (render.ts): the host TUI gets the\n\t// panorama face for both tools' JSON-serialized responses.\n\tconst toolResultRenderer = createWorkflowToolResultRenderer(deps);\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. Creating a workflow requires `title`; on update, an omitted optional field (title/goalId/maxRetreats/maxActiveStages) keeps its stored value. Stages are always submitted in full\",\n\t\tparameters: workflowSetSchema,\n\t\trenderResult: toolResultRenderer,\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. Every action except start, inspect and cancel needs stageId; record-evidence and complete need non-empty evidence, and complete requires an active checkpoint stage with no planId; skip applies only to pending stages; cancel cancels the whole workflow\",\n\t\tparameters: workflowAdvanceSchema,\n\t\trenderResult: toolResultRenderer,\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/index.js CHANGED
@@ -49,7 +49,7 @@ const subagentRoleStateEntry = "subagent.roles.state";
49
49
  const roleIdPattern = /^[a-z0-9][a-z0-9_-]{0,31}$/;
50
50
  const DIAGNOSTICS_CAP = 50;
51
51
  /** §3.1 applicability, verbatim scope (when to use / not to use a workflow). */
52
- const WORKFLOW_APPLICABILITY_GUIDE = "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. When the user explicitly asks for workflow orchestration, still run this weighing: if the task genuinely misses the bar, skipping is fine — but say so in one line why you stayed on goal/plan/todo (an unexplained skip reads as ignoring the request); conversely, do not build one just because it was asked when the task is small (over-orchestration costs more than it saves).";
52
+ const WORKFLOW_APPLICABILITY_GUIDE = "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. When the user explicitly asks for workflow orchestration, still run this weighing: if the task genuinely misses the bar, say so in one line why you stayed on goal/plan/todo (an unexplained skip reads as ignoring the request); do not build one just because it was asked when the task is small (over-orchestration costs more than it saves).";
53
53
  const WORKFLOW_AUTHORING_GUIDE = "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.";
54
54
  const WORKFLOW_EXECUTION_GUIDE = "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.";
55
55
  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.";
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 { createWorkflowToolResultRenderer, 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\";\n/**\n * Session protocol key of the subagent-delegate plugin's session role snapshot\n * (plugins/subagent-delegate, D-081 item 7: `{ version: 1, roles: [{ id, ... }] }`\n * append-only full snapshots). Same literal-coupling precedent as plan/goal\n * above: the workflow plugin never imports the owning plugin.\n */\nconst subagentRoleStateEntry = \"subagent.roles.state\";\n/**\n * Role id shape: the same expression as the authoritative reader's\n * ROLE_ID_PATTERN (plugins/subagent-delegate `readSessionRoles`). Same\n * cross-plugin literal-coupling precedent as the entry keys above — the\n * workflow plugin never imports the owning plugin. The residual difference is\n * field-level only: subagent-delegate validates the whole role record and drops\n * invalid entries, while this side reads the id alone — so the divergence can\n * only under-warn, never false-warn.\n */\nconst roleIdPattern = /^[a-z0-9][a-z0-9_-]{0,31}$/;\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. When the user explicitly asks for workflow orchestration, still run this weighing: if the task genuinely misses the bar, skipping is fine — but say so in one line why you stayed on goal/plan/todo (an unexplained skip reads as ignoring the request); conversely, do not build one just because it was asked when the task is small (over-orchestration costs more than it saves).\";\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(\n\t\tType.String({\n\t\t\tdescription:\n\t\t\t\t\"Soft reference to a plan id; missing = pure checkpoint stage. One plan can back at most one stage in a workflow (unique within the workflow; cross-workflow reuse is allowed)\",\n\t\t}),\n\t),\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:\n\t\t\t\t\"Correction reason; required when an active/awaiting_review stage's spec changes. Only objective/acceptance/scope/role/planId are amendable in place — title, dependsOn, kind, advance, retryLimit and onFail are frozen once a stage leaves pending\",\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:\n\t\t\t\t\"Human-readable workflow title. Required when creating a new workflow; on update, omitting it 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 8. Omitting on update keeps the stored value\",\n\t\t\tminimum: 1,\n\t\t}),\n\t),\n\tstages: Type.Array(stageSchema, {\n\t\tminItems: 1,\n\t\tdescription:\n\t\t\t\"Full stage list (whole submit, not a patch). Existing stages must keep their stored order and ids — appending at the end is the only structural change allowed; inserting, reordering, renaming and removing stages are rejected (drop a stage with workflow_advance skip instead). Completed and skipped stage specs are frozen; a completed, failed or cancelled workflow cannot be updated at all\",\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{\n\t\t\tdescription:\n\t\t\t\t\"Explicit action to perform. Prerequisites: start requires a draft workflow; inspect is accepted on any status; skip and cancel also work on a draft. All other actions require a running workflow. record-evidence and complete require non-empty `evidence`; record-evidence applies only to stages that declare acceptance items (lower-bound stages take the plan's completion evidence); approve/reject require an awaiting_review stage; retreat requires a previously activated stage; complete applies only to checkpoint stages without planId; skip applies only to pending stages; cancel cancels the WHOLE workflow and takes no stageId\",\n\t\t},\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; required by every action except start, inspect and cancel (cancel is workflow-wide and takes no stageId)\",\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. Only record-evidence records it; other actions drop it\",\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{\n\t\t\t\tdescription:\n\t\t\t\t\t\"Evidence items for record-evidence/approve/complete. record-evidence applies only to stages that declare acceptance items (lower-bound stages take the plan's completion evidence). record-evidence and complete require at least one item; when the stage declares acceptance items, every item must carry an acceptanceId that exists in the current spec, and complete must cover all of them\",\n\t\t\t},\n\t\t),\n\t),\n\tnote: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Optional note recorded in the transition detail (approve/reject/retreat/skip/cancel)\",\n\t\t}),\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/**\n * Role ids from the current branch's latest READABLE `subagent.roles.state`\n * snapshot (D-081 item 7). Fallback is symmetric with the authoritative reader\n * (subagent-delegate `readSessionRoles`): a snapshot-level corruption (data not\n * an object / version mismatch / roles not an array) steps back to the previous\n * readable snapshot, and only a fully unreadable table degrades to the empty\n * set. Individual malformed role records are skipped — including ids that do\n * not match `roleIdPattern` — keeping the remaining ids of an otherwise\n * readable snapshot. Silent by contract: the\n * subagent-delegate plugin owns the degradation warning on its side, and a\n * second report here would double-warn for the same fact — this side only\n * tolerates.\n */\nfunction loadSessionRoleIds(api: CapabilityAPI): Set<string> {\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 !== subagentRoleStateEntry) continue;\n\t\tconst data = entry.data;\n\t\tif (!data || typeof data !== \"object\" || Array.isArray(data)) continue;\n\t\tconst snapshot = data as { version?: unknown; roles?: unknown };\n\t\tif (snapshot.version !== 1 || !Array.isArray(snapshot.roles)) continue;\n\t\tconst known = new Set<string>();\n\t\tfor (const role of snapshot.roles) {\n\t\t\tif (!role || typeof role !== \"object\" || Array.isArray(role)) continue;\n\t\t\tconst id = (role as { id?: unknown }).id;\n\t\t\tif (typeof id === \"string\" && roleIdPattern.test(id)) known.add(id);\n\t\t}\n\t\treturn known;\n\t}\n\treturn new Set();\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\t// Two verifiable role sources (D-081 item 7): the host's suite role\n\t// associations (disk roles) plus this branch's session role table. A host\n\t// without the listing AND an empty session table verifies nothing, so the\n\t// advice stays unverified — no warning (缺面不告警). An explicitly empty\n\t// association face ([]) still warns for every role.\n\tconst associated = api.host?.roleAssociations;\n\tconst sessionRoleIds = roles.length > 0 ? loadSessionRoleIds(api) : new Set<string>();\n\tconst merged = new Set([...(associated ?? []), ...sessionRoleIds]);\n\tfor (const item of roles) {\n\t\tif ((associated !== undefined || sessionRoleIds.size > 0) && !merged.has(item.role)) {\n\t\t\twarnings.push(\n\t\t\t\t`stage ${item.stageId}: role \"${item.role}\" is neither associated with the active suite nor ` +\n\t\t\t\t\t\"registered in this session; delegation advice treated as unspecified — register it with \" +\n\t\t\t\t\t'subagent_role (type \"set\") or add it to the suite\\'s roles associations',\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\t// Shared structural renderResult (render.ts): the host TUI gets the\n\t// panorama face for both tools' JSON-serialized responses.\n\tconst toolResultRenderer = createWorkflowToolResultRenderer(deps);\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. Creating a workflow requires `title`; on update, an omitted optional field (title/goalId/maxRetreats/maxActiveStages) keeps its stored value. Stages are always submitted in full\",\n\t\tparameters: workflowSetSchema,\n\t\trenderResult: toolResultRenderer,\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. Every action except start, inspect and cancel needs stageId; record-evidence and complete need non-empty evidence, and complete requires an active checkpoint stage with no planId; skip applies only to pending stages; cancel cancels the whole workflow\",\n\t\tparameters: workflowAdvanceSchema,\n\t\trenderResult: toolResultRenderer,\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 { createWorkflowToolResultRenderer, 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\";\n/**\n * Session protocol key of the subagent-delegate plugin's session role snapshot\n * (plugins/subagent-delegate, D-081 item 7: `{ version: 1, roles: [{ id, ... }] }`\n * append-only full snapshots). Same literal-coupling precedent as plan/goal\n * above: the workflow plugin never imports the owning plugin.\n */\nconst subagentRoleStateEntry = \"subagent.roles.state\";\n/**\n * Role id shape: the same expression as the authoritative reader's\n * ROLE_ID_PATTERN (plugins/subagent-delegate `readSessionRoles`). Same\n * cross-plugin literal-coupling precedent as the entry keys above — the\n * workflow plugin never imports the owning plugin. The residual difference is\n * field-level only: subagent-delegate validates the whole role record and drops\n * invalid entries, while this side reads the id alone — so the divergence can\n * only under-warn, never false-warn.\n */\nconst roleIdPattern = /^[a-z0-9][a-z0-9_-]{0,31}$/;\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. When the user explicitly asks for workflow orchestration, still run this weighing: if the task genuinely misses the bar, say so in one line why you stayed on goal/plan/todo (an unexplained skip reads as ignoring the request); do not build one just because it was asked when the task is small (over-orchestration costs more than it saves).\";\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(\n\t\tType.String({\n\t\t\tdescription:\n\t\t\t\t\"Soft reference to a plan id; missing = pure checkpoint stage. One plan can back at most one stage in a workflow (unique within the workflow; cross-workflow reuse is allowed)\",\n\t\t}),\n\t),\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:\n\t\t\t\t\"Correction reason; required when an active/awaiting_review stage's spec changes. Only objective/acceptance/scope/role/planId are amendable in place — title, dependsOn, kind, advance, retryLimit and onFail are frozen once a stage leaves pending\",\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:\n\t\t\t\t\"Human-readable workflow title. Required when creating a new workflow; on update, omitting it 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 8. Omitting on update keeps the stored value\",\n\t\t\tminimum: 1,\n\t\t}),\n\t),\n\tstages: Type.Array(stageSchema, {\n\t\tminItems: 1,\n\t\tdescription:\n\t\t\t\"Full stage list (whole submit, not a patch). Existing stages must keep their stored order and ids — appending at the end is the only structural change allowed; inserting, reordering, renaming and removing stages are rejected (drop a stage with workflow_advance skip instead). Completed and skipped stage specs are frozen; a completed, failed or cancelled workflow cannot be updated at all\",\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{\n\t\t\tdescription:\n\t\t\t\t\"Explicit action to perform. Prerequisites: start requires a draft workflow; inspect is accepted on any status; skip and cancel also work on a draft. All other actions require a running workflow. record-evidence and complete require non-empty `evidence`; record-evidence applies only to stages that declare acceptance items (lower-bound stages take the plan's completion evidence); approve/reject require an awaiting_review stage; retreat requires a previously activated stage; complete applies only to checkpoint stages without planId; skip applies only to pending stages; cancel cancels the WHOLE workflow and takes no stageId\",\n\t\t},\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; required by every action except start, inspect and cancel (cancel is workflow-wide and takes no stageId)\",\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. Only record-evidence records it; other actions drop it\",\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{\n\t\t\t\tdescription:\n\t\t\t\t\t\"Evidence items for record-evidence/approve/complete. record-evidence applies only to stages that declare acceptance items (lower-bound stages take the plan's completion evidence). record-evidence and complete require at least one item; when the stage declares acceptance items, every item must carry an acceptanceId that exists in the current spec, and complete must cover all of them\",\n\t\t\t},\n\t\t),\n\t),\n\tnote: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Optional note recorded in the transition detail (approve/reject/retreat/skip/cancel)\",\n\t\t}),\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/**\n * Role ids from the current branch's latest READABLE `subagent.roles.state`\n * snapshot (D-081 item 7). Fallback is symmetric with the authoritative reader\n * (subagent-delegate `readSessionRoles`): a snapshot-level corruption (data not\n * an object / version mismatch / roles not an array) steps back to the previous\n * readable snapshot, and only a fully unreadable table degrades to the empty\n * set. Individual malformed role records are skipped — including ids that do\n * not match `roleIdPattern` — keeping the remaining ids of an otherwise\n * readable snapshot. Silent by contract: the\n * subagent-delegate plugin owns the degradation warning on its side, and a\n * second report here would double-warn for the same fact — this side only\n * tolerates.\n */\nfunction loadSessionRoleIds(api: CapabilityAPI): Set<string> {\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 !== subagentRoleStateEntry) continue;\n\t\tconst data = entry.data;\n\t\tif (!data || typeof data !== \"object\" || Array.isArray(data)) continue;\n\t\tconst snapshot = data as { version?: unknown; roles?: unknown };\n\t\tif (snapshot.version !== 1 || !Array.isArray(snapshot.roles)) continue;\n\t\tconst known = new Set<string>();\n\t\tfor (const role of snapshot.roles) {\n\t\t\tif (!role || typeof role !== \"object\" || Array.isArray(role)) continue;\n\t\t\tconst id = (role as { id?: unknown }).id;\n\t\t\tif (typeof id === \"string\" && roleIdPattern.test(id)) known.add(id);\n\t\t}\n\t\treturn known;\n\t}\n\treturn new Set();\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\t// Two verifiable role sources (D-081 item 7): the host's suite role\n\t// associations (disk roles) plus this branch's session role table. A host\n\t// without the listing AND an empty session table verifies nothing, so the\n\t// advice stays unverified — no warning (缺面不告警). An explicitly empty\n\t// association face ([]) still warns for every role.\n\tconst associated = api.host?.roleAssociations;\n\tconst sessionRoleIds = roles.length > 0 ? loadSessionRoleIds(api) : new Set<string>();\n\tconst merged = new Set([...(associated ?? []), ...sessionRoleIds]);\n\tfor (const item of roles) {\n\t\tif ((associated !== undefined || sessionRoleIds.size > 0) && !merged.has(item.role)) {\n\t\t\twarnings.push(\n\t\t\t\t`stage ${item.stageId}: role \"${item.role}\" is neither associated with the active suite nor ` +\n\t\t\t\t\t\"registered in this session; delegation advice treated as unspecified — register it with \" +\n\t\t\t\t\t'subagent_role (type \"set\") or add it to the suite\\'s roles associations',\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\t// Shared structural renderResult (render.ts): the host TUI gets the\n\t// panorama face for both tools' JSON-serialized responses.\n\tconst toolResultRenderer = createWorkflowToolResultRenderer(deps);\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. Creating a workflow requires `title`; on update, an omitted optional field (title/goalId/maxRetreats/maxActiveStages) keeps its stored value. Stages are always submitted in full\",\n\t\tparameters: workflowSetSchema,\n\t\trenderResult: toolResultRenderer,\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. Every action except start, inspect and cancel needs stageId; record-evidence and complete need non-empty evidence, and complete requires an active checkpoint stage with no planId; skip applies only to pending stages; cancel cancels the whole workflow\",\n\t\tparameters: workflowAdvanceSchema,\n\t\trenderResult: toolResultRenderer,\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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-agent-forge/plugin-workflow",
3
- "version": "0.88.19",
3
+ "version": "0.88.20",
4
4
  "description": "Workflow orchestration capability plugin for Agent Forge (stage DAG state machine over session entries)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -45,7 +45,7 @@
45
45
  },
46
46
  "dependencies": {
47
47
  "typebox": "1.3.27",
48
- "@ai-agent-forge/plugin-sdk": "^0.88.19"
48
+ "@ai-agent-forge/plugin-sdk": "^0.88.20"
49
49
  },
50
50
  "devDependencies": {
51
51
  "shx": "0.3.4",
package/plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "agent-forge.plugin.workflow",
3
- "version": "0.88.19",
3
+ "version": "0.88.20",
4
4
  "apiVersion": "1-draft",
5
5
  "entry": "./dist/entry.js",
6
6
  "hostVersion": ">=0.84.4",