@hassangameryt/freeflow 0.8.0 → 0.9.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.
Files changed (290) hide show
  1. package/.agents/plugins/marketplace.json +2 -2
  2. package/.claude-plugin/marketplace.json +1 -1
  3. package/.claude-plugin/plugin.json +2 -2
  4. package/.codex-plugin/plugin.json +3 -3
  5. package/.cursor-plugin/plugin.json +1 -1
  6. package/README.md +96 -149
  7. package/capabilities/cognitive-routing/SKILL.md +21 -129
  8. package/capabilities/cognitive-routing/references/coordinator.md +163 -0
  9. package/capabilities/cognitive-routing/references/worker.md +38 -0
  10. package/capabilities/compaction/SKILL.md +3 -3
  11. package/capabilities/compaction/references/summary-format.md +26 -15
  12. package/capabilities/messaging/SKILL.md +49 -0
  13. package/capabilities/task-memory/SKILL.md +87 -0
  14. package/command-surface.json +6 -54
  15. package/gemini-extension.json +1 -1
  16. package/hooks/claude/hooks.json +13 -3
  17. package/hooks/codex/hooks.json +2 -1
  18. package/hooks/shared/runtime-context.mjs +69 -77
  19. package/package.json +25 -8
  20. package/pi-extension/dist/ask-user/ask.js +108 -0
  21. package/pi-extension/dist/ask-user/form.js +250 -0
  22. package/pi-extension/dist/ask-user/questions.js +66 -0
  23. package/pi-extension/dist/ask-user/tool.js +124 -0
  24. package/pi-extension/dist/cognitive-routing/assembler.js +35 -11
  25. package/pi-extension/dist/cognitive-routing/bootstrap.js +90 -0
  26. package/pi-extension/dist/cognitive-routing/config.js +3 -4
  27. package/pi-extension/dist/cognitive-routing/event-store.js +4 -1
  28. package/pi-extension/dist/cognitive-routing/gate.js +20 -5
  29. package/pi-extension/dist/cognitive-routing/handlers.js +15 -13
  30. package/pi-extension/dist/cognitive-routing/model-control.js +17 -8
  31. package/pi-extension/dist/cognitive-routing/projection.js +23 -6
  32. package/pi-extension/dist/cognitive-routing/provenance.js +3 -1
  33. package/pi-extension/dist/cognitive-routing/render.js +15 -15
  34. package/pi-extension/dist/cognitive-routing/runtime.js +4 -2
  35. package/pi-extension/dist/cognitive-routing/schemas.js +4 -4
  36. package/pi-extension/dist/cognitive-routing/session.js +3 -1
  37. package/pi-extension/dist/cognitive-routing/sources.js +29 -4
  38. package/pi-extension/dist/cognitive-routing/state.js +18 -8
  39. package/pi-extension/dist/cognitive-routing/status.js +4 -3
  40. package/pi-extension/dist/cognitive-routing/tools.js +29 -15
  41. package/pi-extension/dist/cognitive-routing/types.js +10 -1
  42. package/pi-extension/dist/compaction/carry.js +36 -22
  43. package/pi-extension/dist/compaction/config.js +4 -2
  44. package/pi-extension/dist/compaction/controller.js +52 -29
  45. package/pi-extension/dist/compaction/harness.js +19 -3
  46. package/pi-extension/dist/compaction/results.js +14 -13
  47. package/pi-extension/dist/compaction/tool.js +6 -6
  48. package/pi-extension/dist/host/catalog.js +20 -35
  49. package/pi-extension/dist/host/config-validation.js +233 -0
  50. package/pi-extension/dist/host/config.js +78 -91
  51. package/pi-extension/dist/host/inbound.js +142 -0
  52. package/pi-extension/dist/host/projection-tags.js +1 -1
  53. package/pi-extension/dist/host/prompts.js +24 -13
  54. package/pi-extension/dist/host/read-only-session.js +6 -1
  55. package/pi-extension/dist/host/request-history.js +7 -3
  56. package/pi-extension/dist/host/rows.js +25 -0
  57. package/pi-extension/dist/host/runtime-state.js +17 -2
  58. package/pi-extension/dist/host/section-keeper.js +85 -0
  59. package/pi-extension/dist/host/settings/freeflow-command.js +846 -93
  60. package/pi-extension/dist/host/settings/settings-view.js +27 -8
  61. package/pi-extension/dist/host/status.js +19 -5
  62. package/pi-extension/dist/index.js +638 -72
  63. package/pi-extension/dist/messaging/config.js +27 -0
  64. package/pi-extension/dist/messaging/messaging.js +398 -0
  65. package/pi-extension/dist/messaging/registry.js +57 -0
  66. package/pi-extension/dist/messaging/render.js +90 -0
  67. package/pi-extension/dist/messaging/tools.js +109 -0
  68. package/pi-extension/dist/messaging/transport.js +101 -0
  69. package/pi-extension/dist/provider-support/cache/keepalive.js +16 -4
  70. package/pi-extension/dist/task-memory/config.js +49 -0
  71. package/pi-extension/dist/task-memory/registry.js +119 -0
  72. package/pi-extension/dist/task-memory/render.js +107 -0
  73. package/pi-extension/dist/task-memory/runtime.js +994 -0
  74. package/pi-extension/dist/task-memory/tool.js +233 -0
  75. package/pi-extension/dist/tool-execution/apply-patch/tool.js +1 -1
  76. package/pi-extension/dist/tool-execution/background.js +220 -28
  77. package/pi-extension/dist/tool-execution/config.js +14 -3
  78. package/pi-extension/dist/tool-execution/file-tracking.js +24 -4
  79. package/pi-extension/dist/tool-execution/guidance-notices.js +124 -0
  80. package/pi-extension/dist/tool-execution/skill-reads.js +143 -0
  81. package/pi-extension/dist/tool-execution/tools.js +2 -2
  82. package/runtime/prompts/cognitive-routing.md +4 -4
  83. package/runtime/prompts/core.md +24 -14
  84. package/runtime/prompts/interaction-contract.md +7 -4
  85. package/runtime/prompts/tool-execution.md +3 -16
  86. package/runtime/prompts/working-method.md +16 -99
  87. package/skills/deliver-work/SKILL.md +76 -0
  88. package/skills/deliver-work/references/branch-closeout.md +134 -0
  89. package/skills/deliver-work/references/commit.md +83 -0
  90. package/skills/deliver-work/references/launch.md +94 -0
  91. package/skills/deliver-work/references/release.md +85 -0
  92. package/skills/deliver-work/scripts/commit-state.mjs +139 -0
  93. package/skills/deliver-work/scripts/delivery-state.mjs +107 -0
  94. package/skills/deliver-work/scripts/lib/git-state.mjs +178 -0
  95. package/skills/deliver-work/scripts/push-route.mjs +122 -0
  96. package/skills/deliver-work/scripts/release-preflight.mjs +177 -0
  97. package/skills/discuss-work/SKILL.md +148 -0
  98. package/skills/{discuss → discuss-work}/references/discussion-continuity.md +10 -27
  99. package/skills/discuss-work/references/learning-action.md +36 -0
  100. package/skills/discuss-work/scripts/choices.mjs +101 -0
  101. package/skills/discuss-work/scripts/lib/choices.mjs +159 -0
  102. package/skills/evaluate-behavior/SKILL.md +107 -0
  103. package/skills/evaluate-behavior/references/authoring.md +381 -0
  104. package/skills/evaluate-behavior/references/coding-tasks.md +145 -0
  105. package/skills/evaluate-behavior/references/conversations-pipelines-judges.md +177 -0
  106. package/skills/evaluate-behavior/references/design-and-measurement.md +273 -0
  107. package/skills/evaluate-behavior/references/running-and-evidence.md +245 -0
  108. package/skills/evaluate-behavior/scripts/claude-guard.mjs +76 -0
  109. package/skills/evaluate-behavior/scripts/guard-rules.mjs +309 -0
  110. package/skills/evaluate-behavior/scripts/lib/agreement.mjs +90 -0
  111. package/skills/evaluate-behavior/scripts/lib/arms.mjs +55 -0
  112. package/skills/evaluate-behavior/scripts/lib/budget.mjs +87 -0
  113. package/skills/evaluate-behavior/scripts/lib/build-source.mjs +287 -0
  114. package/skills/evaluate-behavior/scripts/lib/clear.mjs +74 -0
  115. package/skills/evaluate-behavior/scripts/lib/container.mjs +395 -0
  116. package/skills/evaluate-behavior/scripts/lib/decision.mjs +418 -0
  117. package/skills/evaluate-behavior/scripts/lib/definitions.mjs +1072 -0
  118. package/skills/evaluate-behavior/scripts/lib/freeflow.mjs +103 -0
  119. package/skills/evaluate-behavior/scripts/lib/grade-command.mjs +591 -0
  120. package/skills/evaluate-behavior/scripts/lib/grade-comparison.mjs +90 -0
  121. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/grade-interaction.mjs +19 -18
  122. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/grade-support.mjs +32 -5
  123. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/grade-workspace.mjs +28 -12
  124. package/skills/evaluate-behavior/scripts/lib/grade.mjs +101 -0
  125. package/skills/evaluate-behavior/scripts/lib/hooks.mjs +98 -0
  126. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/confinement.mjs +196 -0
  127. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/constraints.mjs +111 -0
  128. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/index.mjs +48 -0
  129. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/isolation.mjs +74 -0
  130. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/launch.mjs +123 -0
  131. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/model-call.mjs +73 -0
  132. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/recorder.mjs +178 -0
  133. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/session.mjs +494 -0
  134. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/skills.mjs +81 -0
  135. package/skills/evaluate-behavior/scripts/lib/hosts/index.mjs +31 -0
  136. package/skills/evaluate-behavior/scripts/lib/hosts/names.mjs +3 -0
  137. package/skills/evaluate-behavior/scripts/lib/hosts/pi/confinement.mjs +173 -0
  138. package/skills/evaluate-behavior/scripts/lib/hosts/pi/host.mjs +148 -0
  139. package/skills/evaluate-behavior/scripts/lib/hosts/pi/index.mjs +70 -0
  140. package/skills/evaluate-behavior/scripts/lib/hosts/pi/isolation.mjs +81 -0
  141. package/skills/evaluate-behavior/scripts/lib/hosts/pi/model-call.mjs +79 -0
  142. package/skills/evaluate-behavior/scripts/lib/hosts/pi/process.mjs +241 -0
  143. package/skills/{evaluate-skill/scripts/lib → evaluate-behavior/scripts/lib/hosts/pi}/rpc.mjs +144 -26
  144. package/skills/evaluate-behavior/scripts/lib/identity.mjs +82 -0
  145. package/skills/evaluate-behavior/scripts/lib/judge.mjs +688 -0
  146. package/skills/evaluate-behavior/scripts/lib/metrics.mjs +332 -0
  147. package/skills/evaluate-behavior/scripts/lib/model-call.mjs +17 -0
  148. package/skills/evaluate-behavior/scripts/lib/participants.mjs +616 -0
  149. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/process.mjs +22 -0
  150. package/skills/evaluate-behavior/scripts/lib/queue.mjs +54 -0
  151. package/skills/evaluate-behavior/scripts/lib/reference.mjs +343 -0
  152. package/skills/evaluate-behavior/scripts/lib/reuse.mjs +277 -0
  153. package/skills/evaluate-behavior/scripts/lib/review.mjs +933 -0
  154. package/skills/evaluate-behavior/scripts/lib/runner.mjs +732 -0
  155. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/sandbox.mjs +119 -14
  156. package/skills/evaluate-behavior/scripts/lib/scan-shell.mjs +457 -0
  157. package/skills/evaluate-behavior/scripts/lib/scan.mjs +479 -0
  158. package/skills/evaluate-behavior/scripts/lib/seal.mjs +91 -0
  159. package/skills/evaluate-behavior/scripts/lib/shell.mjs +560 -0
  160. package/skills/evaluate-behavior/scripts/lib/source-override.mjs +64 -0
  161. package/skills/evaluate-behavior/scripts/lib/subject-file.mjs +88 -0
  162. package/skills/{evaluate-skill/scripts/lib/pi.mjs → evaluate-behavior/scripts/lib/subject.mjs} +235 -265
  163. package/skills/evaluate-behavior/scripts/lib/task-copy.mjs +124 -0
  164. package/skills/evaluate-behavior/scripts/lib/trials.mjs +524 -0
  165. package/skills/evaluate-behavior/scripts/lib/validity.mjs +68 -0
  166. package/skills/evaluate-behavior/scripts/lib/view-html.mjs +454 -0
  167. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/view.mjs +159 -18
  168. package/skills/{evaluate-skill → evaluate-behavior}/scripts/pi-command-tool.mjs +21 -6
  169. package/skills/evaluate-behavior/scripts/pi-container-route.mjs +23 -0
  170. package/skills/evaluate-behavior/scripts/pi-guard.mjs +77 -0
  171. package/skills/evaluate-behavior/scripts/pi-login-refresh.mjs +31 -0
  172. package/skills/evaluate-behavior/scripts/skill-eval.mjs +586 -0
  173. package/skills/execute-work/SKILL.md +96 -104
  174. package/skills/execute-work/references/code-practices.md +27 -51
  175. package/skills/execute-work/references/design.md +271 -0
  176. package/skills/execute-work/references/diagnose.md +117 -0
  177. package/skills/execute-work/references/migration.md +108 -0
  178. package/skills/execute-work/references/simplify.md +65 -0
  179. package/skills/execute-work/scripts/self-review.mjs +422 -0
  180. package/skills/execute-work/scripts/touch-map.mjs +290 -0
  181. package/skills/review-work/SKILL.md +89 -65
  182. package/skills/review-work/references/adjudication.md +94 -0
  183. package/skills/review-work/references/artifact.md +198 -0
  184. package/skills/review-work/references/evals-and-judges.md +66 -0
  185. package/skills/review-work/references/work.md +177 -0
  186. package/skills/review-work/scripts/check-brief.mjs +128 -0
  187. package/skills/review-work/scripts/review-packet.mjs +233 -0
  188. package/skills/setup-freeflow/SKILL.md +68 -17
  189. package/skills/track-work/SKILL.md +52 -20
  190. package/skills/track-work/references/handoff.md +190 -0
  191. package/skills/track-work/references/projects.md +51 -0
  192. package/skills/track-work/references/working-record-format.md +36 -18
  193. package/skills/track-work/scripts/lib/document.mjs +17 -13
  194. package/skills/track-work/scripts/lib/format.mjs +2 -0
  195. package/skills/track-work/scripts/lib/recover.mjs +254 -0
  196. package/skills/track-work/scripts/lib/registry.mjs +656 -0
  197. package/skills/track-work/scripts/lib/search.mjs +40 -0
  198. package/skills/track-work/scripts/lib/store.mjs +46 -15
  199. package/skills/track-work/scripts/lib/views.mjs +50 -1
  200. package/skills/track-work/scripts/working-record.mjs +232 -13
  201. package/skills/verify-work/SKILL.md +45 -37
  202. package/skills/verify-work/references/feature-map.md +120 -0
  203. package/skills/verify-work/references/runtime-evidence.md +203 -0
  204. package/skills/verify-work/references/test-design.md +25 -6
  205. package/skills/verify-work/scripts/test-changes.mjs +246 -0
  206. package/skills/write-docs/SKILL.md +113 -25
  207. package/skills/write-docs/references/documentation-shapes.md +68 -3
  208. package/skills/write-docs/references/spec-and-plan-shapes.md +308 -0
  209. package/skills/write-docs/scripts/artifact-check.mjs +148 -0
  210. package/skills/write-docs/scripts/docs-check.mjs +96 -6
  211. package/skills/write-docs/scripts/plan-lint.mjs +123 -0
  212. package/skills/write-skill/SKILL.md +92 -52
  213. package/skills/write-skill/references/activation-and-wording.md +143 -0
  214. package/skills/write-skill/references/placement-and-dependencies.md +154 -0
  215. package/skills/write-skill/scripts/lib/compare.mjs +701 -0
  216. package/skills/write-skill/scripts/lib/skill-author.mjs +197 -3
  217. package/skills/write-skill/scripts/skill-author.mjs +51 -8
  218. package/capabilities/cognitive-routing/references/both-mode.md +0 -36
  219. package/capabilities/cognitive-routing/references/executor-mode.md +0 -48
  220. package/capabilities/cognitive-routing/references/helper-mode.md +0 -47
  221. package/plugin.json +0 -33
  222. package/skills/action-selection/SKILL.md +0 -92
  223. package/skills/action-selection/references/trajectory-stalls.md +0 -73
  224. package/skills/bypass/SKILL.md +0 -153
  225. package/skills/commit-work/SKILL.md +0 -93
  226. package/skills/commit-work/references/git-state-edges.md +0 -94
  227. package/skills/commit-work/references/simple-push.md +0 -94
  228. package/skills/commit-work/references/staging-decisions.md +0 -106
  229. package/skills/decision-gate/SKILL.md +0 -87
  230. package/skills/design-for-depth/SKILL.md +0 -108
  231. package/skills/design-for-depth/references/design-pressure-signals.md +0 -84
  232. package/skills/design-for-depth/references/implementation-decisions.md +0 -76
  233. package/skills/design-for-depth/references/interface-design-loop.md +0 -105
  234. package/skills/design-for-depth/references/module-and-dependency-design.md +0 -117
  235. package/skills/design-for-depth/references/state-and-failure-boundaries.md +0 -125
  236. package/skills/diagnose-failure/SKILL.md +0 -140
  237. package/skills/diagnose-failure/references/diagnostic-loop-catalog.md +0 -50
  238. package/skills/diagnose-failure/references/flaky-and-performance-diagnosis.md +0 -51
  239. package/skills/discuss/SKILL.md +0 -140
  240. package/skills/evaluate-skill/SKILL.md +0 -188
  241. package/skills/evaluate-skill/references/evaluation-definition-schema.md +0 -415
  242. package/skills/evaluate-skill/references/evaluation-design.md +0 -112
  243. package/skills/evaluate-skill/references/execution-and-evidence.md +0 -111
  244. package/skills/evaluate-skill/references/review-and-revision.md +0 -94
  245. package/skills/evaluate-skill/scripts/lib/definitions.mjs +0 -448
  246. package/skills/evaluate-skill/scripts/lib/grade-comparison.mjs +0 -60
  247. package/skills/evaluate-skill/scripts/lib/grade.mjs +0 -64
  248. package/skills/evaluate-skill/scripts/lib/review.mjs +0 -196
  249. package/skills/evaluate-skill/scripts/lib/runner.mjs +0 -405
  250. package/skills/evaluate-skill/scripts/lib/trials.mjs +0 -103
  251. package/skills/evaluate-skill/scripts/pi-guard.mjs +0 -181
  252. package/skills/evaluate-skill/scripts/skill-eval.mjs +0 -182
  253. package/skills/execute-work/references/execute-work-edges.md +0 -78
  254. package/skills/finish-branch/SKILL.md +0 -117
  255. package/skills/finish-branch/references/integration-options.md +0 -80
  256. package/skills/handoff/SKILL.md +0 -82
  257. package/skills/handoff/references/handoff-templates.md +0 -150
  258. package/skills/launch-work/SKILL.md +0 -116
  259. package/skills/launch-work/references/launch-readiness.md +0 -85
  260. package/skills/migration-work/SKILL.md +0 -115
  261. package/skills/migration-work/references/migration-lifecycle.md +0 -82
  262. package/skills/release-work/SKILL.md +0 -118
  263. package/skills/release-work/references/release-evidence.md +0 -78
  264. package/skills/review-artifact/SKILL.md +0 -143
  265. package/skills/review-artifact/references/adjudicate-artifact-review.md +0 -101
  266. package/skills/review-artifact/references/independent-artifact-reviewer-contract.md +0 -159
  267. package/skills/review-work/references/adjudicate-work-review.md +0 -97
  268. package/skills/review-work/references/independent-work-reviewer-contract.md +0 -139
  269. package/skills/review-work/references/security-risk-lens.md +0 -67
  270. package/skills/setup-freeflow/references/activation-contract.md +0 -103
  271. package/skills/setup-freeflow/references/host-setup.md +0 -67
  272. package/skills/simplify-code/SKILL.md +0 -85
  273. package/skills/simplify-code/references/simplification-patterns.md +0 -70
  274. package/skills/verify-work/references/browser-runtime-evidence.md +0 -51
  275. package/skills/verify-work/references/integration-evidence.md +0 -49
  276. package/skills/verify-work/references/performance-evidence.md +0 -59
  277. package/skills/workflow/SKILL.md +0 -171
  278. package/skills/workflow/references/domain-skill-composition.md +0 -45
  279. package/skills/write-plan/SKILL.md +0 -92
  280. package/skills/write-plan/references/plan-shapes.md +0 -156
  281. package/skills/write-skill/references/activation-boundaries.md +0 -106
  282. package/skills/write-skill/references/agent-first-instructions.md +0 -133
  283. package/skills/write-skill/references/progressive-disclosure.md +0 -129
  284. package/skills/write-skill/references/skill-dependency-graphs.md +0 -192
  285. package/skills/write-spec/SKILL.md +0 -85
  286. package/skills/write-spec/references/artifact-standards.md +0 -86
  287. package/skills/write-spec/references/decision-records.md +0 -80
  288. package/skills/write-spec/references/spec-shapes.md +0 -143
  289. /package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/evidence.mjs +0 -0
  290. /package/skills/{evaluate-skill → evaluate-behavior}/scripts/pi-observer.mjs +0 -0
@@ -605,6 +605,7 @@ async function analyzeSkill(directory, packageDirectory) {
605
605
  });
606
606
 
607
607
  return {
608
+ readable: true,
608
609
  skillDirectory,
609
610
  packageRoot,
610
611
  frontmatter: document.frontmatter,
@@ -619,17 +620,210 @@ function emptyResources() {
619
620
  return { localReferences: [], packageDependencies: [], scripts: [], unlinkedFiles: [] };
620
621
  }
621
622
 
622
- export async function validateSkill({ directory, packageRoot }) {
623
+ // Link cycles among the Markdown files a skill reaches: its own references and the package files they link to,
624
+ // followed transitively inside the package root. A link to any SKILL.md is a route or a pointer back to an owner,
625
+ // not an edge: routing between skills may be cyclic by design. A cycle is reported as a fact for the author, not as
626
+ // a validation error.
627
+ async function linkCycles(skillDirectory, packageRoot) {
628
+ const graph = new Map();
629
+ const queue = [path.join(skillDirectory, "SKILL.md")];
630
+ while (queue.length) {
631
+ const source = queue.shift();
632
+ if (graph.has(source)) continue;
633
+ let contents;
634
+ try {
635
+ contents = await readFile(source, "utf8");
636
+ } catch {
637
+ graph.set(source, []);
638
+ continue;
639
+ }
640
+ const targets = new Set();
641
+ for (const link of markdownLinks(contents)) {
642
+ const target = path.resolve(path.dirname(source), link);
643
+ if (target === source || path.basename(target) === "SKILL.md" || path.extname(target).toLowerCase() !== ".md")
644
+ continue;
645
+ if (!isContained(packageRoot, target)) continue;
646
+ try {
647
+ await access(target, fsConstants.R_OK);
648
+ } catch {
649
+ continue;
650
+ }
651
+ targets.add(target);
652
+ queue.push(target);
653
+ }
654
+ graph.set(source, [...targets]);
655
+ }
656
+
657
+ let counter = 0;
658
+ const stack = [];
659
+ const onStack = new Set();
660
+ const order = new Map();
661
+ const low = new Map();
662
+ const cycles = [];
663
+ const visit = (node) => {
664
+ order.set(node, counter);
665
+ low.set(node, counter);
666
+ counter += 1;
667
+ stack.push(node);
668
+ onStack.add(node);
669
+ for (const next of graph.get(node) ?? []) {
670
+ if (!order.has(next)) {
671
+ visit(next);
672
+ low.set(node, Math.min(low.get(node), low.get(next)));
673
+ } else if (onStack.has(next)) {
674
+ low.set(node, Math.min(low.get(node), order.get(next)));
675
+ }
676
+ }
677
+ if (low.get(node) !== order.get(node)) return;
678
+ const component = [];
679
+ let member;
680
+ do {
681
+ member = stack.pop();
682
+ onStack.delete(member);
683
+ component.push(member);
684
+ } while (member !== node);
685
+ if (component.length > 1 && component.some((file) => isContained(skillDirectory, file))) {
686
+ cycles.push(component.map((file) => relativePath(skillDirectory, file)).sort());
687
+ }
688
+ };
689
+ for (const node of graph.keys()) if (!order.has(node)) visit(node);
690
+ return cycles.sort((left, right) => left[0].localeCompare(right[0]));
691
+ }
692
+
693
+ function tableCells(line) {
694
+ return line
695
+ .trim()
696
+ .replace(/^\|/, "")
697
+ .replace(/\|$/, "")
698
+ .split("|")
699
+ .map((cell) => cell.trim());
700
+ }
701
+
702
+ // Routing-map parity: the map's row for this skill names the same sibling routes and direct resources as the links
703
+ // in its SKILL.md. A route is a link to another skill's SKILL.md; the row names it by directory name in backticks or
704
+ // by a link. Every other direct link is a resource, named in the row by a link.
705
+ async function checkRoutingMap({ skillDirectory, body, routingMap }) {
706
+ const mapFile = path.resolve(routingMap);
707
+ const mapPath = relativePath(skillDirectory, mapFile);
708
+ const findings = [];
709
+ let contents;
710
+ try {
711
+ contents = await readFile(mapFile, "utf8");
712
+ } catch {
713
+ return [errorFinding("routing-map-unreadable", mapPath, `Routing map is not a readable file: ${routingMap}`)];
714
+ }
715
+
716
+ const skillFile = path.join(skillDirectory, "SKILL.md");
717
+ const resolveFrom = (directory, link) => path.resolve(directory, link);
718
+ const rows = [];
719
+ let fence = null;
720
+ for (const line of contents.split(/\r?\n/)) {
721
+ if (fence) {
722
+ if (closesFence(line, fence)) fence = null;
723
+ continue;
724
+ }
725
+ fence = openingFence(line);
726
+ if (fence || !/^\s*\|.*\|\s*$/.test(line)) continue;
727
+ const [first, ...rest] = tableCells(line);
728
+ if (markdownLinks(first).some((link) => resolveFrom(path.dirname(mapFile), link) === skillFile))
729
+ rows.push(rest.join(" | "));
730
+ }
731
+ if (rows.length !== 1) {
732
+ const code = rows.length ? "routing-map-duplicate-row" : "routing-map-missing-row";
733
+ const message = rows.length
734
+ ? "Routing map has more than one row for this skill"
735
+ : "Routing map has no row for this skill";
736
+ return [errorFinding(code, mapPath, message)];
737
+ }
738
+
739
+ const isRoute = (target) => path.basename(target) === "SKILL.md" && path.dirname(target) !== skillDirectory;
740
+ const routeName = (target) => path.basename(path.dirname(target));
741
+ const expectedRoutes = new Set();
742
+ const expectedResources = new Set();
743
+ for (const link of markdownLinks(body)) {
744
+ const target = resolveFrom(skillDirectory, link);
745
+ if (isRoute(target)) expectedRoutes.add(routeName(target));
746
+ else if (target !== skillFile) expectedResources.add(target);
747
+ }
748
+
749
+ const siblings = new Set();
750
+ for (const entry of await readdir(path.dirname(skillDirectory), { withFileTypes: true })) {
751
+ if (!entry.isDirectory()) continue;
752
+ try {
753
+ await access(path.join(path.dirname(skillDirectory), entry.name, "SKILL.md"), fsConstants.R_OK);
754
+ siblings.add(entry.name);
755
+ } catch {
756
+ // Not a skill directory.
757
+ }
758
+ }
759
+ const row = rows[0];
760
+ const documentedRoutes = new Set();
761
+ const documentedResources = new Set();
762
+ for (const link of markdownLinks(row)) {
763
+ const target = resolveFrom(path.dirname(mapFile), link);
764
+ if (isRoute(target)) documentedRoutes.add(routeName(target));
765
+ else if (target !== skillFile) documentedResources.add(target);
766
+ }
767
+ for (const match of maskInlineLinks(row).matchAll(/`([a-z0-9]+(?:-[a-z0-9]+)*)`/g)) {
768
+ if (expectedRoutes.has(match[1]) || siblings.has(match[1])) documentedRoutes.add(match[1]);
769
+ }
770
+
771
+ const display = (target) => relativePath(skillDirectory, target);
772
+ for (const name of [...expectedRoutes].filter((name) => !documentedRoutes.has(name)).sort()) {
773
+ findings.push(
774
+ errorFinding("routing-map-missing-route", mapPath, `Routing map row does not name the linked skill: ${name}`),
775
+ );
776
+ }
777
+ for (const name of [...documentedRoutes].filter((name) => !expectedRoutes.has(name)).sort()) {
778
+ findings.push(
779
+ errorFinding("routing-map-extra-route", mapPath, `Routing map row names a skill SKILL.md does not link: ${name}`),
780
+ );
781
+ }
782
+ for (const target of [...expectedResources]
783
+ .filter((target) => !documentedResources.has(target))
784
+ .map(display)
785
+ .sort()) {
786
+ findings.push(
787
+ errorFinding("routing-map-missing-resource", mapPath, `Routing map row does not link the resource: ${target}`),
788
+ );
789
+ }
790
+ for (const target of [...documentedResources]
791
+ .filter((target) => !expectedResources.has(target))
792
+ .map(display)
793
+ .sort()) {
794
+ findings.push(
795
+ errorFinding(
796
+ "routing-map-extra-resource",
797
+ mapPath,
798
+ `Routing map row links a resource SKILL.md does not link: ${target}`,
799
+ ),
800
+ );
801
+ }
802
+ return findings;
803
+ }
804
+
805
+ function maskInlineLinks(text) {
806
+ return text.replace(/\[[^\]]*\]\([^)]*\)/g, " ");
807
+ }
808
+
809
+ export async function validateSkill({ directory, packageRoot, routingMap }) {
623
810
  const analysis = await analyzeSkill(directory, packageRoot);
811
+ const findings = [...analysis.findings];
812
+ let cycles = [];
813
+ if (analysis.readable) {
814
+ cycles = await linkCycles(analysis.skillDirectory, analysis.packageRoot);
815
+ if (routingMap) findings.push(...(await checkRoutingMap({ ...analysis, routingMap })));
816
+ }
624
817
  return {
625
818
  command: "validate",
626
- status: analysis.findings.some((finding) => finding.severity === "error") ? "invalid" : "valid",
819
+ status: findings.some((finding) => finding.severity === "error") ? "invalid" : "valid",
627
820
  skillDirectory: analysis.skillDirectory,
628
821
  packageRoot: analysis.packageRoot,
629
822
  frontmatter: analysis.frontmatter,
630
823
  heading: analysis.heading,
631
824
  resources: analysis.resources,
632
- findings: analysis.findings,
825
+ cycles,
826
+ findings,
633
827
  };
634
828
  }
635
829
 
@@ -1,13 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ import { compareGuidance, compareMarkdown } from "./lib/compare.mjs";
3
4
  import { DEFAULT_THRESHOLD, findSimilarFiles } from "./lib/similarity.mjs";
4
5
  import { initSkill, inspectSkill, SkillAuthorError, validateSkill } from "./lib/skill-author.mjs";
5
6
 
6
- const commands = new Set(["init", "validate", "inspect", "similarity"]);
7
+ const commands = new Set(["init", "validate", "inspect", "similarity", "compare"]);
7
8
 
8
9
  function printUsage() {
9
10
  process.stdout.write(
10
- `Usage: skill-author <init|validate|inspect|similarity> [options]\n\nCommands:\n init <directory> --name <name> --description <text>\n init creates a minimal SKILL.md and refuses to overwrite one\n validate <directory> [--package-root <directory>]\n validate checks structure and recursive resource containment\n inspect <directory> [--package-root <directory>]\n inspect reports factual inventory plus validation findings\n similarity <directory> [--threshold <0-1>]\n similarity reports near-duplicate Markdown files by shared word sequences (default ${DEFAULT_THRESHOLD})\n\nOutput:\n Commands emit JSON. Invalid structure still emits JSON and exits nonzero.\n Command errors emit structured error JSON.\n Package root defaults to the nearest package.json ancestor, then the skill parent.\n\nFrontmatter:\n Validation supports flat plain-string or JSON-compatible double-quoted scalars.\n Double-quote values when punctuation, numbers, booleans, or null-like text could be ambiguous.\n`,
11
+ `Usage: skill-author <init|validate|inspect|similarity> [options]\n skill-author compare [<base-ref> [<new-ref>] | --base <folder> [<folder>]] [options]\n\nCommands:\n init <directory> --name <name> --description <text>\n init creates a minimal SKILL.md and refuses to overwrite one\n validate <directory> [--package-root <directory>] [--routing-map <file>]\n validate checks structure and recursive resource containment, reports link cycles among\n the Markdown files the skill reaches, and with --routing-map checks the skill's row\n inspect <directory> [--package-root <directory>]\n inspect reports factual inventory plus validation findings\n similarity <directory> [--threshold <0-1>]\n similarity reports near-duplicate Markdown files by shared word sequences (default ${DEFAULT_THRESHOLD})\n compare [<base-ref> [<new-ref>]] [--paths <path>...] [--deleted-only] [--all-units] [--verdicts <file>] [--markdown]\n compare reports what changed model-facing Markdown at <base-ref> (default: the merge-base with\n the default branch) no longer says at <new-ref> (default: the working tree, uncommitted edits\n included), and exits nonzero while a rule-like unmatched unit (a rule, a numbered step, or a\n reason: because, so that, otherwise, why) has no verdict; --all-units, for a substantial\n revision (a merge, split, move or rewrite), needs a verdict for every unmatched unit\n compare --base <folder> [<folder>] [options]\n compare against a copy of the text kept outside Git (default: the current folder)\n\nOutput:\n Commands emit JSON. Invalid structure still emits JSON and exits nonzero.\n compare --markdown prints a readable report instead.\n Command errors emit structured error JSON.\n Package root defaults to the nearest package.json ancestor, then the skill parent.\n\nFrontmatter:\n Validation supports flat plain-string or JSON-compatible double-quoted scalars.\n Double-quote values when punctuation, numbers, booleans, or null-like text could be ambiguous.\n`,
11
12
  );
12
13
  }
13
14
 
@@ -15,7 +16,8 @@ function fail(code, message, exitCode = 2) {
15
16
  throw new SkillAuthorError(code, message, exitCode);
16
17
  }
17
18
 
18
- function parseOptions(args, allowedOptions) {
19
+ // Options take one value, except flags (no value) and lists (every following argument up to the next option).
20
+ function parseOptions(args, allowedOptions, { flags = new Set(), lists = new Set() } = {}) {
19
21
  const positionals = [];
20
22
  const options = {};
21
23
 
@@ -26,12 +28,23 @@ function parseOptions(args, allowedOptions) {
26
28
  continue;
27
29
  }
28
30
 
29
- if (!allowedOptions.has(argument)) {
31
+ if (!allowedOptions.has(argument) && !flags.has(argument) && !lists.has(argument)) {
30
32
  fail("unknown-option", `Unknown option: ${argument}`);
31
33
  }
32
34
  if (Object.hasOwn(options, argument)) {
33
35
  fail("duplicate-option", `Option may be supplied once: ${argument}`);
34
36
  }
37
+ if (flags.has(argument)) {
38
+ options[argument] = true;
39
+ continue;
40
+ }
41
+ if (lists.has(argument)) {
42
+ const values = [];
43
+ while (index + 1 < args.length && !args[index + 1].startsWith("--")) values.push(args[(index += 1)]);
44
+ if (values.length === 0) fail("missing-option-value", `Option requires a value: ${argument}`);
45
+ options[argument] = values;
46
+ continue;
47
+ }
35
48
 
36
49
  const value = args[index + 1];
37
50
  if (value === undefined || value.startsWith("--")) {
@@ -61,12 +74,15 @@ async function run(command, args) {
61
74
  }
62
75
 
63
76
  if (command === "validate" || command === "inspect") {
64
- const { positionals, options } = parseOptions(args, new Set(["--package-root"]));
77
+ const allowed = command === "validate" ? ["--package-root", "--routing-map"] : ["--package-root"];
78
+ const { positionals, options } = parseOptions(args, new Set(allowed));
65
79
  if (positionals.length !== 1) {
66
80
  fail("invalid-arguments", `${command} requires exactly one skill directory`);
67
81
  }
68
82
  const input = { directory: positionals[0], packageRoot: options["--package-root"] };
69
- return command === "validate" ? validateSkill(input) : inspectSkill(input);
83
+ return command === "validate"
84
+ ? validateSkill({ ...input, routingMap: options["--routing-map"] })
85
+ : inspectSkill(input);
70
86
  }
71
87
 
72
88
  if (command === "similarity") {
@@ -84,6 +100,33 @@ async function run(command, args) {
84
100
  return findSimilarFiles({ directory: positionals[0], threshold });
85
101
  }
86
102
 
103
+ if (command === "compare") {
104
+ const { positionals, options } = parseOptions(args, new Set(["--base", "--verdicts"]), {
105
+ flags: new Set(["--deleted-only", "--markdown", "--all-units"]),
106
+ lists: new Set(["--paths"]),
107
+ });
108
+ const folder = options["--base"] ?? null;
109
+ if (positionals.length > (folder === null ? 2 : 1)) {
110
+ fail(
111
+ "invalid-arguments",
112
+ folder === null
113
+ ? "compare takes at most a base ref and a new ref"
114
+ : "compare --base takes at most one folder to compare",
115
+ );
116
+ }
117
+ const result = await compareGuidance({
118
+ base: folder === null ? (positionals[0] ?? null) : null,
119
+ next: folder === null ? (positionals[1] ?? null) : null,
120
+ baseFolder: folder,
121
+ directory: folder === null ? null : (positionals[0] ?? null),
122
+ paths: options["--paths"] ?? null,
123
+ deletedOnly: options["--deleted-only"] === true,
124
+ verdicts: options["--verdicts"] ?? null,
125
+ allUnits: options["--all-units"] === true,
126
+ });
127
+ return options["--markdown"] ? { ...result, markdown: true } : result;
128
+ }
129
+
87
130
  fail("unknown-command", `Unknown command: ${command}`);
88
131
  }
89
132
 
@@ -99,8 +142,8 @@ async function main() {
99
142
  }
100
143
 
101
144
  const result = await run(command, args);
102
- process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
103
- if (result.status === "invalid") process.exitCode = 1;
145
+ process.stdout.write(result.markdown ? compareMarkdown(result) : `${JSON.stringify(result, null, 2)}\n`);
146
+ if (result.status === "invalid" || result.status === "unresolved") process.exitCode = 1;
104
147
  }
105
148
 
106
149
  try {
@@ -1,36 +0,0 @@
1
- # Both Mode
2
-
3
- Judgment for placing work when Runtime State shows `Delegation: both`. The core skill's Rules still apply, including the limit on Coordinator's own environment work.
4
-
5
- Both mode is the middle ground between quality and cost. Executor does consequential work, including code; Helper does support; Coordinator plans, writes contracts, assesses, and talks to the user. Every assignment names its worker with `worker: "helper"` or `worker: "executor"`.
6
-
7
- ## Choose The Worker Per Assignment
8
-
9
- Goal: each assignment goes to the cheapest worker that can do it without losing quality.
10
-
11
- Default: Executor for results whose behavior or failure needs engineering ownership; Helper for gathering, checks, setup, record maintenance, and small settled changes.
12
-
13
- | Situation | Worker |
14
- | --- | --- |
15
- | Find the callers, contracts, and conventions the next change will touch. | Helper |
16
- | Implement the change and its tests. | Executor |
17
- | A one-line authorization change with security consequences. | Executor: small, but consequential. |
18
- | A read-only audit that decides whether the design holds. | Executor: no writes, but substantive judgment. |
19
- | Rerun the validation suite and the formatter after Executor's change. | Helper |
20
- | Update several record entries after an accepted result. | Helper, or folded into an assignment already going out. |
21
-
22
- The failure to prevent is misplacement: a consequential change given to Helper because it is short, or Executor spent on pure gathering. Decide by the responsibility and its consequences, not by size or by whether the work writes.
23
-
24
- These are available routes, not phases. A unit may use only Helper, go straight to Executor, or keep one coherent result with Executor through its checks and corrections.
25
-
26
- ## Reuse What The Other Worker Found
27
-
28
- Goal: no worker rediscovers what the other already established.
29
-
30
- Helper and Executor share ordinary history. A typical route: Helper gathers; Executor's contract points at what Helper found instead of asking it to explore; Coordinator receives what it needs through projection. After implementation, Helper can run follow-up checks with Executor's context already present. Recheck a fact only when its freshness matters or its source is no longer available.
31
-
32
- Executor forms the execution forecast for production work; Coordinator supplies the governing decisions.
33
-
34
- ## Mind The Model Configuration
35
-
36
- The user may run Coordinator and Executor on the same model at different effort. On routes that keep the provider cache across effort changes (currently GPT-6 on an OpenAI API key or OpenAI Codex), handoffs to Executor then reuse the cache and cost less. Elsewhere, including OpenAI's Sign in with ChatGPT, each effort keeps its own cache, so the first handoff at each effort rereads the whole context and later ones reread what was added since that effort last ran. With different models, every switch rereads the whole context. Either way the configuration is the user's choice; do not change it.
@@ -1,48 +0,0 @@
1
- # Executor Mode
2
-
3
- Judgment for placing work when Runtime State shows `Delegation: executor`. The core skill's Rules still apply, including the limit on Coordinator's own environment work.
4
-
5
- Executor mode is the main cost saver. A cheaper Executor does the environment work: investigation, preparation, artifacts, implementation, checks, and record maintenance. Coordinator plans, writes contracts, assesses, and talks to the user, and executes nothing itself except under ACT_BOUNDED. The saving comes from two places: projection keeps Executor's working trail out of Coordinator's context, and precise contracts keep Executor from searching.
6
-
7
- ## Make The Contract Do The Heavy Thinking
8
-
9
- Goal: Executor's first attempt is right often enough that the saving outweighs the corrections.
10
-
11
- Coordinator's judgment reaches the work only through the contract, so the contract carries the decision. Frame the problem so the cheaper model finds it straightforward: the representation to use, the invariant to preserve, the wrong approach that looks right, and the check that tells them apart. For consequential design choices, write that content with the Implementation Decisions method in [Design for Depth](../../../skills/design-for-depth/SKILL.md).
12
-
13
- ```text
14
- Weak: Add caching to the config loader.
15
- Strong: Cache the parsed config per file path and invalidate when the file's
16
- modification time changes. Two loads of an unchanged file parse once;
17
- an edit between loads must be seen. A process-lifetime cache looks
18
- right and passes a single-load test but serves stale config, so check
19
- with an edit between two loads.
20
- ```
21
-
22
- A cheaper model applies an escape clause literally, so write requirements as outcomes for named things ("each caller listed below still gets X"), never "unless…" or "as today", and say where the change belongs.
23
-
24
- Default: give structure where Executor has shown difficulty or the property is easy to get subtly wrong, and freedom where the mechanics are ordinary. Signals the balance is off:
25
-
26
- - Executor returns work that misses an unstated decision: the contract left it implicit.
27
- - The contract is longer than the change and reads like a patch: Coordinator has done the work at premium price, and Executor only transcribes it.
28
- - The same misunderstanding recurs: change how you represent the problem, not how forcefully you state it.
29
-
30
- ## Gather, Then Produce
31
-
32
- Goal: Coordinator's contracts rest on evidence without Coordinator doing the reading.
33
-
34
- Coordinator may first commission evidence or a proposal, interpret what comes back, and then commission production. Executor gathers; projection carries the selected evidence to Coordinator; the next contract uses it to narrow Executor's search. Do not add a gathering pass when Executor already has an adequate basis, and do not pre-solve every detail before any evidence exists.
35
-
36
- Executor forms the execution forecast for production work. Coordinator supplies the governing decisions it rests on.
37
-
38
- ## Ask For Evidence That Decides
39
-
40
- Goal: Coordinator can assess from what projection delivers, without asking for the whole trail.
41
-
42
- Request evidence by the claim it must support: the decisive test output, the changed interface, the contradicting observation. Requesting everything moves Executor's trail into Coordinator's context and cancels the saving; requesting too little forces a recovery round. When a return lacks evidence that exists, recover it rather than re-running the work.
43
-
44
- ## What Coordinator Does Not Do Here
45
-
46
- Coordinator writes an artifact itself only when the user explicitly assigns it (see the core skill). Record maintenance goes to Executor, folded into an assignment already going out rather than sent as a handoff of its own. Recovery after context loss is the exception the core skill names: Coordinator reads the Working Record and the artifacts that define the task directly.
47
-
48
- The failures to prevent are weak contracts that cause correction cycles, over-specified contracts that move the work back to Coordinator's price, and weak evidence that forces reassessment.
@@ -1,47 +0,0 @@
1
- # Helper Mode
2
-
3
- Judgment for placing work when Runtime State shows `Delegation: helper`. The core skill's Rules still apply.
4
-
5
- Helper mode is for the best output quality. Coordinator implements; Helper takes everything that does not need Coordinator-level reasoning. There is no Executor to invoke or simulate.
6
-
7
- ## Delegate By Default
8
-
9
- Goal: Coordinator's premium compute goes to the work that needs it, and nothing else.
10
-
11
- Default: delegate a step unless it needs Coordinator-level reasoning. Keep that category narrow:
12
-
13
- - governing decisions and design;
14
- - substantive implementation, meaning changes whose behavior or failure needs engineering ownership;
15
- - the conversation with the user.
16
-
17
- Helper takes the rest: gathering sources and skills, investigating bounded questions, preparing authorized setup, running existing checks and validations, separate record maintenance, and straightforward settled changes that are local, reversible, and easy to check. Helper can reason, compare evidence, spot contradictions, and choose local mechanics; it is not limited to copying facts.
18
-
19
- The failure to prevent is under-delegation: classifying every step as Coordinator-level, so Coordinator does all the gathering, checking, and bookkeeping itself and the mode saves nothing.
20
-
21
- ## Do Not Split What Belongs Together
22
-
23
- Goal: handoffs save more than they cost.
24
-
25
- Keep a tightly coupled edit, check, and interpret loop with Coordinator. Moving each check to Helper adds a contract, a ramp-up, and a return, and forces Helper to rebuild the context Coordinator already holds.
26
-
27
- Hand off results that stand on their own:
28
-
29
- | Situation | Placement |
30
- | --- | --- |
31
- | Before implementing, the sources, callers, and conventions for the planned change need gathering. | Helper gathers; Coordinator implements from the result. |
32
- | Mid-implementation, Coordinator wants to know which acceptance requirements the candidate meets, which lack a check, and which test edits changed coverage. | Helper runs a read-only cross-check against the Slice's acceptance requirements and returns without patching. |
33
- | After a feature lands, several record entries, a validation run, and a formatting pass are due. | Helper, as one assignment. |
34
- | Coordinator just ran a failing test and knows the fix. | Coordinator fixes and reruns; no handoff. |
35
- | One line of the Working Record needs updating in the middle of Coordinator's own work. | Coordinator updates it; a handoff would cost more than the edit. |
36
-
37
- If Helper reaches substantive work outside its assignment, it returns findings and partial state, and Coordinator takes the next decision.
38
-
39
- ## Route Preparation
40
-
41
- Helper gathers; Coordinator implements. Gathered evidence must reach Coordinator: with projection on, Helper selects it at return; with projection off, Coordinator sees Helper's work in ordinary history. Coordinator forms the execution forecast itself.
42
-
43
- ## Coordinator's Own Production
44
-
45
- Coordinator's direct implementation passes through no handoff, and handoffs are part of how routing keeps long work on course. Rely on Execute Work's forecast and on Workflow's check before each continuation: does the next change meet a requirement, repair a demonstrated defect, or only add an optional guarantee? Do not invent assignments for your own work to recreate that boundary, and use no ACT_BOUNDED; direct production is what this mode is for.
46
-
47
- Coordinator may update the Working Record directly as part of its own work. When closing a Slice, fold the writeback into Helper work already going out, or do it directly when it is one small update.
package/plugin.json DELETED
@@ -1,33 +0,0 @@
1
- {
2
- "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
3
- "name": "freeflow",
4
- "version": "0.8.0",
5
- "description": "Feedback-based control system for coding agents.",
6
- "author": {
7
- "name": "Hassan Mohiddin"
8
- },
9
- "homepage": "https://github.com/hassan-mohiddin/freeflow",
10
- "repository": "https://github.com/hassan-mohiddin/freeflow",
11
- "license": "MIT",
12
- "keywords": [
13
- "workflow",
14
- "skills",
15
- "agents",
16
- "feedback-loop",
17
- "task-memory",
18
- "planning",
19
- "verification",
20
- "review",
21
- "agent-plugins",
22
- "gemini",
23
- "copilot",
24
- "vscode",
25
- "cursor",
26
- "kiro",
27
- "opencode",
28
- "hermes"
29
- ],
30
- "extensions": {
31
- "com.github.copilot": {}
32
- }
33
- }
@@ -1,92 +0,0 @@
1
- ---
2
- name: "action-selection"
3
- description: "Use when choosing or bounding an environment interaction, especially when the needed context, target, observer, or scope is uncertain, output may be broad, or recent actions have not advanced the current question."
4
- ---
5
-
6
- # Action Selection
7
-
8
- Choose environment interactions that advance the current question or result, observe what they actually change, and return the changed evidence to the current owner.
9
-
10
- An environment interaction is a bounded tool-mediated observation or effect. A current activity can need many of them; a tool call is not a task phase, a Slice, or a reason to change ownership.
11
-
12
- The **Rules** below are binding; if one cannot be met, stop and say why. Everything else is **judgment**: follow its stated goal, and adapt when a different choice serves that goal better.
13
-
14
- ## Rules
15
-
16
- - Action Selection serves the current owner. It never changes the outcome, work agreement, execution method, scope, Slice, Checkpoint, or route, accepts no result, and an available tool grants no authority. Return changed authority, scope, ownership, direction, evidence boundary, or stop conditions to [Workflow](../workflow/SKILL.md).
17
- - Never present a simulated, predicted, sampled, or truncated result as a complete observation. State truncation and sampling explicitly; a partial result does not show that omitted matches are irrelevant or that a search was exhaustive.
18
- - Never report an interaction's success as proof of a wider claim. A successful read is not understanding, a successful write is not correctness, and a passing tool result is not the claim it was meant to support; return the evidence for interpretation.
19
- - Do not emit candidate tables, scores, or speculative tool-call sequences unless a user-owned choice is exposed.
20
-
21
- ## Know What The Step Must Establish
22
-
23
- Goal: every interaction answers a question the owner actually has.
24
-
25
- Before touching the environment, identify what the interaction must answer or produce, and reuse evidence already available and current enough for that purpose. The need may be understanding the outcome or symptom, establishing a mechanism or dependency, applying an understood change, observing whether a claim holds, or reconstructing missing continuation state. Use these to focus the action, not to print phase labels or restart planning.
26
-
27
- Aim for the minimum sufficient context or effect for the next decision; minimum means sufficient, not merely short. Do not collect information because it may be useful later, and do not mistake a source or reference existing for its contents being available.
28
-
29
- ## Run Settled Steps; Select Uncertain Ones
30
-
31
- Goal: spend judgment where the next step is genuinely open, and none on steps that are already decided.
32
-
33
- When the target, purpose, scope, and observing boundary are supported and the action is covered and directly checkable, act directly: read a known function or range, apply a selected edit, run a chosen focused check, inspect its diff.
34
-
35
- When the owner's route or [Execute Work](../execute-work/SKILL.md)'s forecast already fixes a sequence, run the sequence without reconsidering each call. Issue independent reads together, apply coupled edits before their shared check, and run that check once. Select again only when a result contradicts the forecast, is unexpected, or opens a new question.
36
-
37
- Select deliberately when the target, observer, or scope is uncertain, the likely output is broad, the action is destructive, expensive, or hard to recover, or recent work has stalled:
38
-
39
- 1. Identify the fact or effect the owner needs.
40
- 2. Check whether existing evidence already supplies it.
41
- 3. Consider only a few materially different ways to obtain it.
42
- 4. Reject unchanged rereads, equivalent searches, eliminated approaches, and information with no current use.
43
- 5. Prefer the most direct action that distinguishes the plausible answers.
44
- 6. Among equally useful actions, prefer proportionate output, side effects, context residue, and recovery cost.
45
- 7. Execute it, then choose what follows from the actual result.
46
-
47
- Keep this comparison internal. A command being easy to run does not make its target or hypothesis well chosen. A good observation can change the owner's belief or next action whether it supports or contradicts the leading explanation; an exact mutation can advance a settled result without testing a hypothesis.
48
-
49
- ## Bound The Tool And Its Output
50
-
51
- Goal: get the needed evidence at the lowest total cost, counting what the output costs after it arrives.
52
-
53
- Everything an interaction returns stays in context and is paid for again on every later turn until compaction, so one broad read can cost more than several focused ones. Each separate call also costs a model turn, so batching independent calls saves turns. Weigh both.
54
-
55
- Use the simplest operation that can establish the required relationship:
56
-
57
- - known file, symbol, artifact, or range -> focused read or operation;
58
- - ownership, caller, or dependency question -> structured relationship query where available;
59
- - literal or generated reference -> bounded content search;
60
- - behavioral claim -> the owner's selected test, observer, or reproduction;
61
- - understood effect -> narrow direct mutation;
62
- - unknown location -> bounded discovery, then narrow from its result.
63
-
64
- Choose scope before running: directory, source kind, pattern, range, test target, time window, result count, fields, affected state, or recovery scope. Exclude unrelated history, generated output, and dependencies unless the question needs them. When volume is uncertain, run a location or count query before requesting all matching bodies, and prefer bounded output with an accessible full result.
65
-
66
- Recover saved output instead of rerunning its command, and use a script when a settled loop over many results (filter, parse, compare, aggregate) would otherwise take many model turns. A script runs known steps; return to ordinary calls when a result needs a new decision.
67
-
68
- Use host-supplied usage when available; do not invent token counts or treat the provider maximum as a promise that the work will fit. The owner chooses the work horizon: return an unexpectedly large context need to it instead of reading the whole dependency tree or silently shrinking acceptance.
69
-
70
- ## Observe Before Continuing
71
-
72
- Goal: know what changed before deciding what comes next.
73
-
74
- After an interaction, establish what actually ran or was returned, what changed in evidence, hypotheses, implementation, or task state, whether the intended question was answered or effect produced, and what uncertainty, partial effect, or contradiction remains. New content is not automatically useful evidence.
75
-
76
- When a read settles the question, stop that investigation. An invalidated implementation premise needs reassessment before dependent effects; ordinary local continuation can proceed.
77
-
78
- ## Notice A Stall Early
79
-
80
- Goal: stop spending interactions that no longer change anything.
81
-
82
- If an interaction did not advance the question, do not repeat it with synonyms, nearby files, a wider equivalent search, or another tool with the same evidence relationship. Change the question or the kind of observer, or report the missing evidence.
83
-
84
- The common stalls are rerunning a check against unchanged state, rereading an unchanged source without a new question, widening a search without narrowing the hypothesis, and alternating edits, failures, and reversions without a supported cause. When two or more recent interactions have not changed understanding, advanced the covered effect, or supported a new branch, read [Trajectory Stalls](references/trajectory-stalls.md) before another interaction.
85
-
86
- For unexplained repeated failure, use [Diagnose Failure](../diagnose-failure/SKILL.md).
87
-
88
- ## Return
89
-
90
- Return the observation and material state change to the same owner. Stop when the immediate need is satisfied, the active contract requires return, no useful covered interaction remains, or another activity must settle the next choice. Reuse adequate evidence instead of generating new calls to justify completion.
91
-
92
- The goal is fewer low-value interactions while preserving sufficient evidence and the agreed outcome, not fewer calls at any cost.