@xulthekl/team-flow 0.22.4

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.
Files changed (405) hide show
  1. package/.agents/plugins/marketplace.json +20 -0
  2. package/.agents/skills +1 -0
  3. package/.claude/always/phase-guard.md +3 -0
  4. package/.claude-plugin/marketplace.json +20 -0
  5. package/.claude-plugin/plugin.json +31 -0
  6. package/.codex-plugin/plugin.json +45 -0
  7. package/.codexignore +6 -0
  8. package/.cursor-plugin/marketplace.json +17 -0
  9. package/.cursor-plugin/plugin.json +31 -0
  10. package/.github/copilot-instructions.md +15 -0
  11. package/.github/dependabot.yml +10 -0
  12. package/.github/plugin/marketplace.json +42 -0
  13. package/.github/workflows/ci.yml +98 -0
  14. package/.github/workflows/hol-plugin-scanner.yml +17 -0
  15. package/.opencode/INSTALL.md +61 -0
  16. package/.opencode/plugins/team-flow.js +70 -0
  17. package/AGENTS.md +280 -0
  18. package/CHANGELOG.md +635 -0
  19. package/CONTRIBUTING.md +115 -0
  20. package/GEMINI.md +14 -0
  21. package/HANDOFF.md +219 -0
  22. package/INSTALL.md +810 -0
  23. package/LICENSE +21 -0
  24. package/README.md +185 -0
  25. package/SECURITY.md +37 -0
  26. package/agents/bug-investigator.md +180 -0
  27. package/agents/change-split-auditor.md +257 -0
  28. package/agents/code-reviewer.md +171 -0
  29. package/agents/cross-change-consistency-checker.md +215 -0
  30. package/agents/prd-completeness-reviewer.md +197 -0
  31. package/agents/prototype-builder.md +230 -0
  32. package/agents/prototype-env-scout.md +156 -0
  33. package/agents/prototype-reviewer.md +226 -0
  34. package/assets/icon.svg +6 -0
  35. package/dist/index.d.ts +13 -0
  36. package/dist/index.js +5 -0
  37. package/dist/parsing/change-parser.d.ts +12 -0
  38. package/dist/parsing/change-parser.js +54 -0
  39. package/dist/parsing/requirement-blocks.d.ts +31 -0
  40. package/dist/parsing/requirement-blocks.js +192 -0
  41. package/dist/schema/base.d.ts +7 -0
  42. package/dist/schema/base.js +1 -0
  43. package/dist/schema/change.d.ts +25 -0
  44. package/dist/schema/change.js +1 -0
  45. package/dist/schema/index.d.ts +3 -0
  46. package/dist/schema/index.js +1 -0
  47. package/dist/schema/spec.d.ts +11 -0
  48. package/dist/schema/spec.js +1 -0
  49. package/dist/validation/constants.d.ts +42 -0
  50. package/dist/validation/constants.js +42 -0
  51. package/dist/validation/tokenizer.d.ts +17 -0
  52. package/dist/validation/tokenizer.js +173 -0
  53. package/dist/validation/types.d.ts +40 -0
  54. package/dist/validation/types.js +1 -0
  55. package/dist/validation/validator.d.ts +21 -0
  56. package/dist/validation/validator.js +489 -0
  57. package/docs/README_en.md +358 -0
  58. package/docs/artifact-contract.md +96 -0
  59. package/docs/decision-points.md +88 -0
  60. package/docs/e2e-integration-design.md +207 -0
  61. package/docs/examples/README.md +25 -0
  62. package/docs/examples/add-dark-mode/README.md +13 -0
  63. package/docs/examples/add-dark-mode/design.md +49 -0
  64. package/docs/examples/add-dark-mode/execution-contract.md +56 -0
  65. package/docs/examples/add-dark-mode/proposal.md +46 -0
  66. package/docs/examples/add-dark-mode/specs/ui-theme/spec.md +35 -0
  67. package/docs/examples/add-dark-mode/tasks.md +26 -0
  68. package/docs/examples/refactor-auth-boundary/README.md +15 -0
  69. package/docs/examples/refactor-auth-boundary/design.md +41 -0
  70. package/docs/examples/refactor-auth-boundary/execution-contract.md +61 -0
  71. package/docs/examples/refactor-auth-boundary/proposal.md +47 -0
  72. package/docs/examples/refactor-auth-boundary/specs/auth-boundary/spec.md +45 -0
  73. package/docs/examples/refactor-auth-boundary/tasks.md +25 -0
  74. package/docs/plans/2026-07-07-fix-batch-design.md +68 -0
  75. package/docs/plans/2026-07-20-001-refactor-skill-collaboration-protocol-plan.md +128 -0
  76. package/docs/platform-matrix.md +45 -0
  77. package/docs/prototype-design-research.md +206 -0
  78. package/docs/release-checklist.md +96 -0
  79. package/docs/showcase.html +699 -0
  80. package/docs/skill-rename-v0.8.0.md +49 -0
  81. package/docs/state-machine.md +162 -0
  82. package/gemini-extension.json +6 -0
  83. package/hooks/hooks-cursor.json +8 -0
  84. package/hooks/hooks.json +26 -0
  85. package/hooks/pre-tool-use-guard +116 -0
  86. package/hooks/session-start +14 -0
  87. package/llms.txt +51 -0
  88. package/package.json +48 -0
  89. package/plugin.json +27 -0
  90. package/prd/v1/plan.md +443 -0
  91. package/prd/v1/prd.md +580 -0
  92. package/scripts/check-update.mjs +91 -0
  93. package/scripts/check-version-consistency.mjs +345 -0
  94. package/scripts/ensure-branch.mjs +71 -0
  95. package/scripts/get-config +31 -0
  96. package/scripts/guard/checks/artifacts-exist.mjs +36 -0
  97. package/scripts/guard/checks/contract-current.mjs +33 -0
  98. package/scripts/guard/checks/contract-fresh.mjs +17 -0
  99. package/scripts/guard/checks/dp-gate-passed.mjs +35 -0
  100. package/scripts/guard/checks/dp3-approved.mjs +22 -0
  101. package/scripts/guard/checks/execution-plan-ready.mjs +40 -0
  102. package/scripts/guard/checks/execution-reviews-passed.mjs +36 -0
  103. package/scripts/guard/checks/schema-valid.mjs +63 -0
  104. package/scripts/guard/checks/specs-merged.mjs +51 -0
  105. package/scripts/guard/checks/tasks-complete.mjs +31 -0
  106. package/scripts/guard/checks/tests-passing.mjs +31 -0
  107. package/scripts/guard/design-token-guard.mjs +237 -0
  108. package/scripts/guard/guard.mjs +205 -0
  109. package/scripts/infer-workflow.mjs +136 -0
  110. package/scripts/install-amazon-q.mjs +9 -0
  111. package/scripts/install-cline.mjs +9 -0
  112. package/scripts/install-continue.mjs +9 -0
  113. package/scripts/install-cursor.mjs +265 -0
  114. package/scripts/install-git-hooks.mjs +82 -0
  115. package/scripts/install-kiro.mjs +9 -0
  116. package/scripts/install-pi.mjs +9 -0
  117. package/scripts/install-qoder.mjs +9 -0
  118. package/scripts/install-qwen.mjs +9 -0
  119. package/scripts/install-roocode.mjs +9 -0
  120. package/scripts/install-windsurf.mjs +9 -0
  121. package/scripts/install-zcode.mjs +265 -0
  122. package/scripts/lib/cmd-audit.mjs +127 -0
  123. package/scripts/lib/cmd-checkpoint.mjs +118 -0
  124. package/scripts/lib/cmd-config.mjs +88 -0
  125. package/scripts/lib/cmd-doctor.mjs +267 -0
  126. package/scripts/lib/cmd-execution.mjs +206 -0
  127. package/scripts/lib/cmd-handoff.mjs +94 -0
  128. package/scripts/lib/cmd-inject.mjs +310 -0
  129. package/scripts/lib/cmd-install-amazon-q.mjs +11 -0
  130. package/scripts/lib/cmd-install-cline.mjs +11 -0
  131. package/scripts/lib/cmd-install-continue.mjs +11 -0
  132. package/scripts/lib/cmd-install-cursor.mjs +14 -0
  133. package/scripts/lib/cmd-install-kiro.mjs +11 -0
  134. package/scripts/lib/cmd-install-pi.mjs +11 -0
  135. package/scripts/lib/cmd-install-qoder.mjs +11 -0
  136. package/scripts/lib/cmd-install-qwen.mjs +11 -0
  137. package/scripts/lib/cmd-install-roocode.mjs +11 -0
  138. package/scripts/lib/cmd-install-windsurf.mjs +11 -0
  139. package/scripts/lib/cmd-install-workbuddy.mjs +359 -0
  140. package/scripts/lib/cmd-install-zcode.mjs +14 -0
  141. package/scripts/lib/cmd-isolate.mjs +37 -0
  142. package/scripts/lib/cmd-list.mjs +71 -0
  143. package/scripts/lib/cmd-runtime.mjs +85 -0
  144. package/scripts/lib/cmd-solutions.mjs +71 -0
  145. package/scripts/lib/cmd-state.mjs +231 -0
  146. package/scripts/lib/cmd-sync.mjs +102 -0
  147. package/scripts/lib/cmd-validate.mjs +105 -0
  148. package/scripts/lib/cmd-version.mjs +148 -0
  149. package/scripts/lib/config-loader.mjs +107 -0
  150. package/scripts/lib/execution-plan.mjs +492 -0
  151. package/scripts/lib/execution-recommendation.mjs +221 -0
  152. package/scripts/lib/hash.mjs +74 -0
  153. package/scripts/lib/install.mjs +267 -0
  154. package/scripts/lib/platform-runtime-inventory.mjs +27 -0
  155. package/scripts/lib/platforms.mjs +165 -0
  156. package/scripts/lib/prototype-sync.mjs +192 -0
  157. package/scripts/lib/sdd-overlay.mjs +262 -0
  158. package/scripts/lib/shell-quote.mjs +4 -0
  159. package/scripts/lib/solutions-capture.mjs +102 -0
  160. package/scripts/lib/solutions-index-gen.mjs +112 -0
  161. package/scripts/lib/solutions-inject.mjs +77 -0
  162. package/scripts/lib/solutions-promote.mjs +145 -0
  163. package/scripts/lib/spec-paths.mjs +85 -0
  164. package/scripts/lib/state-loader.mjs +154 -0
  165. package/scripts/lint/lint-skills.mjs +149 -0
  166. package/scripts/lint/rules/behavior-consistency.mjs +56 -0
  167. package/scripts/lint/rules/dp-trigger-points.mjs +60 -0
  168. package/scripts/lint/rules/exception-handling.mjs +59 -0
  169. package/scripts/lint/rules/no-contradictory-instructions.mjs +67 -0
  170. package/scripts/lint/rules/no-redundant-checks.mjs +50 -0
  171. package/scripts/lint/rules/token-rules.mjs +122 -0
  172. package/scripts/review-package +44 -0
  173. package/scripts/task-brief +40 -0
  174. package/scripts/team-flow.mjs +164 -0
  175. package/scripts/token-baseline.mjs +158 -0
  176. package/scripts/validate-artifacts +96 -0
  177. package/scripts/verify-marketplace-release.mjs +59 -0
  178. package/skills/architecture-design/SKILL.md +140 -0
  179. package/skills/architecture-design/chapters/ch01-4a-domains.md +27 -0
  180. package/skills/architecture-design/chapters/ch02-change-cascade.md +27 -0
  181. package/skills/architecture-design/chapters/ch03-architecture-outputs.md +25 -0
  182. package/skills/architecture-design/chapters/ch04-entity-to-aggregate.md +27 -0
  183. package/skills/architecture-design/chapters/ch05-cqrs.md +32 -0
  184. package/skills/architecture-design/chapters/ch06-integration.md +54 -0
  185. package/skills/architecture-design/cheatsheet.md +51 -0
  186. package/skills/architecture-design/glossary.md +23 -0
  187. package/skills/architecture-design/patterns.md +32 -0
  188. package/skills/bug-investigator/SKILL.md +77 -0
  189. package/skills/build-executor/SKILL.md +163 -0
  190. package/skills/build-executor/implementer-prompt.md +162 -0
  191. package/skills/build-executor/references/execution-modes.md +86 -0
  192. package/skills/build-executor/task-reviewer-prompt.md +195 -0
  193. package/skills/ce-brainstorm/SKILL.md +415 -0
  194. package/skills/ce-brainstorm/references/agents/slack-researcher.md +127 -0
  195. package/skills/ce-brainstorm/references/blindspot-pass.md +70 -0
  196. package/skills/ce-brainstorm/references/brainstorm-sections.md +285 -0
  197. package/skills/ce-brainstorm/references/handoff.md +168 -0
  198. package/skills/ce-brainstorm/references/html-rendering.md +634 -0
  199. package/skills/ce-brainstorm/references/markdown-rendering.md +241 -0
  200. package/skills/ce-brainstorm/references/model-tiers.md +9 -0
  201. package/skills/ce-brainstorm/references/prd-mapping.md +71 -0
  202. package/skills/ce-brainstorm/references/product-pressure-test.md +42 -0
  203. package/skills/ce-brainstorm/references/reasoning-elevation.md +63 -0
  204. package/skills/ce-brainstorm/references/settled-decisions.md +45 -0
  205. package/skills/ce-brainstorm/references/synthesis-summary.md +282 -0
  206. package/skills/ce-brainstorm/references/universal-brainstorming.md +73 -0
  207. package/skills/ce-brainstorm/references/verdict-routing.md +26 -0
  208. package/skills/ce-brainstorm/references/visual-probes.md +158 -0
  209. package/skills/ce-brainstorm/scripts/visual-probe-server.js +418 -0
  210. package/skills/ce-compound/SKILL.md +114 -0
  211. package/skills/ce-compound/assets/resolution-template.md +94 -0
  212. package/skills/ce-compound/references/agents/best-practices-researcher.md +115 -0
  213. package/skills/ce-compound/references/agents/data-integrity-guardian.md +68 -0
  214. package/skills/ce-compound/references/agents/framework-docs-researcher.md +93 -0
  215. package/skills/ce-compound/references/agents/pattern-recognition-specialist.md +55 -0
  216. package/skills/ce-compound/references/agents/performance-oracle.md +108 -0
  217. package/skills/ce-compound/references/agents/security-sentinel.md +91 -0
  218. package/skills/ce-compound/references/agents/session-historian.md +83 -0
  219. package/skills/ce-compound/references/concepts-vocabulary.md +78 -0
  220. package/skills/ce-compound/references/full-mode-workflow.md +413 -0
  221. package/skills/ce-compound/references/grounding-validation.md +84 -0
  222. package/skills/ce-compound/references/lightweight-mode.md +53 -0
  223. package/skills/ce-compound/references/output-standards.md +182 -0
  224. package/skills/ce-compound/references/promotion-rules.md +38 -0
  225. package/skills/ce-compound/references/schema.yaml +231 -0
  226. package/skills/ce-compound/references/three-tier-index.md +55 -0
  227. package/skills/ce-compound/references/v0.5-upgrade.md +32 -0
  228. package/skills/ce-compound/references/write-flow.md +36 -0
  229. package/skills/ce-compound/references/yaml-schema.md +118 -0
  230. package/skills/ce-compound/scripts/session-history/discover-sessions.sh +130 -0
  231. package/skills/ce-compound/scripts/session-history/extract-errors.py +254 -0
  232. package/skills/ce-compound/scripts/session-history/extract-metadata.py +456 -0
  233. package/skills/ce-compound/scripts/session-history/extract-skeleton.py +575 -0
  234. package/skills/ce-compound/scripts/validate-doc-claims.py +346 -0
  235. package/skills/ce-compound/scripts/validate-frontmatter.py +137 -0
  236. package/skills/ce-ideate/SKILL.md +402 -0
  237. package/skills/ce-ideate/references/agents/issue-intelligence-analyst.md +200 -0
  238. package/skills/ce-ideate/references/agents/learnings-researcher.md +247 -0
  239. package/skills/ce-ideate/references/agents/slack-researcher.md +127 -0
  240. package/skills/ce-ideate/references/agents/web-researcher.md +121 -0
  241. package/skills/ce-ideate/references/divergent-ideation.md +89 -0
  242. package/skills/ce-ideate/references/html-rendering.md +634 -0
  243. package/skills/ce-ideate/references/ideation-sections.md +191 -0
  244. package/skills/ce-ideate/references/markdown-rendering.md +238 -0
  245. package/skills/ce-ideate/references/post-ideation-workflow.md +167 -0
  246. package/skills/ce-ideate/references/universal-ideation.md +107 -0
  247. package/skills/ce-ideate/references/web-research-cache.md +56 -0
  248. package/skills/ce-plan/SKILL.md +137 -0
  249. package/skills/ce-plan/references/agents/agent-native-planning-strategist.md +62 -0
  250. package/skills/ce-plan/references/agents/architecture-strategist.md +46 -0
  251. package/skills/ce-plan/references/agents/best-practices-researcher.md +114 -0
  252. package/skills/ce-plan/references/agents/data-integrity-guardian.md +68 -0
  253. package/skills/ce-plan/references/agents/data-migration-reviewer.md +103 -0
  254. package/skills/ce-plan/references/agents/deployment-verification-agent.md +157 -0
  255. package/skills/ce-plan/references/agents/framework-docs-researcher.md +93 -0
  256. package/skills/ce-plan/references/agents/git-history-analyzer.md +40 -0
  257. package/skills/ce-plan/references/agents/learnings-researcher.md +247 -0
  258. package/skills/ce-plan/references/agents/pattern-recognition-specialist.md +55 -0
  259. package/skills/ce-plan/references/agents/performance-oracle.md +108 -0
  260. package/skills/ce-plan/references/agents/repo-research-analyst.md +258 -0
  261. package/skills/ce-plan/references/agents/security-sentinel.md +91 -0
  262. package/skills/ce-plan/references/agents/slack-researcher.md +127 -0
  263. package/skills/ce-plan/references/agents/spec-flow-analyzer.md +80 -0
  264. package/skills/ce-plan/references/agents/web-researcher.md +121 -0
  265. package/skills/ce-plan/references/approach-altitude.md +55 -0
  266. package/skills/ce-plan/references/change-splitting.md +65 -0
  267. package/skills/ce-plan/references/completion-contract.md +33 -0
  268. package/skills/ce-plan/references/core-principles.md +40 -0
  269. package/skills/ce-plan/references/deepening-workflow.md +263 -0
  270. package/skills/ce-plan/references/dependency-graph.md +36 -0
  271. package/skills/ce-plan/references/html-rendering.md +634 -0
  272. package/skills/ce-plan/references/intake-routing.md +189 -0
  273. package/skills/ce-plan/references/markdown-rendering.md +238 -0
  274. package/skills/ce-plan/references/plan-handoff.md +150 -0
  275. package/skills/ce-plan/references/plan-sections.md +427 -0
  276. package/skills/ce-plan/references/plan-structure.md +120 -0
  277. package/skills/ce-plan/references/planning-modes.md +69 -0
  278. package/skills/ce-plan/references/reasoning-elevation.md +63 -0
  279. package/skills/ce-plan/references/research-workflow.md +165 -0
  280. package/skills/ce-plan/references/review-and-write.md +127 -0
  281. package/skills/ce-plan/references/settled-decisions.md +45 -0
  282. package/skills/ce-plan/references/synthesis-summary.md +418 -0
  283. package/skills/ce-plan/references/universal-planning.md +168 -0
  284. package/skills/ce-proof/SKILL.md +346 -0
  285. package/skills/ce-strategy/SKILL.md +97 -0
  286. package/skills/ce-strategy/references/interview.md +143 -0
  287. package/skills/ce-strategy/references/strategy-template.md +89 -0
  288. package/skills/code-reviewer/SKILL.md +84 -0
  289. package/skills/code-reviewer/code-reviewer-prompt.md +195 -0
  290. package/skills/contract-builder/SKILL.md +72 -0
  291. package/skills/design-system/SKILL.md +75 -0
  292. package/skills/design-system/references/agents/design-system-architect.md +138 -0
  293. package/skills/design-system/references/creation-flow.md +170 -0
  294. package/skills/design-system/references/preview-template.html +319 -0
  295. package/skills/design-system/references/token-derivation.md +115 -0
  296. package/skills/design-system/references/variant-schema.md +60 -0
  297. package/skills/e2e/SKILL.md +56 -0
  298. package/skills/e2e/references/test-verifier.md +40 -0
  299. package/skills/need-explorer/SKILL.md +79 -0
  300. package/skills/prototype/SKILL.md +98 -0
  301. package/skills/prototype/references/agents/design-system-architect.md +122 -0
  302. package/skills/prototype/references/checklist.md +82 -0
  303. package/skills/prototype/references/craft/accessibility-baseline.md +71 -0
  304. package/skills/prototype/references/craft/anti-ai-slop.md +87 -0
  305. package/skills/prototype/references/craft/laws-of-ux.md +60 -0
  306. package/skills/prototype/references/craft/state-coverage.md +81 -0
  307. package/skills/prototype/references/craft/typography-hierarchy.md +50 -0
  308. package/skills/prototype/references/layouts.md +223 -0
  309. package/skills/prototype/references/orchestration-flow.md +101 -0
  310. package/skills/prototype/references/prototype-scaffold/assets/design-tokens.css +19 -0
  311. package/skills/prototype/references/prototype-scaffold/components/button.html +3 -0
  312. package/skills/prototype/references/prototype-scaffold/design-system.md +7 -0
  313. package/skills/prototype/references/prototype-scaffold/flow.md +11 -0
  314. package/skills/prototype/references/prototype-scaffold/index.html +20 -0
  315. package/skills/prototype/references/prototype-scaffold/pages/index.html +11 -0
  316. package/skills/prototype/references/template.html +396 -0
  317. package/skills/release-archivist/SKILL.md +166 -0
  318. package/skills/release-archivist/references/closing-procedures.md +81 -0
  319. package/skills/session-handoff/SKILL.md +110 -0
  320. package/skills/session-handoff/references/context-extraction.md +70 -0
  321. package/skills/session-handoff/references/handoff-template.md +90 -0
  322. package/skills/session-handoff/references/skill-recommendation.md +43 -0
  323. package/skills/spec-merger/SKILL.md +66 -0
  324. package/skills/spec-writer/SKILL.md +149 -0
  325. package/skills/workflow-bootstrap/SKILL.md +148 -0
  326. package/skills/workflow-bootstrap/references/agents/codebase-recon-analyst.md +121 -0
  327. package/skills/workflow-bootstrap/references/b1-reconnaissance.md +80 -0
  328. package/skills/workflow-bootstrap/scripts/recon-probe.sh +328 -0
  329. package/skills/workflow-feedback/SKILL.md +120 -0
  330. package/skills/workflow-feedback/references/category-guide.md +121 -0
  331. package/skills/workflow-feedback/references/feedback-template.md +73 -0
  332. package/skills/workflow-feedback/references/review-mode.md +92 -0
  333. package/skills/workflow-orchestrator/SKILL.md +94 -0
  334. package/skills/workflow-orchestrator/references/feedback-loops.md +56 -0
  335. package/skills/workflow-orchestrator/references/s1-path-router.md +81 -0
  336. package/skills/workflow-orchestrator/references/s2-prd-prototype-loop.md +96 -0
  337. package/skills/workflow-orchestrator/references/s3-plan-pipeline.md +50 -0
  338. package/skills/workflow-orchestrator/references/s4-split-validate.md +108 -0
  339. package/skills/workflow-orchestrator/references/s5-monitoring.md +61 -0
  340. package/skills/workflow-orchestrator/references/state-model.md +185 -0
  341. package/skills/workflow-start/SKILL.md +147 -0
  342. package/skills/workflow-start/references/routing-rules.md +155 -0
  343. package/src/index.ts +16 -0
  344. package/src/parsing/change-parser.ts +79 -0
  345. package/src/parsing/requirement-blocks.ts +244 -0
  346. package/src/schema/base.ts +8 -0
  347. package/src/schema/change.ts +29 -0
  348. package/src/schema/index.ts +3 -0
  349. package/src/schema/spec.ts +12 -0
  350. package/src/validation/constants.ts +53 -0
  351. package/src/validation/tokenizer.ts +180 -0
  352. package/src/validation/types.ts +47 -0
  353. package/src/validation/validator.ts +552 -0
  354. package/templates/abandonment-summary.md +29 -0
  355. package/templates/design.md +37 -0
  356. package/templates/execution-contract.md +99 -0
  357. package/templates/plan.md +86 -0
  358. package/templates/prd.md +468 -0
  359. package/templates/proposal.md +37 -0
  360. package/templates/spec.md +31 -0
  361. package/templates/tasks.md +47 -0
  362. package/tests/e2e.test.mjs +266 -0
  363. package/tests/lib/cmd-audit.test.mjs +202 -0
  364. package/tests/lib/cmd-checkpoint.test.mjs +98 -0
  365. package/tests/lib/cmd-config.test.mjs +101 -0
  366. package/tests/lib/cmd-doctor.test.mjs +450 -0
  367. package/tests/lib/cmd-execution.test.mjs +647 -0
  368. package/tests/lib/cmd-handoff.test.mjs +137 -0
  369. package/tests/lib/cmd-inject.test.mjs +218 -0
  370. package/tests/lib/cmd-install-workbuddy.test.mjs +113 -0
  371. package/tests/lib/cmd-install-zcode.test.mjs +42 -0
  372. package/tests/lib/cmd-isolate.test.mjs +68 -0
  373. package/tests/lib/cmd-list.test.mjs +127 -0
  374. package/tests/lib/cmd-runtime.test.mjs +83 -0
  375. package/tests/lib/cmd-state-missing.test.mjs +65 -0
  376. package/tests/lib/cmd-state.test.mjs +365 -0
  377. package/tests/lib/cmd-sync-paths.test.mjs +84 -0
  378. package/tests/lib/cmd-validate-paths.test.mjs +90 -0
  379. package/tests/lib/config-loader.test.mjs +175 -0
  380. package/tests/lib/ensure-branch.test.mjs +59 -0
  381. package/tests/lib/execution-control-plane.test.mjs +168 -0
  382. package/tests/lib/execution-plan.test.mjs +474 -0
  383. package/tests/lib/guard-specs-merged.test.mjs +108 -0
  384. package/tests/lib/guard-tests-passing.test.mjs +112 -0
  385. package/tests/lib/guard-transitions.test.mjs +262 -0
  386. package/tests/lib/guard.test.mjs +611 -0
  387. package/tests/lib/hash.test.mjs +138 -0
  388. package/tests/lib/infer-workflow.test.mjs +161 -0
  389. package/tests/lib/install-git-hooks.test.mjs +20 -0
  390. package/tests/lib/marketplace-release-docs.test.mjs +31 -0
  391. package/tests/lib/minimality-discipline.test.mjs +37 -0
  392. package/tests/lib/model-profiles-docs.test.mjs +33 -0
  393. package/tests/lib/node20-compatibility.test.mjs +73 -0
  394. package/tests/lib/node20-test-entry.test.mjs +17 -0
  395. package/tests/lib/platform-runtime-distribution.test.mjs +150 -0
  396. package/tests/lib/raw-mode-smoke.test.mjs +42 -0
  397. package/tests/lib/sdd-overlay.test.mjs +118 -0
  398. package/tests/lib/spec-paths.test.mjs +80 -0
  399. package/tests/lib/state-loader.test.mjs +251 -0
  400. package/tests/lib/token-baseline.test.mjs +72 -0
  401. package/tests/lib/token-rules.test.mjs +94 -0
  402. package/tests/lib/verify-marketplace-release.test.mjs +128 -0
  403. package/tests/tsconfig.json +12 -0
  404. package/token-baseline.json +95 -0
  405. package/tsconfig.json +14 -0
@@ -0,0 +1,456 @@
1
+ #!/usr/bin/env python3
2
+ """Extract session metadata from Claude Code, Codex, Cursor, and Pi JSONL files.
3
+
4
+ Batch mode (preferred — one invocation for all files):
5
+ python3 extract-metadata.py /path/to/dir/*.jsonl
6
+ python3 extract-metadata.py file1.jsonl file2.jsonl file3.jsonl
7
+
8
+ Single-file mode (stdin):
9
+ head -20 <session.jsonl> | python3 extract-metadata.py
10
+
11
+ Auto-detects platform from the JSONL structure.
12
+ Outputs one JSON object per file, one per line.
13
+ Includes a final _meta line with processing stats.
14
+ """
15
+ import sys
16
+ import json
17
+ import os
18
+
19
+ MAX_LINES = 25 # Only need first ~25 lines for metadata
20
+
21
+
22
+ def try_claude(lines):
23
+ for line in lines:
24
+ try:
25
+ obj = json.loads(line.strip())
26
+ if obj.get("type") == "user" and "gitBranch" in obj:
27
+ return {
28
+ "platform": "claude",
29
+ "branch": obj["gitBranch"],
30
+ "ts": obj.get("timestamp", ""),
31
+ "session": obj.get("sessionId", ""),
32
+ }
33
+ except (json.JSONDecodeError, KeyError):
34
+ pass
35
+ return None
36
+
37
+
38
+ def try_codex(lines):
39
+ meta = {}
40
+ for line in lines:
41
+ try:
42
+ obj = json.loads(line.strip())
43
+ if obj.get("type") == "session_meta":
44
+ p = obj.get("payload", {})
45
+ meta["platform"] = "codex"
46
+ meta["cwd"] = p.get("cwd", "")
47
+ meta["session"] = p.get("id", "")
48
+ meta["ts"] = p.get("timestamp", obj.get("timestamp", ""))
49
+ meta["source"] = p.get("source", "")
50
+ meta["cli_version"] = p.get("cli_version", "")
51
+ elif obj.get("type") == "turn_context":
52
+ p = obj.get("payload", {})
53
+ meta["model"] = p.get("model", "")
54
+ meta["cwd"] = meta.get("cwd") or p.get("cwd", "")
55
+ except (json.JSONDecodeError, KeyError):
56
+ pass
57
+ return meta if meta else None
58
+
59
+
60
+ def try_pi(lines):
61
+ """Pi sessions: type='session' header with cwd, followed by message entries."""
62
+ for line in lines:
63
+ try:
64
+ obj = json.loads(line.strip())
65
+ if obj.get("type") == "session" and "cwd" in obj:
66
+ return {
67
+ "platform": "pi",
68
+ "cwd": obj.get("cwd", ""),
69
+ "session": obj.get("id", ""),
70
+ "ts": obj.get("timestamp", ""),
71
+ }
72
+ except (json.JSONDecodeError, KeyError):
73
+ pass
74
+ return None
75
+
76
+
77
+ def try_cursor(lines):
78
+ """Cursor agent transcripts: role-based entries, no timestamps or metadata fields."""
79
+ for line in lines:
80
+ try:
81
+ obj = json.loads(line.strip())
82
+ # Cursor entries have 'role' at top level but no 'type'
83
+ if obj.get("role") in ("user", "assistant") and "type" not in obj:
84
+ return {"platform": "cursor"}
85
+ except (json.JSONDecodeError, KeyError):
86
+ pass
87
+ return None
88
+
89
+
90
+ def extract_from_lines(lines):
91
+ return try_claude(lines) or try_codex(lines) or try_pi(lines) or try_cursor(lines)
92
+
93
+
94
+ TAIL_BYTES = 16384 # Read last 16KB to find final timestamp past trailing metadata
95
+
96
+
97
+ def get_last_timestamp(filepath, size):
98
+ """Read the tail of a file to find the last message with a timestamp."""
99
+ try:
100
+ with open(filepath, "rb") as f:
101
+ f.seek(max(0, size - TAIL_BYTES))
102
+ tail = f.read().decode("utf-8", errors="ignore")
103
+ lines = tail.strip().split("\n")
104
+ for line in reversed(lines):
105
+ try:
106
+ obj = json.loads(line.strip())
107
+ if "timestamp" in obj:
108
+ return obj["timestamp"]
109
+ except (json.JSONDecodeError, KeyError):
110
+ pass
111
+ except (OSError, IOError):
112
+ pass
113
+ return None
114
+
115
+
116
+ def _pi_active_path_objects(objects):
117
+ """Return only entries on Pi's active leaf-to-root path.
118
+
119
+ Pi session files are append-only trees. The final non-session entry is the
120
+ active leaf; abandoned branches remain in the file but are not in context.
121
+ """
122
+ by_id = {
123
+ obj.get("id"): obj
124
+ for obj in objects
125
+ if isinstance(obj.get("id"), str) and obj.get("type") != "session"
126
+ }
127
+ leaf_id = None
128
+ for obj in objects:
129
+ if obj.get("type") != "session" and isinstance(obj.get("id"), str):
130
+ leaf_id = obj["id"]
131
+ if not leaf_id:
132
+ return objects
133
+
134
+ active_ids = set()
135
+ current = leaf_id
136
+ while isinstance(current, str) and current and current not in active_ids:
137
+ active_ids.add(current)
138
+ parent = by_id.get(current, {}).get("parentId")
139
+ current = parent if isinstance(parent, str) else None
140
+ return [
141
+ obj
142
+ for obj in objects
143
+ if obj.get("type") == "session" or obj.get("id") in active_ids
144
+ ]
145
+
146
+
147
+ def _pi_context_objects(objects):
148
+ """Return Pi entries that participate in active LLM context."""
149
+ active = _pi_active_path_objects(objects)
150
+ compactions = [obj for obj in active if obj.get("type") == "compaction"]
151
+ if not compactions:
152
+ return active
153
+
154
+ # Pi emits compaction summary first, then entries from firstKeptEntryId
155
+ # onward. Exclude older ancestors so keyword search mirrors context.
156
+ first_kept = compactions[-1].get("firstKeptEntryId")
157
+ if not isinstance(first_kept, str):
158
+ return active
159
+
160
+ latest_compaction_id = compactions[-1].get("id")
161
+ started = False
162
+ found_first_kept = False
163
+ context = [obj for obj in active if obj.get("type") == "session"]
164
+ context.append(compactions[-1])
165
+ for obj in active:
166
+ if obj.get("type") == "session":
167
+ continue
168
+ if obj.get("id") == first_kept:
169
+ started = True
170
+ found_first_kept = True
171
+ if obj.get("id") == latest_compaction_id:
172
+ continue
173
+ if started:
174
+ context.append(obj)
175
+ return context if found_first_kept and len(context) > 1 else active
176
+
177
+
178
+ def _append_pi_content_text(chunks, content):
179
+ if isinstance(content, str):
180
+ chunks.append(content)
181
+ elif isinstance(content, list):
182
+ for block in content:
183
+ if isinstance(block, dict) and block.get("type") == "text":
184
+ chunks.append(block.get("text", ""))
185
+
186
+
187
+ def _append_pi_tool_call_targets(chunks, content):
188
+ """Append searchable Pi toolCall targets without indexing tool output."""
189
+ if not isinstance(content, list):
190
+ return
191
+ for block in content:
192
+ if not isinstance(block, dict) or block.get("type") != "toolCall":
193
+ continue
194
+ args = block.get("arguments", {})
195
+ if not isinstance(args, dict):
196
+ continue
197
+ for key in ("path", "file_path", "command", "pattern", "query", "prompt"):
198
+ value = args.get(key)
199
+ if isinstance(value, str):
200
+ chunks.append(value)
201
+
202
+
203
+ def _extract_user_assistant_text(filepath):
204
+ """Return concatenated user + assistant text content from a session JSONL.
205
+
206
+ Skips JSONL metadata field names and values (sessionId, gitBranch, uuid,
207
+ timestamps, type tags), tool_use blocks (tool names + tool inputs),
208
+ tool_result blocks (tool outputs), and thinking/reasoning blocks. Only
209
+ content the user or assistant actually said is included.
210
+
211
+ Without this filtering, common topic words like "session" would match every
212
+ JSONL file via the sessionId field, drowning out real content matches.
213
+ """
214
+ chunks = []
215
+ try:
216
+ objects = []
217
+ with open(filepath, "r", errors="replace") as f:
218
+ for line in f:
219
+ try:
220
+ objects.append(json.loads(line.strip()))
221
+ except (json.JSONDecodeError, ValueError):
222
+ continue
223
+
224
+ is_pi = any(
225
+ obj.get("type") == "session" and "cwd" in obj for obj in objects
226
+ )
227
+ if is_pi:
228
+ objects = _pi_context_objects(objects)
229
+
230
+ for obj in objects:
231
+ # Claude Code: type-tagged top-level
232
+ t = obj.get("type")
233
+ if t == "user":
234
+ msg = obj.get("message", {})
235
+ content = msg.get("content")
236
+ if isinstance(content, str):
237
+ chunks.append(content)
238
+ elif isinstance(content, list):
239
+ for block in content:
240
+ if isinstance(block, dict) and block.get("type") == "text":
241
+ chunks.append(block.get("text", ""))
242
+ # Skip tool_result blocks — tool outputs are not user content.
243
+ continue
244
+ if t == "assistant":
245
+ msg = obj.get("message", {})
246
+ content = msg.get("content", [])
247
+ if isinstance(content, list):
248
+ for block in content:
249
+ if isinstance(block, dict) and block.get("type") == "text":
250
+ chunks.append(block.get("text", ""))
251
+ # Skip tool_use and thinking blocks.
252
+ continue
253
+
254
+ # Codex: payload-typed events
255
+ if t == "event_msg":
256
+ p = obj.get("payload", {})
257
+ if p.get("type") == "user_message":
258
+ # Strip Codex/Conductor `<system_instruction>...</system_instruction>`
259
+ # wrapper before counting. Without this, generic wrapper terms
260
+ # (e.g., "Conductor", environment labels) false-match against
261
+ # boilerplate the user did not author. Mirrors the same split
262
+ # used in ce-session-extract/scripts/extract-skeleton.py.
263
+ msg = p.get("message", "")
264
+ if isinstance(msg, str):
265
+ parts = msg.split("</system_instruction>")
266
+ chunks.append(parts[-1] if parts else msg)
267
+ continue
268
+ if t == "response_item":
269
+ p = obj.get("payload", {})
270
+ if p.get("type") == "message" and p.get("role") == "assistant":
271
+ for block in p.get("content", []):
272
+ if isinstance(block, dict) and block.get("type") == "output_text":
273
+ chunks.append(block.get("text", ""))
274
+ continue
275
+
276
+ # Pi: type='message' envelope with AgentMessage under message.
277
+ if t == "message" and "message" in obj:
278
+ msg = obj.get("message", {})
279
+ role = msg.get("role", "")
280
+ if role == "bashExecution":
281
+ command = msg.get("command", "")
282
+ if isinstance(command, str):
283
+ chunks.append(command)
284
+ # Search command text only. Output is tool output and can
285
+ # be large/noisy in the same way as toolResult content.
286
+ continue
287
+ content = msg.get("content", [])
288
+ if role == "custom":
289
+ _append_pi_content_text(chunks, content)
290
+ continue
291
+ if role not in ("user", "assistant"):
292
+ continue
293
+ _append_pi_content_text(chunks, content)
294
+ if role == "assistant":
295
+ _append_pi_tool_call_targets(chunks, content)
296
+ continue
297
+
298
+ if t in ("compaction", "branch_summary"):
299
+ summary = obj.get("summary", "")
300
+ if isinstance(summary, str):
301
+ chunks.append(summary)
302
+ continue
303
+
304
+ if t == "custom_message":
305
+ _append_pi_content_text(chunks, obj.get("content", []))
306
+ continue
307
+
308
+ # Cursor: role-tagged with no top-level type
309
+ if obj.get("role") in ("user", "assistant") and "type" not in obj:
310
+ msg = obj.get("message", {})
311
+ for block in msg.get("content", []) if isinstance(msg.get("content"), list) else []:
312
+ if isinstance(block, dict) and block.get("type") == "text":
313
+ chunks.append(block.get("text", ""))
314
+ continue
315
+ except (OSError, IOError):
316
+ pass
317
+ return "\n".join(chunks)
318
+
319
+
320
+ def count_keyword_matches(filepath, keywords):
321
+ """Case-insensitive substring count for each keyword in user/assistant text.
322
+
323
+ Returns a dict {original_keyword: count}. Scans only content the user or
324
+ assistant said — not JSONL metadata, tool calls, tool outputs, or thinking
325
+ blocks — so common topic words like "session" do not false-match against
326
+ the sessionId field.
327
+ """
328
+ text_lower = _extract_user_assistant_text(filepath).lower()
329
+ return {kw: text_lower.count(kw.lower()) for kw in keywords}
330
+
331
+
332
+ def process_file(filepath):
333
+ """Extract metadata only. Keyword scanning is done separately so callers
334
+ can apply cheap filters (e.g. --cwd-filter) before paying the full-file
335
+ content scan cost."""
336
+ try:
337
+ size = os.path.getsize(filepath)
338
+ with open(filepath, "r") as f:
339
+ lines = []
340
+ for i, line in enumerate(f):
341
+ if i >= MAX_LINES:
342
+ break
343
+ lines.append(line)
344
+ result = extract_from_lines(lines)
345
+ if result:
346
+ result["file"] = filepath
347
+ result["size"] = size
348
+ if result["platform"] == "cursor":
349
+ # Cursor transcripts have no timestamps in JSONL.
350
+ # Use file modification time as the best available signal.
351
+ # Derive session ID from the parent directory name (UUID).
352
+ mtime = os.path.getmtime(filepath)
353
+ from datetime import datetime, timezone
354
+
355
+ result["ts"] = datetime.fromtimestamp(mtime, tz=timezone.utc).isoformat()
356
+ result["session"] = os.path.basename(os.path.dirname(filepath))
357
+ else:
358
+ last_ts = get_last_timestamp(filepath, size)
359
+ if last_ts:
360
+ result["last_ts"] = last_ts
361
+ return result, None
362
+ else:
363
+ return None, filepath
364
+ except (OSError, IOError) as e:
365
+ return None, filepath
366
+
367
+
368
+ def cwd_matches_filter(session_cwd, cwd_filter):
369
+ if not session_cwd or not cwd_filter:
370
+ return True
371
+ if os.path.isabs(cwd_filter):
372
+ return os.path.normpath(session_cwd) == os.path.normpath(cwd_filter)
373
+ return cwd_filter in session_cwd
374
+
375
+
376
+ # Parse arguments: files and optional --cwd-filter / --keyword
377
+ files = []
378
+ cwd_filter = None
379
+ keywords = None
380
+ args = sys.argv[1:]
381
+ i = 0
382
+ while i < len(args):
383
+ if args[i] == "--cwd-filter" and i + 1 < len(args):
384
+ cwd_filter = args[i + 1]
385
+ i += 2
386
+ elif args[i] == "--keyword" and i + 1 < len(args):
387
+ keywords = [k for k in args[i + 1].split(",") if k]
388
+ i += 2
389
+ elif not args[i].startswith("-"):
390
+ files.append(args[i])
391
+ i += 1
392
+ else:
393
+ i += 1
394
+
395
+ if files:
396
+ # Batch mode: process all files
397
+ processed = 0
398
+ parse_errors = 0
399
+ filtered = 0
400
+ matched = 0
401
+ for filepath in files:
402
+ if not filepath.endswith(".jsonl"):
403
+ continue
404
+ result, error = process_file(filepath)
405
+ processed += 1
406
+ if result:
407
+ # Apply CWD filter first: cheap metadata-only check. Skip Codex
408
+ # sessions from other repos before paying the full-file keyword
409
+ # scan cost — Codex discovery returns sessions across all repos,
410
+ # so without this ordering --keyword would scan files that are
411
+ # immediately discarded.
412
+ if cwd_filter and result.get("cwd") and not cwd_matches_filter(result["cwd"], cwd_filter):
413
+ filtered += 1
414
+ continue
415
+ # Apply keyword scan only after cheap filters pass.
416
+ if keywords:
417
+ matches = count_keyword_matches(filepath, keywords)
418
+ result["keyword_matches"] = matches
419
+ result["match_count"] = sum(matches.values())
420
+ if result["match_count"] == 0:
421
+ continue
422
+ matched += 1
423
+ print(json.dumps(result))
424
+ elif error:
425
+ parse_errors += 1
426
+
427
+ meta = {"_meta": True, "files_processed": processed, "parse_errors": parse_errors}
428
+ if filtered:
429
+ meta["filtered_by_cwd"] = filtered
430
+ if keywords:
431
+ meta["files_matched"] = matched
432
+ print(json.dumps(meta))
433
+ else:
434
+ # No file arguments: either single-file stdin mode or empty xargs invocation.
435
+ # When xargs runs us with no input (e.g., discover found no files), stdin is
436
+ # empty or a TTY — emit a clean zero-file result instead of a false parse error.
437
+ if sys.stdin.isatty():
438
+ lines = []
439
+ else:
440
+ lines = list(sys.stdin)
441
+
442
+ if not lines:
443
+ # No input at all — zero-file result (clean exit for empty pipelines).
444
+ # When --keyword was supplied, emit files_matched: 0 so callers relying
445
+ # on its presence to terminate quickly in zero-match scans see a
446
+ # consistent shape with the batch-mode no-match case.
447
+ meta = {"_meta": True, "files_processed": 0, "parse_errors": 0}
448
+ if keywords:
449
+ meta["files_matched"] = 0
450
+ print(json.dumps(meta))
451
+ else:
452
+ # Genuine single-file stdin mode (backward compatible)
453
+ result = extract_from_lines(lines)
454
+ if result:
455
+ print(json.dumps(result))
456
+ print(json.dumps({"_meta": True, "files_processed": 1, "parse_errors": 0 if result else 1}))