@cad0p/pi-steering 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/LICENSE +29 -0
  3. package/README.md +920 -0
  4. package/dist/__test-helpers__.d.ts +95 -0
  5. package/dist/__test-helpers__.d.ts.map +1 -0
  6. package/dist/__test-helpers__.js +174 -0
  7. package/dist/__test-helpers__.js.map +1 -0
  8. package/dist/bin/pi-steering.d.ts +9 -0
  9. package/dist/bin/pi-steering.d.ts.map +1 -0
  10. package/dist/bin/pi-steering.js +506 -0
  11. package/dist/bin/pi-steering.js.map +1 -0
  12. package/dist/compat.d.ts +50 -0
  13. package/dist/compat.d.ts.map +1 -0
  14. package/dist/compat.js +180 -0
  15. package/dist/compat.js.map +1 -0
  16. package/dist/defaults.d.ts +61 -0
  17. package/dist/defaults.d.ts.map +1 -0
  18. package/dist/defaults.js +106 -0
  19. package/dist/defaults.js.map +1 -0
  20. package/dist/define-config.d.ts +235 -0
  21. package/dist/define-config.d.ts.map +1 -0
  22. package/dist/define-config.js +118 -0
  23. package/dist/define-config.js.map +1 -0
  24. package/dist/define-predicate.d.ts +49 -0
  25. package/dist/define-predicate.d.ts.map +1 -0
  26. package/dist/define-predicate.js +35 -0
  27. package/dist/define-predicate.js.map +1 -0
  28. package/dist/evaluator-internals/context.d.ts +186 -0
  29. package/dist/evaluator-internals/context.d.ts.map +1 -0
  30. package/dist/evaluator-internals/context.js +219 -0
  31. package/dist/evaluator-internals/context.js.map +1 -0
  32. package/dist/evaluator-internals/override.d.ts +19 -0
  33. package/dist/evaluator-internals/override.d.ts.map +1 -0
  34. package/dist/evaluator-internals/override.js +79 -0
  35. package/dist/evaluator-internals/override.js.map +1 -0
  36. package/dist/evaluator-internals/predicates.d.ts +152 -0
  37. package/dist/evaluator-internals/predicates.d.ts.map +1 -0
  38. package/dist/evaluator-internals/predicates.js +849 -0
  39. package/dist/evaluator-internals/predicates.js.map +1 -0
  40. package/dist/evaluator-internals/speculative-synthesis.d.ts +102 -0
  41. package/dist/evaluator-internals/speculative-synthesis.d.ts.map +1 -0
  42. package/dist/evaluator-internals/speculative-synthesis.js +101 -0
  43. package/dist/evaluator-internals/speculative-synthesis.js.map +1 -0
  44. package/dist/evaluator.d.ts +101 -0
  45. package/dist/evaluator.d.ts.map +1 -0
  46. package/dist/evaluator.js +714 -0
  47. package/dist/evaluator.js.map +1 -0
  48. package/dist/helpers/walker-unknown-cwd-reason.d.ts +68 -0
  49. package/dist/helpers/walker-unknown-cwd-reason.d.ts.map +1 -0
  50. package/dist/helpers/walker-unknown-cwd-reason.js +73 -0
  51. package/dist/helpers/walker-unknown-cwd-reason.js.map +1 -0
  52. package/dist/index.d.ts +42 -0
  53. package/dist/index.d.ts.map +1 -0
  54. package/dist/index.js +93 -0
  55. package/dist/index.js.map +1 -0
  56. package/dist/internal/drop-unused-observers.d.ts +43 -0
  57. package/dist/internal/drop-unused-observers.d.ts.map +1 -0
  58. package/dist/internal/drop-unused-observers.js +50 -0
  59. package/dist/internal/drop-unused-observers.js.map +1 -0
  60. package/dist/internal/finalize-plugin-state.d.ts +22 -0
  61. package/dist/internal/finalize-plugin-state.d.ts.map +1 -0
  62. package/dist/internal/finalize-plugin-state.js +14 -0
  63. package/dist/internal/finalize-plugin-state.js.map +1 -0
  64. package/dist/internal/merge-observers.d.ts +30 -0
  65. package/dist/internal/merge-observers.d.ts.map +1 -0
  66. package/dist/internal/merge-observers.js +27 -0
  67. package/dist/internal/merge-observers.js.map +1 -0
  68. package/dist/internal/pattern-utils.d.ts +33 -0
  69. package/dist/internal/pattern-utils.d.ts.map +1 -0
  70. package/dist/internal/pattern-utils.js +20 -0
  71. package/dist/internal/pattern-utils.js.map +1 -0
  72. package/dist/internal/ref-text.d.ts +11 -0
  73. package/dist/internal/ref-text.d.ts.map +1 -0
  74. package/dist/internal/ref-text.js +15 -0
  75. package/dist/internal/ref-text.js.map +1 -0
  76. package/dist/internal/session-runtime.d.ts +44 -0
  77. package/dist/internal/session-runtime.d.ts.map +1 -0
  78. package/dist/internal/session-runtime.js +143 -0
  79. package/dist/internal/session-runtime.js.map +1 -0
  80. package/dist/internal/watch-matcher.d.ts +56 -0
  81. package/dist/internal/watch-matcher.d.ts.map +1 -0
  82. package/dist/internal/watch-matcher.js +179 -0
  83. package/dist/internal/watch-matcher.js.map +1 -0
  84. package/dist/loader.d.ts +97 -0
  85. package/dist/loader.d.ts.map +1 -0
  86. package/dist/loader.js +527 -0
  87. package/dist/loader.js.map +1 -0
  88. package/dist/observer-dispatcher.d.ts +69 -0
  89. package/dist/observer-dispatcher.d.ts.map +1 -0
  90. package/dist/observer-dispatcher.js +184 -0
  91. package/dist/observer-dispatcher.js.map +1 -0
  92. package/dist/plugin-merger.d.ts +175 -0
  93. package/dist/plugin-merger.d.ts.map +1 -0
  94. package/dist/plugin-merger.js +450 -0
  95. package/dist/plugin-merger.js.map +1 -0
  96. package/dist/plugins/git/branch-tracker.d.ts +85 -0
  97. package/dist/plugins/git/branch-tracker.d.ts.map +1 -0
  98. package/dist/plugins/git/branch-tracker.js +181 -0
  99. package/dist/plugins/git/branch-tracker.js.map +1 -0
  100. package/dist/plugins/git/cwd-extensions.d.ts +10 -0
  101. package/dist/plugins/git/cwd-extensions.d.ts.map +1 -0
  102. package/dist/plugins/git/cwd-extensions.js +155 -0
  103. package/dist/plugins/git/cwd-extensions.js.map +1 -0
  104. package/dist/plugins/git/git-ops.d.ts +89 -0
  105. package/dist/plugins/git/git-ops.d.ts.map +1 -0
  106. package/dist/plugins/git/git-ops.js +107 -0
  107. package/dist/plugins/git/git-ops.js.map +1 -0
  108. package/dist/plugins/git/index.d.ts +225 -0
  109. package/dist/plugins/git/index.d.ts.map +1 -0
  110. package/dist/plugins/git/index.js +52 -0
  111. package/dist/plugins/git/index.js.map +1 -0
  112. package/dist/plugins/git/predicates.d.ts +312 -0
  113. package/dist/plugins/git/predicates.d.ts.map +1 -0
  114. package/dist/plugins/git/predicates.js +580 -0
  115. package/dist/plugins/git/predicates.js.map +1 -0
  116. package/dist/plugins/git/rules.d.ts +209 -0
  117. package/dist/plugins/git/rules.d.ts.map +1 -0
  118. package/dist/plugins/git/rules.js +267 -0
  119. package/dist/plugins/git/rules.js.map +1 -0
  120. package/dist/schema.d.ts +1799 -0
  121. package/dist/schema.d.ts.map +1 -0
  122. package/dist/schema.js +4 -0
  123. package/dist/schema.js.map +1 -0
  124. package/dist/testing/index.d.ts +621 -0
  125. package/dist/testing/index.d.ts.map +1 -0
  126. package/dist/testing/index.js +747 -0
  127. package/dist/testing/index.js.map +1 -0
  128. package/examples/README.md +83 -0
  129. package/examples/combined-git-discipline/README.md +52 -0
  130. package/examples/combined-git-discipline/node_modules/.bin/pi-steering +43 -0
  131. package/examples/combined-git-discipline/package.json +18 -0
  132. package/examples/combined-git-discipline/steering.json +27 -0
  133. package/examples/combined-git-discipline/steering.test.ts +42 -0
  134. package/examples/combined-git-discipline/steering.ts +64 -0
  135. package/examples/combined-git-discipline/tsconfig.json +7 -0
  136. package/examples/draft-prs-only/README.md +42 -0
  137. package/examples/draft-prs-only/node_modules/.bin/pi-steering +43 -0
  138. package/examples/draft-prs-only/package.json +18 -0
  139. package/examples/draft-prs-only/steering.json +12 -0
  140. package/examples/draft-prs-only/steering.test.ts +48 -0
  141. package/examples/draft-prs-only/steering.ts +36 -0
  142. package/examples/draft-prs-only/tsconfig.json +7 -0
  143. package/examples/dynamic-reason-runtime-cwd/README.md +148 -0
  144. package/examples/dynamic-reason-runtime-cwd/node_modules/.bin/pi-steering +43 -0
  145. package/examples/dynamic-reason-runtime-cwd/package.json +18 -0
  146. package/examples/dynamic-reason-runtime-cwd/steering.test.ts +130 -0
  147. package/examples/dynamic-reason-runtime-cwd/steering.ts +82 -0
  148. package/examples/dynamic-reason-runtime-cwd/tsconfig.json +7 -0
  149. package/examples/force-push-strict/README.md +75 -0
  150. package/examples/force-push-strict/node_modules/.bin/pi-steering +43 -0
  151. package/examples/force-push-strict/package.json +18 -0
  152. package/examples/force-push-strict/steering.json +12 -0
  153. package/examples/force-push-strict/steering.test.ts +51 -0
  154. package/examples/force-push-strict/steering.ts +54 -0
  155. package/examples/force-push-strict/tsconfig.json +7 -0
  156. package/examples/no-amend/README.md +52 -0
  157. package/examples/no-amend/node_modules/.bin/pi-steering +43 -0
  158. package/examples/no-amend/package.json +18 -0
  159. package/examples/no-amend/steering.cwd-scoped.json +12 -0
  160. package/examples/no-amend/steering.json +11 -0
  161. package/examples/no-amend/steering.test.ts +49 -0
  162. package/examples/no-amend/steering.ts +38 -0
  163. package/examples/no-amend/tsconfig.json +7 -0
  164. package/examples/work-item-plugin/README.md +103 -0
  165. package/examples/work-item-plugin/node_modules/.bin/pi-steering +43 -0
  166. package/examples/work-item-plugin/package.json +19 -0
  167. package/examples/work-item-plugin/src/index.test.ts +168 -0
  168. package/examples/work-item-plugin/src/index.ts +122 -0
  169. package/examples/work-item-plugin/src/observers/npm-test-tracker.test.ts +95 -0
  170. package/examples/work-item-plugin/src/observers/npm-test-tracker.ts +88 -0
  171. package/examples/work-item-plugin/src/observers/retest-required-tracker.test.ts +81 -0
  172. package/examples/work-item-plugin/src/observers/retest-required-tracker.ts +81 -0
  173. package/examples/work-item-plugin/src/predicates/work-item-format.test.ts +157 -0
  174. package/examples/work-item-plugin/src/predicates/work-item-format.ts +99 -0
  175. package/examples/work-item-plugin/src/rules/commit-description-check.test.ts +107 -0
  176. package/examples/work-item-plugin/src/rules/commit-description-check.ts +83 -0
  177. package/examples/work-item-plugin/src/rules/commit-requires-work-item.test.ts +79 -0
  178. package/examples/work-item-plugin/src/rules/commit-requires-work-item.ts +56 -0
  179. package/examples/work-item-plugin/src/rules/push-requires-tests.test.ts +245 -0
  180. package/examples/work-item-plugin/src/rules/push-requires-tests.ts +62 -0
  181. package/examples/work-item-plugin/tsconfig.json +8 -0
  182. package/package.json +88 -0
  183. package/skills/steering-authoring/SKILL.md +102 -0
  184. package/src/INVARIANTS.md +116 -0
  185. package/src/__test-helpers__.ts +243 -0
  186. package/src/bin/pi-steering.test.ts +920 -0
  187. package/src/bin/pi-steering.ts +584 -0
  188. package/src/compat.test.ts +431 -0
  189. package/src/compat.ts +282 -0
  190. package/src/defaults.test.ts +585 -0
  191. package/src/defaults.ts +148 -0
  192. package/src/define-config.test.ts +888 -0
  193. package/src/define-config.ts +375 -0
  194. package/src/define-predicate.test.ts +70 -0
  195. package/src/define-predicate.ts +57 -0
  196. package/src/evaluator-internals/context.ts +290 -0
  197. package/src/evaluator-internals/override.test.ts +99 -0
  198. package/src/evaluator-internals/override.ts +83 -0
  199. package/src/evaluator-internals/predicates.ts +1037 -0
  200. package/src/evaluator-internals/speculative-synthesis.test.ts +411 -0
  201. package/src/evaluator-internals/speculative-synthesis.ts +199 -0
  202. package/src/evaluator.test.ts +6296 -0
  203. package/src/evaluator.ts +1106 -0
  204. package/src/factory-time-load.test.ts +630 -0
  205. package/src/helpers/walker-unknown-cwd-reason.test.ts +73 -0
  206. package/src/helpers/walker-unknown-cwd-reason.ts +83 -0
  207. package/src/index.test.ts +836 -0
  208. package/src/index.ts +229 -0
  209. package/src/internal/drop-unused-observers.test.ts +141 -0
  210. package/src/internal/drop-unused-observers.ts +81 -0
  211. package/src/internal/finalize-plugin-state.ts +43 -0
  212. package/src/internal/merge-observers.ts +51 -0
  213. package/src/internal/pattern-utils.test.ts +52 -0
  214. package/src/internal/pattern-utils.ts +38 -0
  215. package/src/internal/ref-text.test.ts +54 -0
  216. package/src/internal/ref-text.ts +17 -0
  217. package/src/internal/session-runtime.test.ts +629 -0
  218. package/src/internal/session-runtime.ts +201 -0
  219. package/src/internal/watch-matcher.test.ts +326 -0
  220. package/src/internal/watch-matcher.ts +200 -0
  221. package/src/jsdoc-propagation.test.ts +277 -0
  222. package/src/loader.test.ts +1098 -0
  223. package/src/loader.ts +581 -0
  224. package/src/not-block-onunknown.test.ts +554 -0
  225. package/src/observer-dispatcher.test.ts +939 -0
  226. package/src/observer-dispatcher.ts +290 -0
  227. package/src/per-predicate-typing.test.ts +361 -0
  228. package/src/plugin-merger.test.ts +790 -0
  229. package/src/plugin-merger.ts +598 -0
  230. package/src/plugins/git/README.md +485 -0
  231. package/src/plugins/git/branch-tracker.test.ts +281 -0
  232. package/src/plugins/git/branch-tracker.ts +187 -0
  233. package/src/plugins/git/cwd-extensions.test.ts +230 -0
  234. package/src/plugins/git/cwd-extensions.ts +160 -0
  235. package/src/plugins/git/git-ops.test.ts +397 -0
  236. package/src/plugins/git/git-ops.ts +173 -0
  237. package/src/plugins/git/index.ts +253 -0
  238. package/src/plugins/git/integration.test.ts +705 -0
  239. package/src/plugins/git/predicates.test.ts +1401 -0
  240. package/src/plugins/git/predicates.ts +693 -0
  241. package/src/plugins/git/rules.test.ts +1001 -0
  242. package/src/plugins/git/rules.ts +307 -0
  243. package/src/schema.test.ts +259 -0
  244. package/src/schema.ts +1963 -0
  245. package/src/testing/index.test.ts +1696 -0
  246. package/src/testing/index.ts +1472 -0
@@ -0,0 +1,506 @@
1
+ #!/usr/bin/env node
2
+ // SPDX-License-Identifier: MIT
3
+ // Part of pi-steering.
4
+ /**
5
+ * `@cad0p/pi-steering` CLI. Two subcommands:
6
+ *
7
+ * pi-steering import-json <input.json> [-o <output.ts>]
8
+ * Convert a v1 JSON config to the v2 TS config shape.
9
+ *
10
+ * pi-steering list [--format=text|json]
11
+ * Resolve the walk-up config from the CWD and print the
12
+ * effective plugins / rules / observers / disables.
13
+ *
14
+ * Exit codes:
15
+ * 0 - success
16
+ * 1 - invalid arguments / file read / parse error / `list`
17
+ * surfaced one or more error-class diagnostics (CI-lint signal)
18
+ * 2 - import-json conversion error ({@link FromJSONError})
19
+ */
20
+ import { readFile, writeFile } from "node:fs/promises";
21
+ import { FromJSONError, fromJSON } from "../compat.js";
22
+ import { EVALUATOR_BUILTIN_TRACKERS } from "../evaluator.js";
23
+ import { finalizePluginState } from "../internal/finalize-plugin-state.js";
24
+ import { formatSingleLineDiagnostic, runMergerPipeline, } from "../internal/session-runtime.js";
25
+ import { loadConfigs } from "../loader.js";
26
+ /**
27
+ * CLI entrypoint. Exported (not just `void main(...)` at module top)
28
+ * so the test suite can exercise the argument parser without spawning
29
+ * a subprocess. Real invocation goes through the bottom-of-file
30
+ * bootstrap when this module is run as `node pi-steering.js`.
31
+ */
32
+ export async function main(argv) {
33
+ const args = argv.slice(2);
34
+ if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
35
+ printHelp();
36
+ return 0;
37
+ }
38
+ const [subcommand, ...rest] = args;
39
+ if (subcommand === "import-json") {
40
+ return runImportJson(rest);
41
+ }
42
+ if (subcommand === "list") {
43
+ return runList(rest);
44
+ }
45
+ process.stderr.write(`pi-steering: unknown subcommand "${subcommand}"\n\n`);
46
+ printHelp();
47
+ return 1;
48
+ }
49
+ function printHelp() {
50
+ process.stdout.write(`pi-steering — tools for pi-steering
51
+
52
+ USAGE
53
+ pi-steering <subcommand> [options]
54
+
55
+ SUBCOMMANDS
56
+ import-json <input.json> [-o <output.ts>]
57
+ Convert a v1 JSON steering config to v2 TS form. Writes to
58
+ <output.ts> if specified, else stdout. See the README for
59
+ the JSON-to-TS conversion surface and rejected features.
60
+
61
+ list [--format=text|json]
62
+ Load the effective config for the current directory (walk-up
63
+ from cwd) and print the resolved plugins, rules, and observers,
64
+ grouped by source. Useful for answering "which rules are
65
+ active here?" without reading the config files by hand.
66
+
67
+ OPTIONS
68
+ -h, --help Show this help.
69
+
70
+ `);
71
+ }
72
+ async function runImportJson(args) {
73
+ let inputPath = null;
74
+ let outputPath = null;
75
+ for (let i = 0; i < args.length; i++) {
76
+ const a = args[i];
77
+ if (a === "-o" || a === "--output") {
78
+ const next = args[++i];
79
+ if (next === undefined) {
80
+ process.stderr.write("pi-steering: -o requires an argument\n");
81
+ return 1;
82
+ }
83
+ outputPath = next;
84
+ }
85
+ else if (a !== undefined && a.startsWith("-")) {
86
+ process.stderr.write(`pi-steering: unknown flag "${a}"\n`);
87
+ return 1;
88
+ }
89
+ else if (inputPath === null && a !== undefined) {
90
+ inputPath = a;
91
+ }
92
+ else {
93
+ process.stderr.write("pi-steering: too many positional arguments\n");
94
+ return 1;
95
+ }
96
+ }
97
+ if (inputPath === null) {
98
+ process.stderr.write("pi-steering: import-json requires an input file\n");
99
+ return 1;
100
+ }
101
+ let raw;
102
+ try {
103
+ raw = await readFile(inputPath, "utf8");
104
+ }
105
+ catch (err) {
106
+ process.stderr.write(`pi-steering: cannot read ${inputPath}: ${err instanceof Error ? err.message : String(err)}\n`);
107
+ return 1;
108
+ }
109
+ let json;
110
+ try {
111
+ json = JSON.parse(raw);
112
+ }
113
+ catch (err) {
114
+ process.stderr.write(`pi-steering: ${inputPath} is not valid JSON: ${err instanceof Error ? err.message : String(err)}\n`);
115
+ return 1;
116
+ }
117
+ let config;
118
+ try {
119
+ config = fromJSON(json);
120
+ }
121
+ catch (err) {
122
+ if (err instanceof FromJSONError) {
123
+ process.stderr.write(`pi-steering: conversion failed at ${err.path}: ${err.message}\n`);
124
+ return 2;
125
+ }
126
+ throw err;
127
+ }
128
+ const output = renderConfig(config);
129
+ if (outputPath !== null) {
130
+ await writeFile(outputPath, output, "utf8");
131
+ process.stdout.write(`Wrote ${outputPath}\n`);
132
+ }
133
+ else {
134
+ process.stdout.write(output);
135
+ }
136
+ return 0;
137
+ }
138
+ /**
139
+ * Render a {@link SteeringConfig} as a v2 TS file using `defineConfig`.
140
+ * Uses `JSON.stringify` for the config value since v1 rules only carry
141
+ * string / number / boolean / array — JSON literal rendering is
142
+ * semantically identical to the TS object literal.
143
+ */
144
+ function renderConfig(config) {
145
+ const body = JSON.stringify(config, null, 2);
146
+ return `// Generated by \`pi-steering import-json\`.
147
+ // Edit freely — this is your steering config now.
148
+
149
+ import { defineConfig } from "@cad0p/pi-steering";
150
+
151
+ export default defineConfig(${body});
152
+ `;
153
+ }
154
+ // ---------------------------------------------------------------------------
155
+ // `list` subcommand
156
+ // ---------------------------------------------------------------------------
157
+ /**
158
+ * Parse the `list` flag set and print the resolved config.
159
+ *
160
+ * Flags:
161
+ * --format=text (default)
162
+ * --format=json machine-readable JSON
163
+ * -h / --help per-subcommand help
164
+ */
165
+ async function runList(args) {
166
+ let format = "text";
167
+ for (const a of args) {
168
+ if (a === "--help" || a === "-h") {
169
+ printListHelp();
170
+ return 0;
171
+ }
172
+ if (a === "--format=text") {
173
+ format = "text";
174
+ }
175
+ else if (a === "--format=json") {
176
+ format = "json";
177
+ }
178
+ else if (a.startsWith("--format=")) {
179
+ process.stderr.write(`pi-steering: unknown --format value "${a.slice("--format=".length)}"; use text|json\n`);
180
+ return 1;
181
+ }
182
+ else {
183
+ process.stderr.write(`pi-steering: unknown flag "${a}"\n`);
184
+ return 1;
185
+ }
186
+ }
187
+ // Walk up from cwd and merge. CLI deliberately omits
188
+ // DEFAULT_PLUGINS / DEFAULT_RULES; runtime injects them.
189
+ let layers;
190
+ let loaderDiagnostics = [];
191
+ try {
192
+ ({ layers, diagnostics: loaderDiagnostics } = await loadConfigs(process.cwd()));
193
+ }
194
+ catch (err) {
195
+ process.stderr.write(`pi-steering: failed to load config: ${err instanceof Error ? err.message : String(err)}\n`);
196
+ return 1;
197
+ }
198
+ // Surface loader-side diagnostics on stderr in the legacy shape so
199
+ // users running `pi-steering list` against a tree with broken layers,
200
+ // dual-form coexistence, stray files, or cross-layer collisions see
201
+ // them — restores the pre-refactor visibility the loader's direct
202
+ // `console.warn` calls used to provide. Track whether any error-
203
+ // class diagnostic was emitted so the CLI can exit non-zero, giving
204
+ // CI lint pipelines a binary signal that the config would refuse to
205
+ // start in production.
206
+ //
207
+ // CLI deliberately renders errors inline rather than via the
208
+ // aggregated thrown-Error form: the audience is a CI grep target,
209
+ // not a human reading a single Error.message.
210
+ let sawError = false;
211
+ const recordDiagnostic = (d) => {
212
+ if (d.type === "error")
213
+ sawError = true;
214
+ process.stderr.write(`${formatSingleLineDiagnostic(d)}\n`);
215
+ };
216
+ for (const d of loaderDiagnostics) {
217
+ recordDiagnostic(d);
218
+ }
219
+ if (layers.length === 0) {
220
+ if (format === "json") {
221
+ process.stdout.write(`${JSON.stringify(emptyListJSON(), null, 2)}\n`);
222
+ }
223
+ else {
224
+ process.stdout.write("No steering config found.\n");
225
+ }
226
+ return sawError ? 1 : 0;
227
+ }
228
+ const { config, diagnostics: mergeAndResolveDiagnostics } = runCliMergeWithInfoCapture(layers);
229
+ for (const d of mergeAndResolveDiagnostics) {
230
+ recordDiagnostic(d);
231
+ }
232
+ if (format === "json") {
233
+ process.stdout.write(`${JSON.stringify(renderListJSON(config), null, 2)}\n`);
234
+ }
235
+ else {
236
+ process.stdout.write(renderListText(config));
237
+ }
238
+ return sawError ? 1 : 0;
239
+ }
240
+ /**
241
+ * CLI variant of the merge pipeline. Redirects `console.info`
242
+ * breadcrumbs (disabled-plugin / disabled-rule / dropped-observer)
243
+ * onto stderr so stdout stays clean for `--format=json`. After
244
+ * {@link runMergerPipeline}, mirrors {@link buildSessionRuntime}'s
245
+ * `disabledRules` filter + `finalizePluginState` so `pi-steering
246
+ * list` reports the same observer-drop set production sees.
247
+ */
248
+ function runCliMergeWithInfoCapture(layers) {
249
+ const originalInfo = console.info;
250
+ console.info = (...args) => {
251
+ process.stderr.write(`${args.map((a) => String(a)).join(" ")}\n`);
252
+ };
253
+ try {
254
+ const { merged, resolved, diagnostics } = runMergerPipeline(layers, undefined, EVALUATOR_BUILTIN_TRACKERS);
255
+ // Skipped on merge short-circuit; without resolved we can't
256
+ // enumerate plugin-side observers.
257
+ if (resolved !== null) {
258
+ const userObservers = merged.observers ?? [];
259
+ // Mirror the runtime's `disabledRules` filter (see
260
+ // `buildSessionRuntime` in `internal/session-runtime.ts`)
261
+ // before invoking `finalizePluginState`. Without this
262
+ // filter, observers whose only consumer is a disabled rule
263
+ // would appear consumed in the CLI but get dropped by the
264
+ // runtime — a divergence between `pi-steering list` and
265
+ // what production sees.
266
+ const disabledRules = new Set(merged.disabledRules ?? []);
267
+ const userRules = (merged.rules ?? []).filter((r) => !disabledRules.has(r.name));
268
+ finalizePluginState(userRules, resolved.rules, userObservers, resolved.observers);
269
+ }
270
+ return { config: merged, diagnostics };
271
+ }
272
+ finally {
273
+ console.info = originalInfo;
274
+ }
275
+ }
276
+ function printListHelp() {
277
+ process.stdout.write(`pi-steering list — show the resolved config
278
+
279
+ USAGE
280
+ pi-steering list [--format=text|json]
281
+
282
+ Walks up from the current directory looking for .pi/steering/index.ts
283
+ (or .pi/steering.ts) at each ancestor. Merges the layers inner-first
284
+ and prints the effective plugins, rules, and observers.
285
+
286
+ FLAGS
287
+ --format=text (default) human-readable grouped output
288
+ --format=json machine-readable JSON
289
+ -h, --help show this help
290
+
291
+ EXIT CODES
292
+ 0 resolved successfully (warnings, if any, are fail-soft)
293
+ 1 one or more error-class diagnostics surfaced — production
294
+ runtime would refuse to start on this config; CI lint pipelines
295
+ can gate on this code
296
+
297
+ EXAMPLES
298
+ pi-steering list
299
+ pi-steering list --format=json
300
+
301
+ `);
302
+ }
303
+ /**
304
+ * Curated mapping from a plugin's `name` to a short human-readable
305
+ * source label (used in the `name [source]` header in text output).
306
+ * Covers plugins shipped by this package. Unknown plugin names get
307
+ * no bracket — the plugin name alone is enough for the user to
308
+ * locate it.
309
+ */
310
+ const KNOWN_PLUGIN_SOURCES = {
311
+ git: "pi-steering/plugins/git",
312
+ };
313
+ /**
314
+ * Render the config as JSON for machine consumption.
315
+ *
316
+ * Shape:
317
+ * {
318
+ * plugins: [{ name, source?, rules: [{ name, tool, when }], observers: [...] }],
319
+ * userRules: [{ name, tool, when }],
320
+ * userObservers: [{ name, writes }],
321
+ * disabled: { rules: [...], plugins: [...] },
322
+ * defaultNoOverride: bool|null,
323
+ * disableDefaults: bool|null
324
+ * }
325
+ */
326
+ function renderListJSON(config) {
327
+ const disabledSet = new Set(config.disabledRules ?? []);
328
+ const disabledPluginsSet = new Set(config.disabledPlugins ?? []);
329
+ const plugins = (config.plugins ?? []).map((p) => ({
330
+ name: p.name,
331
+ ...(KNOWN_PLUGIN_SOURCES[p.name] !== undefined
332
+ ? { source: KNOWN_PLUGIN_SOURCES[p.name] }
333
+ : {}),
334
+ ...(disabledPluginsSet.has(p.name) ? { disabled: true } : {}),
335
+ rules: (p.rules ?? []).map((r) => ruleJSON(r, disabledSet)),
336
+ observers: (p.observers ?? []).map((o) => observerJSON(o)),
337
+ }));
338
+ return {
339
+ plugins,
340
+ userRules: (config.rules ?? []).map((r) => ruleJSON(r, disabledSet)),
341
+ userObservers: (config.observers ?? []).map((o) => observerJSON(o)),
342
+ disabled: {
343
+ rules: config.disabledRules ?? [],
344
+ plugins: config.disabledPlugins ?? [],
345
+ },
346
+ defaultNoOverride: config.defaultNoOverride ?? null,
347
+ disableDefaults: config.disableDefaults ?? null,
348
+ };
349
+ }
350
+ function emptyListJSON() {
351
+ return {
352
+ plugins: [],
353
+ userRules: [],
354
+ userObservers: [],
355
+ disabled: { rules: [], plugins: [] },
356
+ defaultNoOverride: null,
357
+ disableDefaults: null,
358
+ };
359
+ }
360
+ function ruleJSON(r, disabledSet) {
361
+ return {
362
+ name: r.name,
363
+ tool: r.tool,
364
+ ...(r.when !== undefined ? { when: whenSummaryKeys(r.when) } : {}),
365
+ ...(disabledSet?.has(r.name) ? { disabled: true } : {}),
366
+ };
367
+ }
368
+ function observerJSON(o) {
369
+ return {
370
+ name: o.name,
371
+ writes: o.writes ?? [],
372
+ };
373
+ }
374
+ /**
375
+ * Render the config as a grouped text block.
376
+ *
377
+ * Shape mirrors ADR §16:
378
+ *
379
+ * Resolved config: 2 plugins, 4 rules, 1 observer.
380
+ *
381
+ * git [pi-steering/plugins/git]
382
+ * no-main-commit bash when: branch
383
+ * ...
384
+ *
385
+ * User (.pi/steering/index.ts):
386
+ * (none)
387
+ *
388
+ * Disabled: (none)
389
+ */
390
+ function renderListText(config) {
391
+ const plugins = config.plugins ?? [];
392
+ const userRules = config.rules ?? [];
393
+ const userObservers = config.observers ?? [];
394
+ const disabled = config.disabledRules ?? [];
395
+ const disabledPlugins = config.disabledPlugins ?? [];
396
+ const disabledSet = new Set(disabled);
397
+ const disabledPluginsSet = new Set(disabledPlugins);
398
+ const totalRules = plugins.reduce((n, p) => n + (p.rules?.length ?? 0), 0) + userRules.length;
399
+ const totalObservers = plugins.reduce((n, p) => n + (p.observers?.length ?? 0), 0) +
400
+ userObservers.length;
401
+ const lines = [];
402
+ lines.push(`Resolved config: ${plugins.length} ${plural("plugin", plugins.length)}, ${totalRules} ${plural("rule", totalRules)}, ${totalObservers} ${plural("observer", totalObservers)}.`);
403
+ lines.push("");
404
+ // Per-plugin block.
405
+ for (const plugin of plugins) {
406
+ const source = KNOWN_PLUGIN_SOURCES[plugin.name];
407
+ const pluginDisabled = disabledPluginsSet.has(plugin.name);
408
+ const suffix = pluginDisabled ? " (disabled)" : "";
409
+ const header = source
410
+ ? `${plugin.name} [${source}]${suffix}`
411
+ : `${plugin.name}${suffix}`;
412
+ lines.push(header);
413
+ renderRuleLines(plugin.rules ?? [], lines, disabledSet);
414
+ renderObserverLines(plugin.observers ?? [], lines);
415
+ lines.push("");
416
+ }
417
+ // User block.
418
+ lines.push("User (.pi/steering/index.ts):");
419
+ if (userRules.length === 0 && userObservers.length === 0) {
420
+ lines.push(" (none)");
421
+ }
422
+ else {
423
+ renderRuleLines(userRules, lines, disabledSet);
424
+ renderObserverLines(userObservers, lines);
425
+ }
426
+ lines.push("");
427
+ // Disabled block.
428
+ if (disabled.length === 0 && disabledPlugins.length === 0) {
429
+ lines.push("Disabled: (none)");
430
+ }
431
+ else {
432
+ if (disabled.length > 0) {
433
+ lines.push(`Disabled rules: ${disabled.join(", ")}`);
434
+ }
435
+ if (disabledPlugins.length > 0) {
436
+ lines.push(`Disabled plugins: ${disabledPlugins.join(", ")}`);
437
+ }
438
+ }
439
+ lines.push("");
440
+ return lines.join("\n");
441
+ }
442
+ function renderRuleLines(rules, lines, disabledSet) {
443
+ if (rules.length === 0)
444
+ return;
445
+ const nameWidth = Math.max(...rules.map((r) => r.name.length), 20);
446
+ for (const r of rules) {
447
+ const tools = r.tool.padEnd(5);
448
+ const whenSummary = r.when ? ` when: ${whenSummaryKeys(r.when)}` : "";
449
+ const disabledSuffix = disabledSet?.has(r.name) ? " (disabled)" : "";
450
+ lines.push(` ${r.name.padEnd(nameWidth)} ${tools}${whenSummary}${disabledSuffix}`);
451
+ }
452
+ }
453
+ function renderObserverLines(observers, lines) {
454
+ if (observers.length === 0)
455
+ return;
456
+ for (const o of observers) {
457
+ const writes = o.writes && o.writes.length > 0 ? ` writes: ${o.writes.join(", ")}` : "";
458
+ lines.push(` observer: ${o.name}${writes}`);
459
+ }
460
+ }
461
+ /**
462
+ * Compact summary of a `TopLevelWhenClause`. Returns a comma-separated list
463
+ * of keys (e.g. `branch, cwd`). Built-in keys get special labels so
464
+ * the output is informative without dumping full predicate values:
465
+ * - `happened` becomes `happened:<event>`
466
+ * - `not` becomes `not:...`
467
+ * - `condition` stays `condition`
468
+ * - plugin predicates just show the key name (`branch`, `upstream`, …).
469
+ */
470
+ function whenSummaryKeys(when) {
471
+ const parts = [];
472
+ for (const key of Object.keys(when)) {
473
+ if (key === "happened") {
474
+ const happened = when.happened;
475
+ if (happened !== undefined) {
476
+ parts.push(`happened:${happened.event}`);
477
+ }
478
+ else {
479
+ parts.push("happened");
480
+ }
481
+ }
482
+ else if (key === "not") {
483
+ parts.push("not:...");
484
+ }
485
+ else {
486
+ // Everything else (cwd, condition, plugin predicates) renders
487
+ // as its key name — the source file is the canonical place
488
+ // to look up the full value.
489
+ parts.push(key);
490
+ }
491
+ }
492
+ return parts.join(", ");
493
+ }
494
+ function plural(word, n) {
495
+ return n === 1 ? word : `${word}s`;
496
+ }
497
+ // Bootstrap: only invoke `main` when this module is the entry point,
498
+ // not when imported for testing. `import.meta.url` matches `argv[1]`
499
+ // when run as `node pi-steering.js`.
500
+ const entry = process.argv[1];
501
+ if (entry !== undefined && import.meta.url === `file://${entry}`) {
502
+ void main(process.argv).then((code) => {
503
+ process.exit(code);
504
+ });
505
+ }
506
+ //# sourceMappingURL=pi-steering.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-steering.js","sourceRoot":"","sources":["../../src/bin/pi-steering.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * `fromJSON` — convert the v1 JSON config shape to a v2
3
+ * {@link SteeringConfig}.
4
+ *
5
+ * Per the accepted ADR ("Design → File layout and loader behavior"):
6
+ * JSON is not a first-class config format in v2. `fromJSON` exists so
7
+ * `.pi/steering.json` files authored against the PoC shape can be
8
+ * loaded programmatically — either as a library call (this module)
9
+ * or via the `pi-steering import-json` CLI wrapping it.
10
+ *
11
+ * Scope:
12
+ *
13
+ * - Top-level v1 fields: `disable`, `defaultNoOverride`, `rules`.
14
+ * - Rule fields: `name`, `tool`, `field`, `pattern` (stays a string —
15
+ * v2 accepts `string | RegExp`), `requires`, `unless`, `reason`,
16
+ * `noOverride`, `when.cwd` (string pattern).
17
+ *
18
+ * Rejected (throws):
19
+ *
20
+ * - Plugins (JSON can't express function-typed handlers).
21
+ * - Observers (ditto — `onResult` is a function).
22
+ * - Function-valued fields on rules (ditto).
23
+ * - `when.<customKey>` — plugin-registered predicates have no
24
+ * JSON-expressible binding.
25
+ * - `when.not` or `when.condition` (also function-shaped or recursive).
26
+ *
27
+ * Callers that hit one of the rejection cases should author the
28
+ * offending rule / plugin directly in TypeScript; `fromJSON` is only
29
+ * for the trivial pattern-string path.
30
+ */
31
+ import type { SteeringConfig } from "./schema.ts";
32
+ /**
33
+ * Error thrown when the input JSON uses a feature the v1 → v2 helper
34
+ * can't represent. Carries a `path` pointing at the offending location
35
+ * (e.g. `rules[2].when.branch`) so callers can point the user at the
36
+ * rule to rewrite in TypeScript.
37
+ */
38
+ export declare class FromJSONError extends Error {
39
+ readonly path: string;
40
+ constructor(message: string, path: string);
41
+ }
42
+ /**
43
+ * Convert v1 JSON into a v2 {@link SteeringConfig}.
44
+ *
45
+ * The input is typed `unknown` deliberately — this helper accepts
46
+ * whatever came out of `JSON.parse`, validates the shape, and throws
47
+ * {@link FromJSONError} on anything it can't represent.
48
+ */
49
+ export declare function fromJSON(json: unknown): SteeringConfig;
50
+ //# sourceMappingURL=compat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compat.d.ts","sourceRoot":"","sources":["../src/compat.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAQ,cAAc,EAAc,MAAM,aAAa,CAAC;AAEpE;;;;;GAKG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;CAK1C;AAOD;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,cAAc,CAoEtD"}