opencode-plugin-flow 5.0.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -12,6 +12,7 @@ import {
12
12
  } from "node:fs/promises";
13
13
  import { homedir } from "node:os";
14
14
  import { isAbsolute, join, normalize, sep } from "node:path";
15
+ import { setTimeout as sleep } from "node:timers/promises";
15
16
 
16
17
  // src/guidance/ids.ts
17
18
  var FLOW_GUIDANCE_TOPICS = [
@@ -29,6 +30,8 @@ var FLOW_GUIDANCE_TOPICS = [
29
30
  var LEGACY_MARKER = ".flow-skill-version";
30
31
  var NO_FOLLOW = constants.O_NOFOLLOW ?? 0;
31
32
  var SUPPORTED_LEGACY_MAJOR = "4";
33
+ var POST_MOVE_VERIFICATION_ATTEMPTS = 4;
34
+ var POST_MOVE_VERIFICATION_RETRY_MS = 25;
32
35
  var SEMVER_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
33
36
  function configuredHome() {
34
37
  return process.env.HOME?.trim() || process.env.USERPROFILE?.trim() || homedir();
@@ -226,6 +229,14 @@ async function ensureRealArchiveRoot(path) {
226
229
  }
227
230
  }
228
231
  }
232
+ async function verifyMovedLegacyFolder(name, archivePath) {
233
+ let verified = await inspectLegacyFolder(name, archivePath);
234
+ for (let attempt = 1;attempt < POST_MOVE_VERIFICATION_ATTEMPTS && verified.status !== "eligible"; attempt += 1) {
235
+ await sleep(POST_MOVE_VERIFICATION_RETRY_MS * attempt);
236
+ verified = await inspectLegacyFolder(name, archivePath);
237
+ }
238
+ return verified;
239
+ }
229
240
  async function cleanupLegacySkills(options) {
230
241
  const home = options?.home ?? configuredHome();
231
242
  const root = resolveLegacySkillsRoot(home);
@@ -259,7 +270,7 @@ async function cleanupLegacySkills(options) {
259
270
  continue;
260
271
  }
261
272
  await options?.afterQuarantine?.({ name, path, archivePath });
262
- const verified = await inspectLegacyFolder(name, archivePath);
273
+ const verified = await verifyMovedLegacyFolder(name, archivePath);
263
274
  if (verified.status !== "eligible") {
264
275
  results.push({
265
276
  name,
@@ -374,4 +385,4 @@ main(process.argv).catch((error) => {
374
385
  process.exitCode = 1;
375
386
  });
376
387
 
377
- //# debugId=690F8C77CD4F802F64756E2164756E21
388
+ //# debugId=4B60DFA5FC84470464756E2164756E21
package/dist/cli.js.map CHANGED
@@ -2,12 +2,12 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/distribution/legacy-cleanup.ts", "../src/guidance/ids.ts", "../src/version.ts", "../src/cli.ts"],
4
4
  "sourcesContent": [
5
- "import { createHash } from \"node:crypto\";\nimport { constants } from \"node:fs\";\nimport {\n\ttype FileHandle,\n\tlstat,\n\tmkdir,\n\topen,\n\treaddir,\n\trename,\n} from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { isAbsolute, join, normalize, sep } from \"node:path\";\nimport { FLOW_GUIDANCE_TOPICS } from \"../guidance/ids.js\";\n\nconst LEGACY_MARKER = \".flow-skill-version\";\nconst NO_FOLLOW = constants.O_NOFOLLOW ?? 0;\nconst SUPPORTED_LEGACY_MAJOR = \"4\";\nconst SEMVER_PATTERN =\n\t/^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-(?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*))*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$/;\n\ntype ParsedMarker = {\n\tversion: string;\n\tfiles: Map<string, string>;\n};\n\nexport type LegacySkillCleanupResult = {\n\tname: string;\n\tpath: string;\n\tstatus: \"absent\" | \"eligible\" | \"archived\" | \"refused\" | \"quarantined\";\n\treason?: string;\n\tarchivePath?: string;\n};\n\nexport type LegacyCleanupReport = {\n\tmode: \"dry-run\" | \"apply\";\n\troot: string;\n\tarchiveRoot: string;\n\tresults: LegacySkillCleanupResult[];\n};\n\nfunction configuredHome(): string {\n\treturn (\n\t\tprocess.env.HOME?.trim() || process.env.USERPROFILE?.trim() || homedir()\n\t);\n}\n\nexport function resolveLegacySkillsRoot(home = configuredHome()): string {\n\treturn join(home, \".config\", \"opencode\", \"skills\");\n}\n\nexport function resolveLegacyArchiveRoot(home = configuredHome()): string {\n\treturn join(home, \".config\", \"opencode\", \"flow-legacy-skills\");\n}\n\nfunction sha256(content: string): string {\n\treturn createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\nfunction safeLegacyPath(folder: string, relativePath: string): string {\n\tif (\n\t\t!relativePath ||\n\t\tisAbsolute(relativePath) ||\n\t\trelativePath.includes(\"\\\\\") ||\n\t\trelativePath\n\t\t\t.split(\"/\")\n\t\t\t.some((part) => !part || part === \".\" || part === \"..\")\n\t) {\n\t\tthrow new Error(`unsafe marker path '${relativePath}'`);\n\t}\n\tconst resolved = normalize(join(folder, ...relativePath.split(\"/\")));\n\tif (!resolved.startsWith(`${folder}${sep}`)) {\n\t\tthrow new Error(`unsafe marker path '${relativePath}'`);\n\t}\n\treturn resolved;\n}\n\nasync function optionalStat(path: string) {\n\ttry {\n\t\treturn await lstat(path, { bigint: false });\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n\t\tthrow error;\n\t}\n}\n\nasync function readRegularFileWithoutFollowing(path: string): Promise<string> {\n\tlet handle: FileHandle | undefined;\n\ttry {\n\t\tconst pathMetadata = await lstat(path);\n\t\tif (pathMetadata.isSymbolicLink()) {\n\t\t\tthrow new Error(`symbolic link refused: ${path}`);\n\t\t}\n\t\tif (!pathMetadata.isFile()) throw new Error(`not a regular file: ${path}`);\n\t\thandle = await open(path, constants.O_RDONLY | NO_FOLLOW);\n\t\tconst metadata = await handle.stat();\n\t\tif (!metadata.isFile()) throw new Error(`not a regular file: ${path}`);\n\t\tif (\n\t\t\tmetadata.dev !== pathMetadata.dev ||\n\t\t\tmetadata.ino !== pathMetadata.ino\n\t\t) {\n\t\t\tthrow new Error(`file changed while cleanup was running: ${path}`);\n\t\t}\n\t\treturn await handle.readFile({ encoding: \"utf8\" });\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ELOOP\") {\n\t\t\tthrow new Error(`symbolic link refused: ${path}`);\n\t\t}\n\t\tthrow error;\n\t} finally {\n\t\tawait handle?.close();\n\t}\n}\n\nfunction parseMarker(content: string): ParsedMarker {\n\tlet version: string | undefined;\n\tconst files = new Map<string, string>();\n\tfor (const line of content.split(/\\r?\\n/)) {\n\t\tif (!line) continue;\n\t\tconst versionMatch = /^version=(.+)$/.exec(line);\n\t\tif (versionMatch?.[1]) {\n\t\t\tif (version) throw new Error(\"marker contains duplicate versions\");\n\t\t\tversion = versionMatch[1];\n\t\t\tcontinue;\n\t\t}\n\t\tconst fileMatch =\n\t\t\t/^file=(.+) sha256=([a-f0-9]{64})$/.exec(line) ??\n\t\t\t/^file=(.+)=sha256:([a-f0-9]{64})$/.exec(line);\n\t\tif (fileMatch?.[1] && fileMatch[2]) {\n\t\t\tif (files.has(fileMatch[1])) {\n\t\t\t\tthrow new Error(`marker contains duplicate file '${fileMatch[1]}'`);\n\t\t\t}\n\t\t\tfiles.set(fileMatch[1], fileMatch[2]);\n\t\t\tcontinue;\n\t\t}\n\t\tconst topLevelHash = /^hash=sha256:([a-f0-9]{64})$/.exec(line);\n\t\tif (topLevelHash?.[1] && !files.has(\"SKILL.md\")) {\n\t\t\tfiles.set(\"SKILL.md\", topLevelHash[1]);\n\t\t\tcontinue;\n\t\t}\n\t\tthrow new Error(`marker contains an invalid line: '${line}'`);\n\t}\n\tif (!version) throw new Error(\"marker has no version\");\n\tif (!files.has(\"SKILL.md\")) throw new Error(\"marker does not own SKILL.md\");\n\treturn { version, files };\n}\n\nfunction assertSupportedLegacyVersion(version: string): void {\n\tconst match = SEMVER_PATTERN.exec(version);\n\tif (!match) {\n\t\tthrow new Error(\n\t\t\t`marker version '${version}' is not a valid semantic version`,\n\t\t);\n\t}\n\tif (match[1] !== SUPPORTED_LEGACY_MAJOR) {\n\t\tthrow new Error(\n\t\t\t`marker version '${version}' is outside the supported legacy range >=4.0.0 <5.0.0`,\n\t\t);\n\t}\n}\n\nfunction expectedDirectoryEntries(\n\tmarker: ParsedMarker,\n): Map<string, Set<string>> {\n\tconst entries = new Map<string, Set<string>>([\n\t\t[\"\", new Set([LEGACY_MARKER])],\n\t]);\n\tfor (const relativePath of marker.files.keys()) {\n\t\tconst parts = relativePath.split(\"/\");\n\t\tlet parent = \"\";\n\t\tfor (let index = 0; index < parts.length; index += 1) {\n\t\t\tconst part = parts[index];\n\t\t\tif (!part) throw new Error(`unsafe marker path '${relativePath}'`);\n\t\t\tconst children = entries.get(parent) ?? new Set<string>();\n\t\t\tchildren.add(part);\n\t\t\tentries.set(parent, children);\n\t\t\tif (index < parts.length - 1) {\n\t\t\t\tparent = parent ? `${parent}/${part}` : part;\n\t\t\t\tif (!entries.has(parent)) entries.set(parent, new Set());\n\t\t\t}\n\t\t}\n\t}\n\treturn entries;\n}\n\nasync function inspectLegacyFolder(\n\tname: string,\n\tfolder: string,\n): Promise<LegacySkillCleanupResult> {\n\tconst metadata = await optionalStat(folder);\n\tif (!metadata) return { name, path: folder, status: \"absent\" };\n\tif (!metadata.isDirectory()) {\n\t\treturn {\n\t\t\tname,\n\t\t\tpath: folder,\n\t\t\tstatus: \"refused\",\n\t\t\treason: \"path is not a real directory\",\n\t\t};\n\t}\n\n\ttry {\n\t\tconst markerPath = join(folder, LEGACY_MARKER);\n\t\tconst marker = parseMarker(\n\t\t\tawait readRegularFileWithoutFollowing(markerPath),\n\t\t);\n\t\tassertSupportedLegacyVersion(marker.version);\n\t\tconst directories = expectedDirectoryEntries(marker);\n\t\tfor (const [relativeDirectory, expectedEntries] of directories) {\n\t\t\tconst directory = relativeDirectory\n\t\t\t\t? safeLegacyPath(folder, relativeDirectory)\n\t\t\t\t: folder;\n\t\t\tconst directoryMetadata = await optionalStat(directory);\n\t\t\tif (!directoryMetadata?.isDirectory()) {\n\t\t\t\tthrow new Error(`expected real directory: ${relativeDirectory || \".\"}`);\n\t\t\t}\n\t\t\tconst actualEntries = await readdir(directory);\n\t\t\tconst unexpected = actualEntries.filter(\n\t\t\t\t(entry) => !expectedEntries.has(entry),\n\t\t\t);\n\t\t\tconst missing = [...expectedEntries].filter(\n\t\t\t\t(entry) => !actualEntries.includes(entry),\n\t\t\t);\n\t\t\tif (unexpected.length > 0 || missing.length > 0) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t[\n\t\t\t\t\t\tunexpected.length > 0\n\t\t\t\t\t\t\t? `unexpected entries: ${unexpected.join(\", \")}`\n\t\t\t\t\t\t\t: \"\",\n\t\t\t\t\t\tmissing.length > 0 ? `missing entries: ${missing.join(\", \")}` : \"\",\n\t\t\t\t\t]\n\t\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t\t.join(\"; \"),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tfor (const [relativePath, expectedHash] of marker.files) {\n\t\t\tconst path = safeLegacyPath(folder, relativePath);\n\t\t\tconst content = await readRegularFileWithoutFollowing(path);\n\t\t\tif (sha256(content) !== expectedHash) {\n\t\t\t\tthrow new Error(`edited file refused: ${relativePath}`);\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tname,\n\t\t\tpath: folder,\n\t\t\tstatus: \"eligible\",\n\t\t};\n\t} catch (error) {\n\t\treturn {\n\t\t\tname,\n\t\t\tpath: folder,\n\t\t\tstatus: \"refused\",\n\t\t\treason: error instanceof Error ? error.message : String(error),\n\t\t};\n\t}\n}\n\nasync function ensureRealArchiveRoot(path: string): Promise<void> {\n\tconst existing = await optionalStat(path);\n\tif (existing) {\n\t\tif (!existing.isDirectory()) {\n\t\t\tthrow new Error(`Legacy archive path is not a real directory: ${path}`);\n\t\t}\n\t\treturn;\n\t}\n\ttry {\n\t\tawait mkdir(path, { mode: 0o700 });\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n\t\tconst raced = await optionalStat(path);\n\t\tif (!raced?.isDirectory()) {\n\t\t\tthrow new Error(`Legacy archive path is not a real directory: ${path}`);\n\t\t}\n\t}\n}\n\nexport async function cleanupLegacySkills(options?: {\n\thome?: string;\n\tapply?: boolean;\n\t/** @internal Deterministic race-testing seam; package consumers should omit it. */\n\tafterQuarantine?: (context: {\n\t\tname: string;\n\t\tpath: string;\n\t\tarchivePath: string;\n\t}) => Promise<void>;\n}): Promise<LegacyCleanupReport> {\n\tconst home = options?.home ?? configuredHome();\n\tconst root = resolveLegacySkillsRoot(home);\n\tconst archiveRoot = resolveLegacyArchiveRoot(home);\n\tconst apply = options?.apply === true;\n\tconst results: LegacySkillCleanupResult[] = [];\n\n\tlet archiveReady = false;\n\tfor (const name of FLOW_GUIDANCE_TOPICS) {\n\t\tconst path = join(root, name);\n\t\tconst inspected = await inspectLegacyFolder(name, path);\n\t\tif (!apply || inspected.status !== \"eligible\") {\n\t\t\tresults.push(inspected);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!archiveReady) {\n\t\t\tawait ensureRealArchiveRoot(archiveRoot);\n\t\t\tarchiveReady = true;\n\t\t}\n\t\tconst archivePath = join(\n\t\t\tarchiveRoot,\n\t\t\t`${name}-${new Date().toISOString().replaceAll(\":\", \"-\")}-${crypto.randomUUID()}`,\n\t\t);\n\t\ttry {\n\t\t\tawait rename(path, archivePath);\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n\t\t\tresults.push({\n\t\t\t\tname,\n\t\t\t\tpath,\n\t\t\t\tstatus: \"refused\",\n\t\t\t\treason: \"folder changed while cleanup was running\",\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tawait options?.afterQuarantine?.({ name, path, archivePath });\n\t\tconst verified = await inspectLegacyFolder(name, archivePath);\n\t\tif (verified.status !== \"eligible\") {\n\t\t\tresults.push({\n\t\t\t\tname,\n\t\t\t\tpath,\n\t\t\t\tstatus: \"quarantined\",\n\t\t\t\treason:\n\t\t\t\t\t\"folder changed while cleanup was running; preserved for manual recovery\",\n\t\t\t\tarchivePath,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tresults.push({\n\t\t\tname,\n\t\t\tpath,\n\t\t\tstatus: \"archived\",\n\t\t\tarchivePath,\n\t\t});\n\t}\n\n\treturn {\n\t\tmode: apply ? \"apply\" : \"dry-run\",\n\t\troot,\n\t\tarchiveRoot,\n\t\tresults,\n\t};\n}\n",
5
+ "import { createHash } from \"node:crypto\";\nimport { constants } from \"node:fs\";\nimport {\n\ttype FileHandle,\n\tlstat,\n\tmkdir,\n\topen,\n\treaddir,\n\trename,\n} from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { isAbsolute, join, normalize, sep } from \"node:path\";\nimport { setTimeout as sleep } from \"node:timers/promises\";\nimport { FLOW_GUIDANCE_TOPICS } from \"../guidance/ids.js\";\n\nconst LEGACY_MARKER = \".flow-skill-version\";\nconst NO_FOLLOW = constants.O_NOFOLLOW ?? 0;\nconst SUPPORTED_LEGACY_MAJOR = \"4\";\nconst POST_MOVE_VERIFICATION_ATTEMPTS = 4;\nconst POST_MOVE_VERIFICATION_RETRY_MS = 25;\nconst SEMVER_PATTERN =\n\t/^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-(?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*))*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$/;\n\ntype ParsedMarker = {\n\tversion: string;\n\tfiles: Map<string, string>;\n};\n\nexport type LegacySkillCleanupResult = {\n\tname: string;\n\tpath: string;\n\tstatus: \"absent\" | \"eligible\" | \"archived\" | \"refused\" | \"quarantined\";\n\treason?: string;\n\tarchivePath?: string;\n};\n\nexport type LegacyCleanupReport = {\n\tmode: \"dry-run\" | \"apply\";\n\troot: string;\n\tarchiveRoot: string;\n\tresults: LegacySkillCleanupResult[];\n};\n\nfunction configuredHome(): string {\n\treturn (\n\t\tprocess.env.HOME?.trim() || process.env.USERPROFILE?.trim() || homedir()\n\t);\n}\n\nexport function resolveLegacySkillsRoot(home = configuredHome()): string {\n\treturn join(home, \".config\", \"opencode\", \"skills\");\n}\n\nexport function resolveLegacyArchiveRoot(home = configuredHome()): string {\n\treturn join(home, \".config\", \"opencode\", \"flow-legacy-skills\");\n}\n\nfunction sha256(content: string): string {\n\treturn createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\nfunction safeLegacyPath(folder: string, relativePath: string): string {\n\tif (\n\t\t!relativePath ||\n\t\tisAbsolute(relativePath) ||\n\t\trelativePath.includes(\"\\\\\") ||\n\t\trelativePath\n\t\t\t.split(\"/\")\n\t\t\t.some((part) => !part || part === \".\" || part === \"..\")\n\t) {\n\t\tthrow new Error(`unsafe marker path '${relativePath}'`);\n\t}\n\tconst resolved = normalize(join(folder, ...relativePath.split(\"/\")));\n\tif (!resolved.startsWith(`${folder}${sep}`)) {\n\t\tthrow new Error(`unsafe marker path '${relativePath}'`);\n\t}\n\treturn resolved;\n}\n\nasync function optionalStat(path: string) {\n\ttry {\n\t\treturn await lstat(path, { bigint: false });\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n\t\tthrow error;\n\t}\n}\n\nasync function readRegularFileWithoutFollowing(path: string): Promise<string> {\n\tlet handle: FileHandle | undefined;\n\ttry {\n\t\tconst pathMetadata = await lstat(path);\n\t\tif (pathMetadata.isSymbolicLink()) {\n\t\t\tthrow new Error(`symbolic link refused: ${path}`);\n\t\t}\n\t\tif (!pathMetadata.isFile()) throw new Error(`not a regular file: ${path}`);\n\t\thandle = await open(path, constants.O_RDONLY | NO_FOLLOW);\n\t\tconst metadata = await handle.stat();\n\t\tif (!metadata.isFile()) throw new Error(`not a regular file: ${path}`);\n\t\tif (\n\t\t\tmetadata.dev !== pathMetadata.dev ||\n\t\t\tmetadata.ino !== pathMetadata.ino\n\t\t) {\n\t\t\tthrow new Error(`file changed while cleanup was running: ${path}`);\n\t\t}\n\t\treturn await handle.readFile({ encoding: \"utf8\" });\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ELOOP\") {\n\t\t\tthrow new Error(`symbolic link refused: ${path}`);\n\t\t}\n\t\tthrow error;\n\t} finally {\n\t\tawait handle?.close();\n\t}\n}\n\nfunction parseMarker(content: string): ParsedMarker {\n\tlet version: string | undefined;\n\tconst files = new Map<string, string>();\n\tfor (const line of content.split(/\\r?\\n/)) {\n\t\tif (!line) continue;\n\t\tconst versionMatch = /^version=(.+)$/.exec(line);\n\t\tif (versionMatch?.[1]) {\n\t\t\tif (version) throw new Error(\"marker contains duplicate versions\");\n\t\t\tversion = versionMatch[1];\n\t\t\tcontinue;\n\t\t}\n\t\tconst fileMatch =\n\t\t\t/^file=(.+) sha256=([a-f0-9]{64})$/.exec(line) ??\n\t\t\t/^file=(.+)=sha256:([a-f0-9]{64})$/.exec(line);\n\t\tif (fileMatch?.[1] && fileMatch[2]) {\n\t\t\tif (files.has(fileMatch[1])) {\n\t\t\t\tthrow new Error(`marker contains duplicate file '${fileMatch[1]}'`);\n\t\t\t}\n\t\t\tfiles.set(fileMatch[1], fileMatch[2]);\n\t\t\tcontinue;\n\t\t}\n\t\tconst topLevelHash = /^hash=sha256:([a-f0-9]{64})$/.exec(line);\n\t\tif (topLevelHash?.[1] && !files.has(\"SKILL.md\")) {\n\t\t\tfiles.set(\"SKILL.md\", topLevelHash[1]);\n\t\t\tcontinue;\n\t\t}\n\t\tthrow new Error(`marker contains an invalid line: '${line}'`);\n\t}\n\tif (!version) throw new Error(\"marker has no version\");\n\tif (!files.has(\"SKILL.md\")) throw new Error(\"marker does not own SKILL.md\");\n\treturn { version, files };\n}\n\nfunction assertSupportedLegacyVersion(version: string): void {\n\tconst match = SEMVER_PATTERN.exec(version);\n\tif (!match) {\n\t\tthrow new Error(\n\t\t\t`marker version '${version}' is not a valid semantic version`,\n\t\t);\n\t}\n\tif (match[1] !== SUPPORTED_LEGACY_MAJOR) {\n\t\tthrow new Error(\n\t\t\t`marker version '${version}' is outside the supported legacy range >=4.0.0 <5.0.0`,\n\t\t);\n\t}\n}\n\nfunction expectedDirectoryEntries(\n\tmarker: ParsedMarker,\n): Map<string, Set<string>> {\n\tconst entries = new Map<string, Set<string>>([\n\t\t[\"\", new Set([LEGACY_MARKER])],\n\t]);\n\tfor (const relativePath of marker.files.keys()) {\n\t\tconst parts = relativePath.split(\"/\");\n\t\tlet parent = \"\";\n\t\tfor (let index = 0; index < parts.length; index += 1) {\n\t\t\tconst part = parts[index];\n\t\t\tif (!part) throw new Error(`unsafe marker path '${relativePath}'`);\n\t\t\tconst children = entries.get(parent) ?? new Set<string>();\n\t\t\tchildren.add(part);\n\t\t\tentries.set(parent, children);\n\t\t\tif (index < parts.length - 1) {\n\t\t\t\tparent = parent ? `${parent}/${part}` : part;\n\t\t\t\tif (!entries.has(parent)) entries.set(parent, new Set());\n\t\t\t}\n\t\t}\n\t}\n\treturn entries;\n}\n\nasync function inspectLegacyFolder(\n\tname: string,\n\tfolder: string,\n): Promise<LegacySkillCleanupResult> {\n\tconst metadata = await optionalStat(folder);\n\tif (!metadata) return { name, path: folder, status: \"absent\" };\n\tif (!metadata.isDirectory()) {\n\t\treturn {\n\t\t\tname,\n\t\t\tpath: folder,\n\t\t\tstatus: \"refused\",\n\t\t\treason: \"path is not a real directory\",\n\t\t};\n\t}\n\n\ttry {\n\t\tconst markerPath = join(folder, LEGACY_MARKER);\n\t\tconst marker = parseMarker(\n\t\t\tawait readRegularFileWithoutFollowing(markerPath),\n\t\t);\n\t\tassertSupportedLegacyVersion(marker.version);\n\t\tconst directories = expectedDirectoryEntries(marker);\n\t\tfor (const [relativeDirectory, expectedEntries] of directories) {\n\t\t\tconst directory = relativeDirectory\n\t\t\t\t? safeLegacyPath(folder, relativeDirectory)\n\t\t\t\t: folder;\n\t\t\tconst directoryMetadata = await optionalStat(directory);\n\t\t\tif (!directoryMetadata?.isDirectory()) {\n\t\t\t\tthrow new Error(`expected real directory: ${relativeDirectory || \".\"}`);\n\t\t\t}\n\t\t\tconst actualEntries = await readdir(directory);\n\t\t\tconst unexpected = actualEntries.filter(\n\t\t\t\t(entry) => !expectedEntries.has(entry),\n\t\t\t);\n\t\t\tconst missing = [...expectedEntries].filter(\n\t\t\t\t(entry) => !actualEntries.includes(entry),\n\t\t\t);\n\t\t\tif (unexpected.length > 0 || missing.length > 0) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t[\n\t\t\t\t\t\tunexpected.length > 0\n\t\t\t\t\t\t\t? `unexpected entries: ${unexpected.join(\", \")}`\n\t\t\t\t\t\t\t: \"\",\n\t\t\t\t\t\tmissing.length > 0 ? `missing entries: ${missing.join(\", \")}` : \"\",\n\t\t\t\t\t]\n\t\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t\t.join(\"; \"),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tfor (const [relativePath, expectedHash] of marker.files) {\n\t\t\tconst path = safeLegacyPath(folder, relativePath);\n\t\t\tconst content = await readRegularFileWithoutFollowing(path);\n\t\t\tif (sha256(content) !== expectedHash) {\n\t\t\t\tthrow new Error(`edited file refused: ${relativePath}`);\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tname,\n\t\t\tpath: folder,\n\t\t\tstatus: \"eligible\",\n\t\t};\n\t} catch (error) {\n\t\treturn {\n\t\t\tname,\n\t\t\tpath: folder,\n\t\t\tstatus: \"refused\",\n\t\t\treason: error instanceof Error ? error.message : String(error),\n\t\t};\n\t}\n}\n\nasync function ensureRealArchiveRoot(path: string): Promise<void> {\n\tconst existing = await optionalStat(path);\n\tif (existing) {\n\t\tif (!existing.isDirectory()) {\n\t\t\tthrow new Error(`Legacy archive path is not a real directory: ${path}`);\n\t\t}\n\t\treturn;\n\t}\n\ttry {\n\t\tawait mkdir(path, { mode: 0o700 });\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n\t\tconst raced = await optionalStat(path);\n\t\tif (!raced?.isDirectory()) {\n\t\t\tthrow new Error(`Legacy archive path is not a real directory: ${path}`);\n\t\t}\n\t}\n}\n\nasync function verifyMovedLegacyFolder(\n\tname: string,\n\tarchivePath: string,\n): Promise<LegacySkillCleanupResult> {\n\tlet verified = await inspectLegacyFolder(name, archivePath);\n\tfor (\n\t\tlet attempt = 1;\n\t\tattempt < POST_MOVE_VERIFICATION_ATTEMPTS && verified.status !== \"eligible\";\n\t\tattempt += 1\n\t) {\n\t\t// Windows may briefly report a just-renamed directory as missing or\n\t\t// inaccessible while a competing inspection releases its file handles.\n\t\t// Retrying never weakens cleanup safety: only a complete byte-pristine\n\t\t// inspection can return eligible, while persistent edits still quarantine.\n\t\tawait sleep(POST_MOVE_VERIFICATION_RETRY_MS * attempt);\n\t\tverified = await inspectLegacyFolder(name, archivePath);\n\t}\n\treturn verified;\n}\n\nexport async function cleanupLegacySkills(options?: {\n\thome?: string;\n\tapply?: boolean;\n\t/** @internal Deterministic race-testing seam; package consumers should omit it. */\n\tafterQuarantine?: (context: {\n\t\tname: string;\n\t\tpath: string;\n\t\tarchivePath: string;\n\t}) => Promise<void>;\n}): Promise<LegacyCleanupReport> {\n\tconst home = options?.home ?? configuredHome();\n\tconst root = resolveLegacySkillsRoot(home);\n\tconst archiveRoot = resolveLegacyArchiveRoot(home);\n\tconst apply = options?.apply === true;\n\tconst results: LegacySkillCleanupResult[] = [];\n\n\tlet archiveReady = false;\n\tfor (const name of FLOW_GUIDANCE_TOPICS) {\n\t\tconst path = join(root, name);\n\t\tconst inspected = await inspectLegacyFolder(name, path);\n\t\tif (!apply || inspected.status !== \"eligible\") {\n\t\t\tresults.push(inspected);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!archiveReady) {\n\t\t\tawait ensureRealArchiveRoot(archiveRoot);\n\t\t\tarchiveReady = true;\n\t\t}\n\t\tconst archivePath = join(\n\t\t\tarchiveRoot,\n\t\t\t`${name}-${new Date().toISOString().replaceAll(\":\", \"-\")}-${crypto.randomUUID()}`,\n\t\t);\n\t\ttry {\n\t\t\tawait rename(path, archivePath);\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n\t\t\tresults.push({\n\t\t\t\tname,\n\t\t\t\tpath,\n\t\t\t\tstatus: \"refused\",\n\t\t\t\treason: \"folder changed while cleanup was running\",\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tawait options?.afterQuarantine?.({ name, path, archivePath });\n\t\tconst verified = await verifyMovedLegacyFolder(name, archivePath);\n\t\tif (verified.status !== \"eligible\") {\n\t\t\tresults.push({\n\t\t\t\tname,\n\t\t\t\tpath,\n\t\t\t\tstatus: \"quarantined\",\n\t\t\t\treason:\n\t\t\t\t\t\"folder changed while cleanup was running; preserved for manual recovery\",\n\t\t\t\tarchivePath,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tresults.push({\n\t\t\tname,\n\t\t\tpath,\n\t\t\tstatus: \"archived\",\n\t\t\tarchivePath,\n\t\t});\n\t}\n\n\treturn {\n\t\tmode: apply ? \"apply\" : \"dry-run\",\n\t\troot,\n\t\tarchiveRoot,\n\t\tresults,\n\t};\n}\n",
6
6
  "export const FLOW_GUIDANCE_TOPICS = [\n\t\"flow\",\n\t\"flow-plan\",\n\t\"flow-run\",\n\t\"flow-test\",\n\t\"flow-review\",\n\t\"flow-deslop\",\n\t\"flow-ui-quality\",\n\t\"flow-commit\",\n] as const;\n\nexport type FlowGuidanceTopic = (typeof FLOW_GUIDANCE_TOPICS)[number];\n\nexport const FLOW_GUIDANCE_IDS = [\n\t\"flow\",\n\t\"flow/references/recovery-playbook.md\",\n\t\"flow/references/parallel-orchestration.md\",\n\t\"flow/references/parallel-decision.md\",\n\t\"flow/references/parallel-manifest.md\",\n\t\"flow/references/parallel-execution.md\",\n\t\"flow/references/parallel-synthesis.md\",\n\t\"flow/references/parallel-pass-example.md\",\n\t\"flow/references/handoff-format.md\",\n\t\"flow-plan\",\n\t\"flow-plan/references/planning-examples.md\",\n\t\"flow-plan/references/plan-quality-checklist.md\",\n\t\"flow-plan/references/parallel-discovery.md\",\n\t\"flow-run\",\n\t\"flow-run/references/validation-rubric.md\",\n\t\"flow-run/references/audit-rubric.md\",\n\t\"flow-test\",\n\t\"flow-review\",\n\t\"flow-review/references/hidden-reviewer-contract.md\",\n\t\"flow-review/references/review-rubric.md\",\n\t\"flow-deslop\",\n\t\"flow-deslop/references/smell-rubric.md\",\n\t\"flow-deslop/references/refactor-workflow.md\",\n\t\"flow-ui-quality\",\n\t\"flow-ui-quality/references/ui-rubric.md\",\n\t\"flow-ui-quality/references/visual-verification.md\",\n\t\"flow-commit\",\n] as const;\n\nexport type FlowGuidanceId = (typeof FLOW_GUIDANCE_IDS)[number];\n",
7
7
  "import { createRequire } from \"node:module\";\n\nexport function resolveFlowPluginVersion(): string {\n\ttry {\n\t\tconst require = createRequire(import.meta.url);\n\t\tconst manifest = require(\"../package.json\") as { version?: string };\n\t\tif (manifest.version) return manifest.version;\n\t} catch {\n\t\t// Fall through to the development sentinel.\n\t}\n\treturn \"0.0.0\";\n}\n",
8
8
  "import {\n\tcleanupLegacySkills,\n\ttype LegacyCleanupReport,\n} from \"./distribution/legacy-cleanup.js\";\nimport { resolveFlowPluginVersion } from \"./version.js\";\n\nfunction usage(): string {\n\treturn [\n\t\t\"usage: opencode-plugin-flow legacy-cleanup <--dry-run|--apply> [--json]\",\n\t\t\"\",\n\t\t\"commands:\",\n\t\t\" legacy-cleanup Inspect or archive marker-proven legacy global Flow skills\",\n\t\t\"\",\n\t\t\"options:\",\n\t\t\" --dry-run Report eligible folders without changing the filesystem\",\n\t\t\" --apply Move eligible folders to a recoverable archive outside skill discovery\",\n\t\t\" Cleanup never deletes legacy folders\",\n\t\t\" --json Write the report as JSON\",\n\t\t\" --help Show this help\",\n\t\t\" --version Print the plugin version\",\n\t].join(\"\\n\");\n}\n\nfunction writeReport(report: LegacyCleanupReport, json: boolean): void {\n\tif (json) {\n\t\tprocess.stdout.write(`${JSON.stringify(report, null, 2)}\\n`);\n\t\treturn;\n\t}\n\tprocess.stdout.write(`Flow legacy skill cleanup (${report.mode})\\n`);\n\tprocess.stdout.write(`- legacy root: ${report.root}\\n`);\n\tprocess.stdout.write(`- archive root: ${report.archiveRoot}\\n`);\n\tfor (const result of report.results) {\n\t\tprocess.stdout.write(`- ${result.name}: ${result.status}\\n`);\n\t\tif (result.reason) process.stdout.write(` reason: ${result.reason}\\n`);\n\t\tif (result.archivePath) {\n\t\t\tconst label = result.status === \"archived\" ? \"archived\" : \"preserved\";\n\t\t\tprocess.stdout.write(` ${label} at: ${result.archivePath}\\n`);\n\t\t}\n\t}\n}\n\nasync function main(argv: string[]): Promise<void> {\n\tconst [command, ...flags] = argv.slice(2);\n\tif (command === \"--help\" || command === \"-h\") {\n\t\tprocess.stdout.write(`${usage()}\\n`);\n\t\treturn;\n\t}\n\tif (command === \"--version\" || command === \"-v\") {\n\t\tprocess.stdout.write(`${resolveFlowPluginVersion()}\\n`);\n\t\treturn;\n\t}\n\tconst knownFlags = new Set([\"--dry-run\", \"--apply\", \"--json\"]);\n\tconst validFlags = flags.every((flag) => knownFlags.has(flag));\n\tconst dryRun = flags.includes(\"--dry-run\");\n\tconst apply = flags.includes(\"--apply\");\n\tif (command !== \"legacy-cleanup\" || !validFlags || dryRun === apply) {\n\t\tprocess.stderr.write(`${usage()}\\n`);\n\t\tprocess.exitCode = 2;\n\t\treturn;\n\t}\n\tconst report = await cleanupLegacySkills({ apply });\n\twriteReport(report, flags.includes(\"--json\"));\n\tif (\n\t\tapply &&\n\t\treport.results.some((result) =>\n\t\t\t[\"refused\", \"quarantined\"].includes(result.status),\n\t\t)\n\t) {\n\t\tprocess.exitCode = 1;\n\t}\n}\n\nmain(process.argv).catch((error) => {\n\tprocess.stderr.write(\n\t\t`${error instanceof Error ? error.message : String(error)}\\n`,\n\t);\n\tprocess.exitCode = 1;\n});\n"
9
9
  ],
10
- "mappings": "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",
11
- "debugId": "690F8C77CD4F802F64756E2164756E21",
10
+ "mappings": ";;;AAAA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA;AACA;AACA,uBAAS;;;ACZF,IAAM,uBAAuB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;;;ADMA,IAAM,gBAAgB;AACtB,IAAM,YAAY,UAAU,cAAc;AAC1C,IAAM,yBAAyB;AAC/B,IAAM,kCAAkC;AACxC,IAAM,kCAAkC;AACxC,IAAM,iBACL;AAsBD,SAAS,cAAc,GAAW;AAAA,EACjC,OACC,QAAQ,IAAI,MAAM,KAAK,KAAK,QAAQ,IAAI,aAAa,KAAK,KAAK,QAAQ;AAAA;AAIlE,SAAS,uBAAuB,CAAC,OAAO,eAAe,GAAW;AAAA,EACxE,OAAO,KAAK,MAAM,WAAW,YAAY,QAAQ;AAAA;AAG3C,SAAS,wBAAwB,CAAC,OAAO,eAAe,GAAW;AAAA,EACzE,OAAO,KAAK,MAAM,WAAW,YAAY,oBAAoB;AAAA;AAG9D,SAAS,MAAM,CAAC,SAAyB;AAAA,EACxC,OAAO,WAAW,QAAQ,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK;AAAA;AAGzD,SAAS,cAAc,CAAC,QAAgB,cAA8B;AAAA,EACrE,IACC,CAAC,gBACD,WAAW,YAAY,KACvB,aAAa,SAAS,IAAI,KAC1B,aACE,MAAM,GAAG,EACT,KAAK,CAAC,SAAS,CAAC,QAAQ,SAAS,OAAO,SAAS,IAAI,GACtD;AAAA,IACD,MAAM,IAAI,MAAM,uBAAuB,eAAe;AAAA,EACvD;AAAA,EACA,MAAM,WAAW,UAAU,KAAK,QAAQ,GAAG,aAAa,MAAM,GAAG,CAAC,CAAC;AAAA,EACnE,IAAI,CAAC,SAAS,WAAW,GAAG,SAAS,KAAK,GAAG;AAAA,IAC5C,MAAM,IAAI,MAAM,uBAAuB,eAAe;AAAA,EACvD;AAAA,EACA,OAAO;AAAA;AAGR,eAAe,YAAY,CAAC,MAAc;AAAA,EACzC,IAAI;AAAA,IACH,OAAO,MAAM,MAAM,MAAM,EAAE,QAAQ,MAAM,CAAC;AAAA,IACzC,OAAO,OAAO;AAAA,IACf,IAAK,MAAgC,SAAS;AAAA,MAAU,OAAO;AAAA,IAC/D,MAAM;AAAA;AAAA;AAIR,eAAe,+BAA+B,CAAC,MAA+B;AAAA,EAC7E,IAAI;AAAA,EACJ,IAAI;AAAA,IACH,MAAM,eAAe,MAAM,MAAM,IAAI;AAAA,IACrC,IAAI,aAAa,eAAe,GAAG;AAAA,MAClC,MAAM,IAAI,MAAM,0BAA0B,MAAM;AAAA,IACjD;AAAA,IACA,IAAI,CAAC,aAAa,OAAO;AAAA,MAAG,MAAM,IAAI,MAAM,uBAAuB,MAAM;AAAA,IACzE,SAAS,MAAM,KAAK,MAAM,UAAU,WAAW,SAAS;AAAA,IACxD,MAAM,WAAW,MAAM,OAAO,KAAK;AAAA,IACnC,IAAI,CAAC,SAAS,OAAO;AAAA,MAAG,MAAM,IAAI,MAAM,uBAAuB,MAAM;AAAA,IACrE,IACC,SAAS,QAAQ,aAAa,OAC9B,SAAS,QAAQ,aAAa,KAC7B;AAAA,MACD,MAAM,IAAI,MAAM,2CAA2C,MAAM;AAAA,IAClE;AAAA,IACA,OAAO,MAAM,OAAO,SAAS,EAAE,UAAU,OAAO,CAAC;AAAA,IAChD,OAAO,OAAO;AAAA,IACf,IAAK,MAAgC,SAAS,SAAS;AAAA,MACtD,MAAM,IAAI,MAAM,0BAA0B,MAAM;AAAA,IACjD;AAAA,IACA,MAAM;AAAA,YACL;AAAA,IACD,MAAM,QAAQ,MAAM;AAAA;AAAA;AAItB,SAAS,WAAW,CAAC,SAA+B;AAAA,EACnD,IAAI;AAAA,EACJ,MAAM,QAAQ,IAAI;AAAA,EAClB,WAAW,QAAQ,QAAQ,MAAM,OAAO,GAAG;AAAA,IAC1C,IAAI,CAAC;AAAA,MAAM;AAAA,IACX,MAAM,eAAe,iBAAiB,KAAK,IAAI;AAAA,IAC/C,IAAI,eAAe,IAAI;AAAA,MACtB,IAAI;AAAA,QAAS,MAAM,IAAI,MAAM,oCAAoC;AAAA,MACjE,UAAU,aAAa;AAAA,MACvB;AAAA,IACD;AAAA,IACA,MAAM,YACL,oCAAoC,KAAK,IAAI,KAC7C,oCAAoC,KAAK,IAAI;AAAA,IAC9C,IAAI,YAAY,MAAM,UAAU,IAAI;AAAA,MACnC,IAAI,MAAM,IAAI,UAAU,EAAE,GAAG;AAAA,QAC5B,MAAM,IAAI,MAAM,mCAAmC,UAAU,KAAK;AAAA,MACnE;AAAA,MACA,MAAM,IAAI,UAAU,IAAI,UAAU,EAAE;AAAA,MACpC;AAAA,IACD;AAAA,IACA,MAAM,eAAe,+BAA+B,KAAK,IAAI;AAAA,IAC7D,IAAI,eAAe,MAAM,CAAC,MAAM,IAAI,UAAU,GAAG;AAAA,MAChD,MAAM,IAAI,YAAY,aAAa,EAAE;AAAA,MACrC;AAAA,IACD;AAAA,IACA,MAAM,IAAI,MAAM,qCAAqC,OAAO;AAAA,EAC7D;AAAA,EACA,IAAI,CAAC;AAAA,IAAS,MAAM,IAAI,MAAM,uBAAuB;AAAA,EACrD,IAAI,CAAC,MAAM,IAAI,UAAU;AAAA,IAAG,MAAM,IAAI,MAAM,8BAA8B;AAAA,EAC1E,OAAO,EAAE,SAAS,MAAM;AAAA;AAGzB,SAAS,4BAA4B,CAAC,SAAuB;AAAA,EAC5D,MAAM,QAAQ,eAAe,KAAK,OAAO;AAAA,EACzC,IAAI,CAAC,OAAO;AAAA,IACX,MAAM,IAAI,MACT,mBAAmB,0CACpB;AAAA,EACD;AAAA,EACA,IAAI,MAAM,OAAO,wBAAwB;AAAA,IACxC,MAAM,IAAI,MACT,mBAAmB,+DACpB;AAAA,EACD;AAAA;AAGD,SAAS,wBAAwB,CAChC,QAC2B;AAAA,EAC3B,MAAM,UAAU,IAAI,IAAyB;AAAA,IAC5C,CAAC,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,CAAC;AAAA,EAC9B,CAAC;AAAA,EACD,WAAW,gBAAgB,OAAO,MAAM,KAAK,GAAG;AAAA,IAC/C,MAAM,QAAQ,aAAa,MAAM,GAAG;AAAA,IACpC,IAAI,SAAS;AAAA,IACb,SAAS,QAAQ,EAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AAAA,MACrD,MAAM,OAAO,MAAM;AAAA,MACnB,IAAI,CAAC;AAAA,QAAM,MAAM,IAAI,MAAM,uBAAuB,eAAe;AAAA,MACjE,MAAM,WAAW,QAAQ,IAAI,MAAM,KAAK,IAAI;AAAA,MAC5C,SAAS,IAAI,IAAI;AAAA,MACjB,QAAQ,IAAI,QAAQ,QAAQ;AAAA,MAC5B,IAAI,QAAQ,MAAM,SAAS,GAAG;AAAA,QAC7B,SAAS,SAAS,GAAG,UAAU,SAAS;AAAA,QACxC,IAAI,CAAC,QAAQ,IAAI,MAAM;AAAA,UAAG,QAAQ,IAAI,QAAQ,IAAI,GAAK;AAAA,MACxD;AAAA,IACD;AAAA,EACD;AAAA,EACA,OAAO;AAAA;AAGR,eAAe,mBAAmB,CACjC,MACA,QACoC;AAAA,EACpC,MAAM,WAAW,MAAM,aAAa,MAAM;AAAA,EAC1C,IAAI,CAAC;AAAA,IAAU,OAAO,EAAE,MAAM,MAAM,QAAQ,QAAQ,SAAS;AAAA,EAC7D,IAAI,CAAC,SAAS,YAAY,GAAG;AAAA,IAC5B,OAAO;AAAA,MACN;AAAA,MACA,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ;AAAA,IACT;AAAA,EACD;AAAA,EAEA,IAAI;AAAA,IACH,MAAM,aAAa,KAAK,QAAQ,aAAa;AAAA,IAC7C,MAAM,SAAS,YACd,MAAM,gCAAgC,UAAU,CACjD;AAAA,IACA,6BAA6B,OAAO,OAAO;AAAA,IAC3C,MAAM,cAAc,yBAAyB,MAAM;AAAA,IACnD,YAAY,mBAAmB,oBAAoB,aAAa;AAAA,MAC/D,MAAM,YAAY,oBACf,eAAe,QAAQ,iBAAiB,IACxC;AAAA,MACH,MAAM,oBAAoB,MAAM,aAAa,SAAS;AAAA,MACtD,IAAI,CAAC,mBAAmB,YAAY,GAAG;AAAA,QACtC,MAAM,IAAI,MAAM,4BAA4B,qBAAqB,KAAK;AAAA,MACvE;AAAA,MACA,MAAM,gBAAgB,MAAM,QAAQ,SAAS;AAAA,MAC7C,MAAM,aAAa,cAAc,OAChC,CAAC,UAAU,CAAC,gBAAgB,IAAI,KAAK,CACtC;AAAA,MACA,MAAM,UAAU,CAAC,GAAG,eAAe,EAAE,OACpC,CAAC,UAAU,CAAC,cAAc,SAAS,KAAK,CACzC;AAAA,MACA,IAAI,WAAW,SAAS,KAAK,QAAQ,SAAS,GAAG;AAAA,QAChD,MAAM,IAAI,MACT;AAAA,UACC,WAAW,SAAS,IACjB,uBAAuB,WAAW,KAAK,IAAI,MAC3C;AAAA,UACH,QAAQ,SAAS,IAAI,oBAAoB,QAAQ,KAAK,IAAI,MAAM;AAAA,QACjE,EACE,OAAO,OAAO,EACd,KAAK,IAAI,CACZ;AAAA,MACD;AAAA,IACD;AAAA,IACA,YAAY,cAAc,iBAAiB,OAAO,OAAO;AAAA,MACxD,MAAM,OAAO,eAAe,QAAQ,YAAY;AAAA,MAChD,MAAM,UAAU,MAAM,gCAAgC,IAAI;AAAA,MAC1D,IAAI,OAAO,OAAO,MAAM,cAAc;AAAA,QACrC,MAAM,IAAI,MAAM,wBAAwB,cAAc;AAAA,MACvD;AAAA,IACD;AAAA,IACA,OAAO;AAAA,MACN;AAAA,MACA,MAAM;AAAA,MACN,QAAQ;AAAA,IACT;AAAA,IACC,OAAO,OAAO;AAAA,IACf,OAAO;AAAA,MACN;AAAA,MACA,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAC9D;AAAA;AAAA;AAIF,eAAe,qBAAqB,CAAC,MAA6B;AAAA,EACjE,MAAM,WAAW,MAAM,aAAa,IAAI;AAAA,EACxC,IAAI,UAAU;AAAA,IACb,IAAI,CAAC,SAAS,YAAY,GAAG;AAAA,MAC5B,MAAM,IAAI,MAAM,gDAAgD,MAAM;AAAA,IACvE;AAAA,IACA;AAAA,EACD;AAAA,EACA,IAAI;AAAA,IACH,MAAM,MAAM,MAAM,EAAE,MAAM,IAAM,CAAC;AAAA,IAChC,OAAO,OAAO;AAAA,IACf,IAAK,MAAgC,SAAS;AAAA,MAAU,MAAM;AAAA,IAC9D,MAAM,QAAQ,MAAM,aAAa,IAAI;AAAA,IACrC,IAAI,CAAC,OAAO,YAAY,GAAG;AAAA,MAC1B,MAAM,IAAI,MAAM,gDAAgD,MAAM;AAAA,IACvE;AAAA;AAAA;AAIF,eAAe,uBAAuB,CACrC,MACA,aACoC;AAAA,EACpC,IAAI,WAAW,MAAM,oBAAoB,MAAM,WAAW;AAAA,EAC1D,SACK,UAAU,EACd,UAAU,mCAAmC,SAAS,WAAW,YACjE,WAAW,GACV;AAAA,IAKD,MAAM,MAAM,kCAAkC,OAAO;AAAA,IACrD,WAAW,MAAM,oBAAoB,MAAM,WAAW;AAAA,EACvD;AAAA,EACA,OAAO;AAAA;AAGR,eAAsB,mBAAmB,CAAC,SAST;AAAA,EAChC,MAAM,OAAO,SAAS,QAAQ,eAAe;AAAA,EAC7C,MAAM,OAAO,wBAAwB,IAAI;AAAA,EACzC,MAAM,cAAc,yBAAyB,IAAI;AAAA,EACjD,MAAM,QAAQ,SAAS,UAAU;AAAA,EACjC,MAAM,UAAsC,CAAC;AAAA,EAE7C,IAAI,eAAe;AAAA,EACnB,WAAW,QAAQ,sBAAsB;AAAA,IACxC,MAAM,OAAO,KAAK,MAAM,IAAI;AAAA,IAC5B,MAAM,YAAY,MAAM,oBAAoB,MAAM,IAAI;AAAA,IACtD,IAAI,CAAC,SAAS,UAAU,WAAW,YAAY;AAAA,MAC9C,QAAQ,KAAK,SAAS;AAAA,MACtB;AAAA,IACD;AAAA,IACA,IAAI,CAAC,cAAc;AAAA,MAClB,MAAM,sBAAsB,WAAW;AAAA,MACvC,eAAe;AAAA,IAChB;AAAA,IACA,MAAM,cAAc,KACnB,aACA,GAAG,QAAQ,IAAI,KAAK,EAAE,YAAY,EAAE,WAAW,KAAK,GAAG,KAAK,OAAO,WAAW,GAC/E;AAAA,IACA,IAAI;AAAA,MACH,MAAM,OAAO,MAAM,WAAW;AAAA,MAC7B,OAAO,OAAO;AAAA,MACf,IAAK,MAAgC,SAAS;AAAA,QAAU,MAAM;AAAA,MAC9D,QAAQ,KAAK;AAAA,QACZ;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,QACR,QAAQ;AAAA,MACT,CAAC;AAAA,MACD;AAAA;AAAA,IAED,MAAM,SAAS,kBAAkB,EAAE,MAAM,MAAM,YAAY,CAAC;AAAA,IAC5D,MAAM,WAAW,MAAM,wBAAwB,MAAM,WAAW;AAAA,IAChE,IAAI,SAAS,WAAW,YAAY;AAAA,MACnC,QAAQ,KAAK;AAAA,QACZ;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,QACR,QACC;AAAA,QACD;AAAA,MACD,CAAC;AAAA,MACD;AAAA,IACD;AAAA,IACA,QAAQ,KAAK;AAAA,MACZ;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EAEA,OAAO;AAAA,IACN,MAAM,QAAQ,UAAU;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,EACD;AAAA;;;AEhXD;AAEO,SAAS,wBAAwB,GAAW;AAAA,EAClD,IAAI;AAAA,IACH,MAAM,WAAU,cAAc,YAAY,GAAG;AAAA,IAC7C,MAAM,WAAW,SAAQ,iBAAiB;AAAA,IAC1C,IAAI,SAAS;AAAA,MAAS,OAAO,SAAS;AAAA,IACrC,MAAM;AAAA,EAGR,OAAO;AAAA;;;ACJR,SAAS,KAAK,GAAW;AAAA,EACxB,OAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,EAAE,KAAK;AAAA,CAAI;AAAA;AAGZ,SAAS,WAAW,CAAC,QAA6B,MAAqB;AAAA,EACtE,IAAI,MAAM;AAAA,IACT,QAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC;AAAA,CAAK;AAAA,IAC3D;AAAA,EACD;AAAA,EACA,QAAQ,OAAO,MAAM,8BAA8B,OAAO;AAAA,CAAS;AAAA,EACnE,QAAQ,OAAO,MAAM,kBAAkB,OAAO;AAAA,CAAQ;AAAA,EACtD,QAAQ,OAAO,MAAM,mBAAmB,OAAO;AAAA,CAAe;AAAA,EAC9D,WAAW,UAAU,OAAO,SAAS;AAAA,IACpC,QAAQ,OAAO,MAAM,KAAK,OAAO,SAAS,OAAO;AAAA,CAAU;AAAA,IAC3D,IAAI,OAAO;AAAA,MAAQ,QAAQ,OAAO,MAAM,aAAa,OAAO;AAAA,CAAU;AAAA,IACtE,IAAI,OAAO,aAAa;AAAA,MACvB,MAAM,QAAQ,OAAO,WAAW,aAAa,aAAa;AAAA,MAC1D,QAAQ,OAAO,MAAM,KAAK,aAAa,OAAO;AAAA,CAAe;AAAA,IAC9D;AAAA,EACD;AAAA;AAGD,eAAe,IAAI,CAAC,MAA+B;AAAA,EAClD,OAAO,YAAY,SAAS,KAAK,MAAM,CAAC;AAAA,EACxC,IAAI,YAAY,YAAY,YAAY,MAAM;AAAA,IAC7C,QAAQ,OAAO,MAAM,GAAG,MAAM;AAAA,CAAK;AAAA,IACnC;AAAA,EACD;AAAA,EACA,IAAI,YAAY,eAAe,YAAY,MAAM;AAAA,IAChD,QAAQ,OAAO,MAAM,GAAG,yBAAyB;AAAA,CAAK;AAAA,IACtD;AAAA,EACD;AAAA,EACA,MAAM,aAAa,IAAI,IAAI,CAAC,aAAa,WAAW,QAAQ,CAAC;AAAA,EAC7D,MAAM,aAAa,MAAM,MAAM,CAAC,SAAS,WAAW,IAAI,IAAI,CAAC;AAAA,EAC7D,MAAM,SAAS,MAAM,SAAS,WAAW;AAAA,EACzC,MAAM,QAAQ,MAAM,SAAS,SAAS;AAAA,EACtC,IAAI,YAAY,oBAAoB,CAAC,cAAc,WAAW,OAAO;AAAA,IACpE,QAAQ,OAAO,MAAM,GAAG,MAAM;AAAA,CAAK;AAAA,IACnC,QAAQ,WAAW;AAAA,IACnB;AAAA,EACD;AAAA,EACA,MAAM,SAAS,MAAM,oBAAoB,EAAE,MAAM,CAAC;AAAA,EAClD,YAAY,QAAQ,MAAM,SAAS,QAAQ,CAAC;AAAA,EAC5C,IACC,SACA,OAAO,QAAQ,KAAK,CAAC,WACpB,CAAC,WAAW,aAAa,EAAE,SAAS,OAAO,MAAM,CAClD,GACC;AAAA,IACD,QAAQ,WAAW;AAAA,EACpB;AAAA;AAGD,KAAK,QAAQ,IAAI,EAAE,MAAM,CAAC,UAAU;AAAA,EACnC,QAAQ,OAAO,MACd,GAAG,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,CACzD;AAAA,EACA,QAAQ,WAAW;AAAA,CACnB;",
11
+ "debugId": "4B60DFA5FC84470464756E2164756E21",
12
12
  "names": []
13
13
  }
@@ -1,8 +1,21 @@
1
+ import type { ValidationCommandClass } from "./validation-command.js";
1
2
  export type FeatureStatus = "pending" | "in_progress" | "completed" | "blocked";
2
3
  export type SessionStatus = "planning" | "ready" | "running" | "blocked" | "completed";
3
4
  export type FeatureReviewDepth = "quick" | "standard" | "detailed";
4
5
  export type FinalReviewPolicy = "broad" | "detailed";
5
6
  export type ValidationScope = "targeted" | "broad";
7
+ export type SnapshotId = string;
8
+ export type EvidenceId = string;
9
+ export type EvidenceArtifactRef = {
10
+ kind: "restricted_evidence_v1";
11
+ digest: `sha256:${string}`;
12
+ byteLength: number;
13
+ };
14
+ export type CausalGuard = {
15
+ operationId: string;
16
+ expectedRevision: number;
17
+ expectedSnapshotId: SnapshotId;
18
+ };
6
19
  declare const featureIdBrand: unique symbol;
7
20
  declare const sessionIdBrand: unique symbol;
8
21
  export type FeatureId = string & {
@@ -48,6 +61,49 @@ export type ReviewFinding = {
48
61
  summary: string;
49
62
  severity: "blocking" | "advisory";
50
63
  };
64
+ export type ReviewFindingTaxonomy = "implementation_defect" | "regression_coverage_gap" | "evidence_gap" | "advisory";
65
+ export type ReviewExecutionFindingInput = {
66
+ taxonomy: ReviewFindingTaxonomy;
67
+ subject: string;
68
+ requirementOrRisk: string;
69
+ evidenceLocator: string;
70
+ summary: string;
71
+ severity: "blocking" | "advisory";
72
+ };
73
+ export type ReviewExecutionFinding = ReviewExecutionFindingInput & {
74
+ fingerprint: string;
75
+ };
76
+ export type ReviewExecutionInput = {
77
+ attemptId: string;
78
+ logicalPassId: string;
79
+ featureId: FeatureId;
80
+ reviewKind: "feature" | "final";
81
+ reviewSnapshotId: string;
82
+ verdict: "passed" | "failed";
83
+ findings: ReviewExecutionFindingInput[];
84
+ startedAt: string;
85
+ completedAt: string;
86
+ terminalDisposition: "submitted" | "observed_unsubmitted";
87
+ };
88
+ export type ReviewExecution = Omit<ReviewExecutionInput, "findings"> & {
89
+ findings: ReviewExecutionFinding[];
90
+ };
91
+ export type ReviewLifecycleTelemetry = {
92
+ featureAttemptCount: number;
93
+ finalAttemptCount: number;
94
+ passedVerdictCount: number;
95
+ failedVerdictCount: number;
96
+ retryConsumedCount: number;
97
+ };
98
+ export type ObservedReviewWorkerLedger = {
99
+ source: "unavailable";
100
+ reconciliationStatus: "unreconciled";
101
+ observedExecutionCount: null;
102
+ } | {
103
+ source: "host_observed";
104
+ reconciliationStatus: "reconciled";
105
+ observedExecutionCount: number;
106
+ };
51
107
  export type Review = {
52
108
  status: "passed" | "failed";
53
109
  summary: string;
@@ -61,6 +117,89 @@ export type ValidationRun = {
61
117
  status: "passed" | "failed";
62
118
  summary: string;
63
119
  };
120
+ export type ValidationEvidence = {
121
+ kind: "validation";
122
+ evidenceId: EvidenceId;
123
+ snapshotId: SnapshotId;
124
+ sourceDigest: string;
125
+ commandClass: ValidationCommandClass;
126
+ startedAt: string;
127
+ completedAt: string;
128
+ exitCode: number;
129
+ outputDigest: string;
130
+ artifactRef?: EvidenceArtifactRef | undefined;
131
+ environmentKeys: string[];
132
+ };
133
+ export type ReviewEvidence = {
134
+ kind: "review";
135
+ evidenceId: EvidenceId;
136
+ snapshotId: SnapshotId;
137
+ sourceDigest: string;
138
+ attemptId: string;
139
+ packetDigest: string;
140
+ startedAt: string;
141
+ completedAt: string;
142
+ };
143
+ export type EvidenceRecord = ValidationEvidence | ReviewEvidence;
144
+ export type CausalMutationRecord = {
145
+ operationId: string;
146
+ operationKind: "plan_save" | "plan_approve" | "run_start" | "review_record" | "evidence_record" | "feature_complete" | "feature_reset" | "session_close";
147
+ requestDigest: string;
148
+ priorMutationDigest: string | null;
149
+ mutationDigest: string;
150
+ priorRevision: number;
151
+ revision: number;
152
+ priorSnapshotId: SnapshotId;
153
+ currentSnapshotId: SnapshotId;
154
+ changedEntity: {
155
+ kind: "session" | "plan" | "feature" | "review" | "evidence" | "closure";
156
+ id: string;
157
+ };
158
+ changedFields: string[];
159
+ blockerDelta: {
160
+ added: string[];
161
+ removed: string[];
162
+ };
163
+ evidenceRefs: EvidenceId[];
164
+ recordedAt: string;
165
+ };
166
+ export type CausalState = {
167
+ revision: number;
168
+ genesisSnapshotId: SnapshotId;
169
+ snapshotId: SnapshotId;
170
+ mutations: CausalMutationRecord[];
171
+ evidence: EvidenceRecord[];
172
+ };
173
+ type ReviewerProjectionRequestBase = {
174
+ featureId: FeatureId;
175
+ packetHash: string;
176
+ evidenceRefs: string[];
177
+ expectedRevision?: number | undefined;
178
+ expectedSnapshotId?: SnapshotId | undefined;
179
+ };
180
+ export type ReviewerProjectionRequest = (ReviewerProjectionRequestBase & {
181
+ reviewKind: "feature";
182
+ }) | (ReviewerProjectionRequestBase & {
183
+ reviewKind: "final";
184
+ });
185
+ type ReviewerProjectionBase = {
186
+ view: "reviewer";
187
+ featureId: FeatureId;
188
+ assignedScope: string[];
189
+ packetHash: string;
190
+ evidenceRefs: string[];
191
+ expectedRevision: number;
192
+ expectedSnapshotId: SnapshotId;
193
+ };
194
+ export type ReviewerProjection = (ReviewerProjectionBase & {
195
+ reviewKind: "feature";
196
+ requiredDepth: FeatureReviewDepth;
197
+ }) | (ReviewerProjectionBase & {
198
+ reviewKind: "final";
199
+ requiredDepth: FinalReviewPolicy;
200
+ requirements: string[];
201
+ decisions: string[];
202
+ });
64
203
  export type Artifact = {
65
204
  path: string;
66
205
  };
@@ -82,6 +221,30 @@ export type Plan = {
82
221
  finalReviewPolicy: FinalReviewPolicy;
83
222
  features: Feature[];
84
223
  };
224
+ export type ExecutionProjection = {
225
+ view: "execution";
226
+ goal: string;
227
+ plan: {
228
+ summary: string;
229
+ overview: string;
230
+ requirements: string[];
231
+ decisions: string[];
232
+ finalReviewPolicy: FinalReviewPolicy;
233
+ };
234
+ feature: {
235
+ id: FeatureId;
236
+ title: string;
237
+ summary: string;
238
+ targets: string[];
239
+ validation: string[];
240
+ dependsOn: FeatureId[];
241
+ reviewDepth: FeatureReviewDepth;
242
+ };
243
+ isFinalFeature: boolean;
244
+ requiredValidationScope: ValidationScope;
245
+ expectedRevision: number;
246
+ expectedSnapshotId: SnapshotId;
247
+ };
85
248
  export type PlanInput = {
86
249
  summary: string;
87
250
  overview: string;
@@ -111,6 +274,11 @@ export type NeedsInputOutcome = {
111
274
  };
112
275
  export type WorkerOutcome = CompletedWorkerOutcome | NeedsInputOutcome;
113
276
  type WorkerResultBase = {
277
+ operationId?: string | undefined;
278
+ expectedRevision?: number | undefined;
279
+ expectedSnapshotId?: SnapshotId | undefined;
280
+ /** Trusted application-boundary digest of the normalized public request. */
281
+ requestDigest?: string | undefined;
114
282
  featureId: FeatureId;
115
283
  summary: string;
116
284
  artifactsChanged: Artifact[];
@@ -119,6 +287,8 @@ type WorkerResultBase = {
119
287
  featureReviewDepth?: FeatureReviewDepth | undefined;
120
288
  featureReview?: Review | undefined;
121
289
  finalReview?: FinalReview | undefined;
290
+ reviewExecutions?: ReviewExecutionInput[] | undefined;
291
+ evidence?: EvidenceRecord[] | undefined;
122
292
  orchestrationPasses: OrchestrationPassRecord[];
123
293
  };
124
294
  export type WorkerResult = (WorkerResultBase & {
@@ -149,6 +319,9 @@ export type BudgetTelemetry = {
149
319
  reviewCount: number;
150
320
  failedReviewCount: number;
151
321
  failedReviewAttemptsByFeature: Record<string, number>;
322
+ reviewExecutions: ReviewExecution[];
323
+ reviewLifecycle: ReviewLifecycleTelemetry;
324
+ observedReviewWorkers: ObservedReviewWorkerLedger;
152
325
  orchestration: OrchestrationTelemetry;
153
326
  };
154
327
  export type Session = {
@@ -161,6 +334,7 @@ export type Session = {
161
334
  activeFeatureId: FeatureId | null;
162
335
  history: ExecutionHistoryEntry[];
163
336
  budget: BudgetTelemetry;
337
+ causal: CausalState;
164
338
  closure: {
165
339
  kind: "completed" | "deferred" | "abandoned";
166
340
  summary: string;
@@ -1,7 +1,9 @@
1
- import type { ExecutionHistoryEntry, Feature, FeatureId, PlanInput, Session, SessionId, WorkerResult } from "./session.js";
1
+ import type { CausalGuard, CausalMutationRecord, EvidenceRecord, ExecutionProjection, Feature, FeatureId, FeatureReviewDepth, PlanInput, ReviewExecution, ReviewExecutionFindingInput, ReviewExecutionInput, ReviewerProjection, ReviewerProjectionRequest, Session, SessionId, SnapshotId, WorkerResult } from "./session.js";
2
+ export declare const MAX_EXECUTION_PROJECTION_BYTES: number;
2
3
  export type TransitionEnvironment = {
3
4
  now(): string;
4
5
  newSessionId(): SessionId;
6
+ newOperationId?(revision: number): string;
5
7
  };
6
8
  export type TransitionResult<T> = {
7
9
  ok: true;
@@ -12,6 +14,25 @@ export type TransitionResult<T> = {
12
14
  recovery?: string;
13
15
  session?: Session;
14
16
  };
17
+ export declare function canonicalOperationRequestDigest(kind: CausalMutationRecord["operationKind"], input: unknown): string;
18
+ export declare function canonicalSessionSnapshotId(session: Session): SnapshotId;
19
+ export declare function canonicalEvidenceId(evidence: EvidenceRecord): string;
20
+ export declare function validateCausalChain(session: Session): string | null;
21
+ export declare function stableReviewFindingFingerprint(finding: ReviewExecutionFindingInput): string;
22
+ export type LogicalReviewPassProjection = {
23
+ logicalPassId: string;
24
+ featureId: FeatureId;
25
+ reviewKind: ReviewExecution["reviewKind"];
26
+ reviewSnapshotId: string;
27
+ latestAttemptId: string;
28
+ verdict: ReviewExecution["verdict"];
29
+ attemptCount: number;
30
+ };
31
+ export declare function projectLogicalReviewPasses(executions: readonly ReviewExecution[]): LogicalReviewPassProjection[];
32
+ export declare function recordReviewExecutions(session: Session, executions: readonly ReviewExecutionInput[], environment: TransitionEnvironment, operationId?: string, guard?: Pick<CausalGuard, "expectedRevision" | "expectedSnapshotId">): TransitionResult<Session>;
33
+ export declare function mergeReviewExecutionsForCompletion(session: Session, executions: readonly ReviewExecutionInput[]): TransitionResult<Session>;
34
+ export declare function mergeEvidenceForCompletion(session: Session, evidenceRecords: readonly EvidenceRecord[]): TransitionResult<Session>;
35
+ export declare function recordEvidence(session: Session, evidenceRecords: readonly EvidenceRecord[], environment: TransitionEnvironment, operationId?: string): TransitionResult<Session>;
15
36
  export declare function createSession(goal: string, environment: TransitionEnvironment): Session;
16
37
  export declare function applyPlan(session: Session, planInput: PlanInput, environment: TransitionEnvironment): TransitionResult<Session>;
17
38
  export declare function approvePlan(session: Session, environment: TransitionEnvironment): TransitionResult<Session>;
@@ -20,61 +41,123 @@ export declare function startRun(session: Session, environment: TransitionEnviro
20
41
  feature: Feature;
21
42
  }>;
22
43
  export declare function completeFeature(session: Session, worker: WorkerResult, environment: TransitionEnvironment): TransitionResult<Session>;
23
- export declare function resetFeature(session: Session, featureId: FeatureId, environment: TransitionEnvironment): TransitionResult<Session>;
24
- export declare function closeSession(session: Session, kind: "completed" | "deferred" | "abandoned", environment: TransitionEnvironment, summary?: string): TransitionResult<Session>;
25
- export declare function summarizeSession(session: Session | null): {
26
- status: "missing_session";
27
- summary: string;
28
- nextAction: string;
29
- statusSummary?: never;
30
- dataNote?: never;
31
- workflowData?: never;
32
- } | {
33
- status: "ok";
34
- summary: string;
35
- statusSummary: string;
44
+ export declare function resetFeature(session: Session, featureId: FeatureId, environment: TransitionEnvironment, guard?: CausalGuard): TransitionResult<Session>;
45
+ export declare function closeSession(session: Session, kind: "completed" | "deferred" | "abandoned", environment: TransitionEnvironment, summary?: string, guard?: CausalGuard): TransitionResult<Session>;
46
+ export declare function serializedUtf8JsonBytes(value: unknown): number;
47
+ export declare function compactSessionProjection(session: Session): {
48
+ view: "compact";
49
+ sessionId: SessionId;
50
+ status: import("./session.js").SessionStatus;
51
+ approval: "approved" | "pending";
52
+ revision: number;
53
+ snapshotId: string;
54
+ feature: {
55
+ id: FeatureId;
56
+ status: import("./session.js").FeatureStatus;
57
+ } | null;
58
+ progress: {
59
+ completed: number;
60
+ total: number;
61
+ remaining: number;
62
+ };
63
+ blockers: {
64
+ featureIds: string[];
65
+ summary: string | null;
66
+ };
67
+ closure: {
68
+ kind: "abandoned" | "completed" | "deferred";
69
+ } | null;
36
70
  nextAction: string;
37
- dataNote: string;
38
- workflowData: {
39
- session: {
40
- sourceSummary: string;
41
- id: SessionId;
42
- goal: string;
43
- status: import("./session.js").SessionStatus;
44
- approval: "approved" | "pending";
45
- activeFeature: Feature | null;
46
- nextFeature: Feature | null;
47
- pendingFeatures: Feature[];
48
- progress: {
49
- completed: number;
50
- total: number;
51
- remaining: number;
52
- };
53
- features: Feature[];
54
- budget: {
55
- reviewCount: number;
56
- failedReviewCount: number;
57
- failedReviewAttemptsByFeature: Record<string, number>;
58
- orchestration: import("./session.js").OrchestrationTelemetry;
59
- };
60
- closure: {
61
- kind: "completed" | "deferred" | "abandoned";
62
- summary: string;
63
- recordedAt: string;
64
- } | null;
65
- lastError: {
66
- tool: string;
67
- summary: string;
68
- recovery?: string | undefined;
69
- recordedAt: string;
70
- } | null;
71
- latestHistoryEntry: ExecutionHistoryEntry | null;
72
- historyCount: number;
73
- timestamps: {
74
- createdAt: string;
75
- updatedAt: string;
76
- completedAt: string | null;
77
- };
71
+ };
72
+ export declare function executionSessionProjection(session: Session): TransitionResult<ExecutionProjection>;
73
+ export declare function detailSessionProjection(session: Session): {
74
+ view: "detail";
75
+ compact: {
76
+ view: "compact";
77
+ sessionId: SessionId;
78
+ status: import("./session.js").SessionStatus;
79
+ approval: "approved" | "pending";
80
+ revision: number;
81
+ snapshotId: string;
82
+ feature: {
83
+ id: FeatureId;
84
+ status: import("./session.js").FeatureStatus;
85
+ } | null;
86
+ progress: {
87
+ completed: number;
88
+ total: number;
89
+ remaining: number;
78
90
  };
91
+ blockers: {
92
+ featureIds: string[];
93
+ summary: string | null;
94
+ };
95
+ closure: {
96
+ kind: "abandoned" | "completed" | "deferred";
97
+ } | null;
98
+ nextAction: string;
99
+ };
100
+ plan: {
101
+ summary: string;
102
+ overview: string;
103
+ requirements: string[];
104
+ decisions: string[];
105
+ finalReviewPolicy: import("./session.js").FinalReviewPolicy;
106
+ features: {
107
+ id: FeatureId;
108
+ title: string;
109
+ summary: string;
110
+ status: import("./session.js").FeatureStatus;
111
+ reviewDepth: FeatureReviewDepth;
112
+ targets: string[];
113
+ dependsOn: FeatureId[];
114
+ }[];
115
+ } | null;
116
+ history: {
117
+ featureId: FeatureId;
118
+ status: "blocked" | "completed" | "needs_input";
119
+ summary: string;
120
+ recordedAt: string;
121
+ validation: {
122
+ status: "failed" | "passed";
123
+ summary: string;
124
+ }[];
125
+ }[];
126
+ causal: {
127
+ revision: number;
128
+ snapshotId: string;
129
+ mutations: CausalMutationRecord[];
130
+ evidence: EvidenceRecord[];
131
+ };
132
+ };
133
+ export declare function reviewerSessionProjection(session: Session, request: ReviewerProjectionRequest): TransitionResult<ReviewerProjection>;
134
+ export declare function mutationReceiptProjection(session: Session, warnings?: readonly string[], operationId?: string): {
135
+ view: "mutation_receipt";
136
+ status: import("./session.js").SessionStatus;
137
+ operationId: string | null;
138
+ revision: number;
139
+ snapshotId: string;
140
+ changedEntity: {
141
+ kind: "session" | "plan" | "feature" | "review" | "evidence" | "closure";
142
+ id: string;
143
+ } | null;
144
+ changedFields: string[];
145
+ blockerDelta: {
146
+ added: string[];
147
+ removed: string[];
79
148
  };
149
+ evidenceRefs: string[];
150
+ warnings: string[];
151
+ nextAction: string;
80
152
  };
153
+ export declare function causalDeltaProjection(session: Session, sinceRevision: number): TransitionResult<{
154
+ view: "delta";
155
+ changed: boolean;
156
+ fromRevision: number;
157
+ throughRevision: number;
158
+ currentRevision: number;
159
+ snapshotId: SnapshotId;
160
+ mutations: CausalMutationRecord[];
161
+ hasMore: boolean;
162
+ nextSinceRevision: number | null;
163
+ }>;
@@ -0,0 +1,8 @@
1
+ export type ValidationCommandClass = "test" | "typecheck" | "lint" | "build" | "format" | "smoke" | "other";
2
+ /**
3
+ * Classify a validation command for evidence matching.
4
+ *
5
+ * Precedence is intentional and preserves the classifier contract previously
6
+ * exposed at the application boundary.
7
+ */
8
+ export declare function validationCommandClass(command: string): ValidationCommandClass;