@mmerterden/multi-agent-pipeline 17.6.0 → 19.0.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 (272) hide show
  1. package/CHANGELOG.md +310 -0
  2. package/README.md +76 -18
  3. package/README.tr.md +55 -16
  4. package/docs/adr/0002-instruction-driven-flag.md +1 -0
  5. package/docs/adr/0005-lazy-phase-docs.md +11 -1
  6. package/docs/adr/0008-installer-modularization-and-secret-leak-defense.md +1 -0
  7. package/docs/adr/0010-own-code-graph.md +1 -0
  8. package/docs/adr/0011-dormant-ci.md +25 -1
  9. package/docs/adr/0014-six-phase-consolidation.md +134 -0
  10. package/docs/adr/README.md +2 -1
  11. package/docs/architecture.md +37 -38
  12. package/docs/best-practices.md +1 -1
  13. package/docs/ecosystem.md +37 -26
  14. package/docs/engineering.md +1 -1
  15. package/docs/facts.json +45 -0
  16. package/docs/features.md +54 -53
  17. package/docs/performance.md +5 -5
  18. package/docs/recovery-guide.md +9 -9
  19. package/docs/server-readiness.md +188 -0
  20. package/docs/token-budget-history.md +3 -1
  21. package/index.js +18 -3
  22. package/install/_codex-agents.mjs +1 -1
  23. package/install/_common.mjs +42 -17
  24. package/install/_dev-only-files.mjs +8 -0
  25. package/install/_unattended-profile.mjs +113 -0
  26. package/install/index.mjs +48 -0
  27. package/install/templates/claude-hooks.json +1 -1
  28. package/install/templates/codex-instructions.md +1 -1
  29. package/install/templates/copilot-instructions.md +28 -28
  30. package/manifest.json +1065 -0
  31. package/package.json +6 -3
  32. package/pipeline/agents/dev-critic.md +3 -3
  33. package/pipeline/commands/figma-to-swiftui.md +1 -1
  34. package/pipeline/commands/multi-agent/SKILL.md +8 -8
  35. package/pipeline/commands/multi-agent/analysis/SKILL.md +9 -9
  36. package/pipeline/commands/multi-agent/autopilot/SKILL.md +7 -7
  37. package/pipeline/commands/multi-agent/channels/SKILL.md +15 -15
  38. package/pipeline/commands/multi-agent/diff-explain/SKILL.md +6 -6
  39. package/pipeline/commands/multi-agent/garbage-collect/SKILL.md +1 -1
  40. package/pipeline/commands/multi-agent/graph/SKILL.md +1 -1
  41. package/pipeline/commands/multi-agent/help/SKILL.md +62 -62
  42. package/pipeline/commands/multi-agent/language/SKILL.md +2 -2
  43. package/pipeline/commands/multi-agent/local/SKILL.md +11 -11
  44. package/pipeline/commands/multi-agent/local-autopilot/SKILL.md +13 -13
  45. package/pipeline/commands/multi-agent/log/SKILL.md +2 -2
  46. package/pipeline/commands/multi-agent/manual-test/SKILL.md +9 -9
  47. package/pipeline/commands/multi-agent/model/SKILL.md +69 -0
  48. package/pipeline/commands/multi-agent/refactor/SKILL.md +3 -3
  49. package/pipeline/commands/multi-agent/resume/SKILL.md +4 -4
  50. package/pipeline/commands/multi-agent/resume-local/SKILL.md +19 -17
  51. package/pipeline/commands/multi-agent/review/SKILL.md +1 -1
  52. package/pipeline/commands/multi-agent/route-off/SKILL.md +36 -0
  53. package/pipeline/commands/multi-agent/route-on/SKILL.md +74 -0
  54. package/pipeline/commands/multi-agent/route-status/SKILL.md +56 -0
  55. package/pipeline/commands/multi-agent/setup/SKILL.md +2 -2
  56. package/pipeline/commands/multi-agent/status/SKILL.md +54 -23
  57. package/pipeline/commands/multi-agent/steer/SKILL.md +2 -2
  58. package/pipeline/commands/multi-agent/sync/SKILL.md +12 -13
  59. package/pipeline/commands/multi-agent/test/SKILL.md +1 -1
  60. package/pipeline/lib/_jira-auth.sh +8 -0
  61. package/pipeline/lib/analysis-jira-write.sh +32 -0
  62. package/pipeline/lib/ask-choice.sh +13 -2
  63. package/pipeline/lib/autopilot-state.sh +8 -0
  64. package/pipeline/lib/credential-inventory.sh +1 -1
  65. package/pipeline/lib/fatal.mjs +129 -0
  66. package/pipeline/lib/fetch-fortify.sh +1 -1
  67. package/pipeline/lib/figma-mcp-refresh.sh +18 -0
  68. package/pipeline/lib/figma-screenshot.sh +18 -0
  69. package/pipeline/lib/invoked-directly.mjs +43 -0
  70. package/pipeline/lib/jira-publish.sh +42 -0
  71. package/pipeline/lib/md2confluence-v3.py +47 -0
  72. package/pipeline/lib/model-rung.sh +142 -0
  73. package/pipeline/lib/outbound-gate.mjs +175 -0
  74. package/pipeline/lib/phase-schema.mjs +88 -0
  75. package/pipeline/lib/plan-todos.sh +32 -11
  76. package/pipeline/lib/post-pr-review.sh +77 -8
  77. package/pipeline/lib/repo-hygiene.sh +8 -3
  78. package/pipeline/lib/require-jq.sh +40 -0
  79. package/pipeline/lib/route-state.sh +161 -0
  80. package/pipeline/lib/run-paths.sh +335 -0
  81. package/pipeline/multi-agent-refs/_account-picker.md +1 -1
  82. package/pipeline/multi-agent-refs/_dev-context.md +1 -1
  83. package/pipeline/multi-agent-refs/_input-parser.md +1 -1
  84. package/pipeline/multi-agent-refs/analysis/evidence.md +0 -9
  85. package/pipeline/multi-agent-refs/analysis/intake.md +1 -1
  86. package/pipeline/multi-agent-refs/analysis/locked.md +21 -22
  87. package/pipeline/multi-agent-refs/analysis/render.md +1 -1
  88. package/pipeline/multi-agent-refs/analysis/synthesis.md +12 -6
  89. package/pipeline/multi-agent-refs/android-guide.md +1 -1
  90. package/pipeline/multi-agent-refs/audit-guide.md +13 -13
  91. package/pipeline/multi-agent-refs/channels/issue-comment.md +2 -2
  92. package/pipeline/multi-agent-refs/channels/jira.md +3 -3
  93. package/pipeline/multi-agent-refs/channels/pr.md +4 -4
  94. package/pipeline/multi-agent-refs/channels/wiki.md +1 -1
  95. package/pipeline/multi-agent-refs/component-dispatch.md +3 -3
  96. package/pipeline/multi-agent-refs/cross-cli-contract.md +31 -6
  97. package/pipeline/multi-agent-refs/features/autopilot-circuit-breaker.md +74 -4
  98. package/pipeline/multi-agent-refs/features/code-graph.md +5 -5
  99. package/pipeline/multi-agent-refs/features/cost-analysis.md +93 -0
  100. package/pipeline/multi-agent-refs/features/design-conformance.md +1 -1
  101. package/pipeline/multi-agent-refs/features/dev-critic.md +3 -3
  102. package/pipeline/multi-agent-refs/features/doctor.md +47 -2
  103. package/pipeline/multi-agent-refs/features/external-context-injection.md +3 -3
  104. package/pipeline/multi-agent-refs/features/maturity-followup.md +3 -3
  105. package/pipeline/multi-agent-refs/features/model-fallback.md +5 -5
  106. package/pipeline/multi-agent-refs/features/plan-todos.md +1 -1
  107. package/pipeline/multi-agent-refs/features/repo-map.md +1 -1
  108. package/pipeline/multi-agent-refs/features/review-delta.md +3 -3
  109. package/pipeline/multi-agent-refs/features/review-multi-repo.md +1 -1
  110. package/pipeline/multi-agent-refs/features/scope-check.md +4 -4
  111. package/pipeline/multi-agent-refs/features/skill-conformance.md +2 -2
  112. package/pipeline/multi-agent-refs/features/stack-skill-routing.md +1 -1
  113. package/pipeline/multi-agent-refs/features/verify-by-test.md +4 -4
  114. package/pipeline/multi-agent-refs/features/verify.md +83 -0
  115. package/pipeline/multi-agent-refs/features/visual-evidence.md +19 -19
  116. package/pipeline/multi-agent-refs/features/worktree-finalize.md +6 -6
  117. package/pipeline/multi-agent-refs/issue-jira-triad.md +10 -10
  118. package/pipeline/multi-agent-refs/knowledge.md +11 -11
  119. package/pipeline/multi-agent-refs/multi-repo-integration-build.md +13 -13
  120. package/pipeline/multi-agent-refs/payload-contracts.md +8 -8
  121. package/pipeline/multi-agent-refs/phases/log-format.md +10 -10
  122. package/pipeline/multi-agent-refs/phases/modes.md +30 -30
  123. package/pipeline/multi-agent-refs/phases/operations.md +21 -10
  124. package/pipeline/multi-agent-refs/phases/phase-0-init.md +25 -25
  125. package/pipeline/multi-agent-refs/phases/phase-1-plan.md +599 -0
  126. package/pipeline/multi-agent-refs/phases/{phase-3-dev.md → phase-2-dev.md} +129 -49
  127. package/pipeline/multi-agent-refs/phases/{phase-4-review.md → phase-3-review.md} +225 -107
  128. package/pipeline/multi-agent-refs/phases/{phase-6-commit.md → phase-4-commit.md} +23 -23
  129. package/pipeline/multi-agent-refs/phases/{phase-7-report.md → phase-5-report.md} +29 -29
  130. package/pipeline/multi-agent-refs/phases.md +44 -48
  131. package/pipeline/multi-agent-refs/picker-contract.md +1 -1
  132. package/pipeline/multi-agent-refs/progress-contract.md +6 -6
  133. package/pipeline/multi-agent-refs/readiness-review.md +1 -1
  134. package/pipeline/multi-agent-refs/rules.md +7 -7
  135. package/pipeline/multi-agent-refs/swiftui-guide.md +2 -2
  136. package/pipeline/multi-agent-refs/tracker-contract.md +31 -32
  137. package/pipeline/multi-agent-refs/unattended-contract.md +129 -0
  138. package/pipeline/multi-agent-refs/wiki-capture.md +14 -14
  139. package/pipeline/preferences-template.json +9 -1
  140. package/pipeline/rules/outside-the-pipeline.md +1 -1
  141. package/pipeline/schemas/agent-state.schema.json +50 -50
  142. package/pipeline/schemas/analysis-output.schema.json +2 -2
  143. package/pipeline/schemas/autopilot-config.schema.json +1 -1
  144. package/pipeline/schemas/code-graph.schema.json +1 -1
  145. package/pipeline/schemas/criteria-manifest.schema.json +1 -1
  146. package/pipeline/schemas/dev-critic-output.schema.json +1 -1
  147. package/pipeline/schemas/diff-risk.schema.json +1 -1
  148. package/pipeline/schemas/migrations/prefs-2.4.0-to-2.5.0.mjs +2 -2
  149. package/pipeline/schemas/migrations/prefs-2.6.0-to-2.7.0.mjs +31 -0
  150. package/pipeline/schemas/migrations/state-2.1.0-to-2.2.0.mjs +129 -0
  151. package/pipeline/schemas/phases.json +105 -0
  152. package/pipeline/schemas/plan-todos.schema.json +5 -5
  153. package/pipeline/schemas/planning-output.schema.json +1 -1
  154. package/pipeline/schemas/prefs.schema.json +100 -56
  155. package/pipeline/schemas/reviewer-output.schema.json +3 -3
  156. package/pipeline/schemas/route-config.schema.json +74 -0
  157. package/pipeline/schemas/scope-check.schema.json +1 -1
  158. package/pipeline/schemas/test-gap.schema.json +1 -1
  159. package/pipeline/schemas/token-budget.json +12 -18
  160. package/pipeline/schemas/triage-output.schema.json +6 -6
  161. package/pipeline/scripts/README.md +3 -3
  162. package/pipeline/scripts/_code-graph.mjs +2 -2
  163. package/pipeline/scripts/_run-paths.mjs +372 -0
  164. package/pipeline/scripts/_smoke-root.sh +1 -1
  165. package/pipeline/scripts/aggregate-metrics.mjs +65 -65
  166. package/pipeline/scripts/autopilot-arming.mjs +2 -1
  167. package/pipeline/scripts/autopilot-intake.mjs +2 -1
  168. package/pipeline/scripts/autopilot-runner.mjs +206 -2
  169. package/pipeline/scripts/build-references.mjs +2 -1
  170. package/pipeline/scripts/build-stack-plugins.mjs +10 -2
  171. package/pipeline/scripts/capture-evidence.sh +7 -2
  172. package/pipeline/scripts/capture-flush.sh +8 -8
  173. package/pipeline/scripts/capture-resume.sh +3 -3
  174. package/pipeline/scripts/classify-plan-safety.mjs +3 -2
  175. package/pipeline/scripts/cost-analyze.mjs +600 -0
  176. package/pipeline/scripts/cost-budget-check.mjs +4 -12
  177. package/pipeline/scripts/council-view.mjs +2 -1
  178. package/pipeline/scripts/crush-json.mjs +2 -1
  179. package/pipeline/scripts/diff-explain.mjs +7 -10
  180. package/pipeline/scripts/diff-risk-score.mjs +2 -1
  181. package/pipeline/scripts/doctor.mjs +140 -6
  182. package/pipeline/scripts/evidence-gate.mjs +9 -3
  183. package/pipeline/scripts/feedback-send.mjs +12 -2
  184. package/pipeline/scripts/gc-abandoned.sh +32 -16
  185. package/pipeline/scripts/gc-tmp.sh +1 -1
  186. package/pipeline/scripts/gc-worktrees.sh +12 -5
  187. package/pipeline/scripts/gen-facts.mjs +175 -0
  188. package/pipeline/scripts/gen-mode-dispatch.mjs +32 -37
  189. package/pipeline/scripts/gen-ref-toc.mjs +1 -1
  190. package/pipeline/scripts/github-ssh-setup.sh +64 -7
  191. package/pipeline/scripts/graph-mermaid.mjs +4 -2
  192. package/pipeline/scripts/graph-report.mjs +1 -1
  193. package/pipeline/scripts/jira-attach.sh +1 -1
  194. package/pipeline/scripts/keychain-save.sh +101 -30
  195. package/pipeline/scripts/learn-from-transcripts.mjs +3 -2
  196. package/pipeline/scripts/learning-curve.mjs +36 -31
  197. package/pipeline/scripts/log-metric.sh +17 -4
  198. package/pipeline/scripts/make-manifest.mjs +199 -0
  199. package/pipeline/scripts/memory-save.sh +1 -1
  200. package/pipeline/scripts/migrate-prefs.mjs +24 -6
  201. package/pipeline/scripts/migrate-state.mjs +94 -4
  202. package/pipeline/scripts/phase-banner.sh +26 -22
  203. package/pipeline/scripts/phase-tracker.sh +48 -10
  204. package/pipeline/scripts/plan-coverage-gate.mjs +8 -4
  205. package/pipeline/scripts/pre-commit-check.sh +7 -0
  206. package/pipeline/scripts/pre-push-check.sh +7 -0
  207. package/pipeline/scripts/purge.sh +23 -6
  208. package/pipeline/scripts/render-agent-log-cost.sh +10 -3
  209. package/pipeline/scripts/render-cost-summary.sh +9 -2
  210. package/pipeline/scripts/render-work-summary.sh +14 -7
  211. package/pipeline/scripts/review-file-filter.mjs +5 -3
  212. package/pipeline/scripts/review-scope.mjs +2 -1
  213. package/pipeline/scripts/routine-registry.mjs +2 -1
  214. package/pipeline/scripts/run-aggregator.mjs +26 -20
  215. package/pipeline/scripts/run-metrics.mjs +4 -2
  216. package/pipeline/scripts/runs-index.mjs +353 -0
  217. package/pipeline/scripts/scorecard-snapshot.mjs +178 -0
  218. package/pipeline/scripts/search-logs.sh +18 -0
  219. package/pipeline/scripts/smoke-cross-cli-behavior.sh +6 -6
  220. package/pipeline/scripts/smoke-schema-validation.sh +26 -7
  221. package/pipeline/scripts/test-gap-scan.mjs +2 -1
  222. package/pipeline/scripts/test-integrity-gate.mjs +2 -1
  223. package/pipeline/scripts/token-budget-report.mjs +13 -2
  224. package/pipeline/scripts/triage-memory.mjs +2 -2
  225. package/pipeline/scripts/update-issue-progress.sh +56 -7
  226. package/pipeline/scripts/usage-report.mjs +12 -1
  227. package/pipeline/scripts/validate-analysis-doc.mjs +75 -18
  228. package/pipeline/scripts/validate-code-graph.mjs +6 -3
  229. package/pipeline/scripts/validate-complaint-doc.mjs +2 -1
  230. package/pipeline/scripts/validate-diff-risk.mjs +6 -3
  231. package/pipeline/scripts/validate-planning.mjs +1 -1
  232. package/pipeline/scripts/validate-reviewer.mjs +1 -1
  233. package/pipeline/scripts/validate-state.mjs +45 -5
  234. package/pipeline/scripts/validate-test-gap.mjs +6 -3
  235. package/pipeline/scripts/validate-triage.mjs +6 -4
  236. package/pipeline/scripts/verify-citations.mjs +4 -2
  237. package/pipeline/scripts/verify.mjs +327 -0
  238. package/pipeline/scripts/worktree-finalize.sh +18 -9
  239. package/pipeline/scripts/write-state.mjs +154 -15
  240. package/pipeline/skills/.skill-manifest.json +37 -21
  241. package/pipeline/skills/.skills-index.json +104 -5
  242. package/pipeline/skills/shared/README.md +15 -6
  243. package/pipeline/skills/shared/core/apple-archive-compliance/SKILL.md +2 -2
  244. package/pipeline/skills/shared/core/google-play-compliance/SKILL.md +2 -2
  245. package/pipeline/skills/shared/core/multi-agent/SKILL.md +69 -71
  246. package/pipeline/skills/shared/core/multi-agent-autopilot/SKILL.md +3 -3
  247. package/pipeline/skills/shared/core/multi-agent-channels/SKILL.md +14 -14
  248. package/pipeline/skills/shared/core/multi-agent-diff-explain/SKILL.md +5 -5
  249. package/pipeline/skills/shared/core/multi-agent-graph/SKILL.md +1 -1
  250. package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +25 -23
  251. package/pipeline/skills/shared/core/multi-agent-language/SKILL.md +2 -2
  252. package/pipeline/skills/shared/core/multi-agent-local/SKILL.md +2 -2
  253. package/pipeline/skills/shared/core/multi-agent-local-autopilot/SKILL.md +8 -8
  254. package/pipeline/skills/shared/core/multi-agent-manual-test/SKILL.md +6 -6
  255. package/pipeline/skills/shared/core/multi-agent-model/SKILL.md +71 -0
  256. package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +3 -3
  257. package/pipeline/skills/shared/core/multi-agent-resume/SKILL.md +1 -1
  258. package/pipeline/skills/shared/core/multi-agent-resume-local/SKILL.md +7 -7
  259. package/pipeline/skills/shared/core/multi-agent-route-off/SKILL.md +39 -0
  260. package/pipeline/skills/shared/core/multi-agent-route-on/SKILL.md +76 -0
  261. package/pipeline/skills/shared/core/multi-agent-route-status/SKILL.md +59 -0
  262. package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +1 -1
  263. package/pipeline/skills/shared/core/multi-agent-status/SKILL.md +35 -11
  264. package/pipeline/skills/shared/core/multi-agent-steer/SKILL.md +2 -2
  265. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +6 -5
  266. package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/package_app.sh +4 -1
  267. package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/setup_dev_signing.sh +4 -1
  268. package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/sign-and-notarize.sh +2 -1
  269. package/pipeline/skills/skills-index.md +13 -4
  270. package/pipeline/multi-agent-refs/phases/phase-1-analysis.md +0 -263
  271. package/pipeline/multi-agent-refs/phases/phase-2-planning.md +0 -344
  272. package/pipeline/multi-agent-refs/phases/phase-5-test.md +0 -182
@@ -0,0 +1,175 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @file gen-facts.mjs - the numbers the website is allowed to state, derived.
4
+ *
5
+ * The site carried its own copies: `ArchitectureContent.tsx` said "6 faz + 51
6
+ * komut" while the repo had six phases and sixty commands. Nobody noticed,
7
+ * because a number written into a React component is guarded by nothing. This
8
+ * is the same defect `smoke-phase-contract.sh` fixes inside the pipeline, and
9
+ * the fix is the same shape: one producer, everything else reads it.
10
+ *
11
+ * Source of truth per field:
12
+ * phases pipeline/schemas/phases.json - the phase contract itself
13
+ * commandCount a count of pipeline/commands/multi-agent/<name>/SKILL.md
14
+ * skillCount a count of pipeline/skills/shared/external/<name>/SKILL.md
15
+ * toolCount the toolkit's own tools/list response, when reachable
16
+ * version package.json
17
+ *
18
+ * Counts come from the filesystem at the moment of writing, never from a README
19
+ * or a previous version of this file.
20
+ *
21
+ * Usage:
22
+ * node gen-facts.mjs write docs/facts.json
23
+ * node gen-facts.mjs --check exit 1 if the file on disk is stale
24
+ * node gen-facts.mjs --stdout print, write nothing
25
+ *
26
+ * Exit codes:
27
+ * 0 - written, or up to date
28
+ * 1 - --check found drift
29
+ * 2 - a source could not be read (nothing is written)
30
+ */
31
+
32
+ import { readFileSync, writeFileSync, readdirSync, existsSync } from "node:fs";
33
+ import { join, dirname } from "node:path";
34
+ import { fileURLToPath } from "node:url";
35
+ import { spawnSync } from "node:child_process";
36
+
37
+ const HERE = dirname(fileURLToPath(import.meta.url));
38
+ const ROOT = join(HERE, "..", "..");
39
+ const OUT = join(ROOT, "docs", "facts.json");
40
+
41
+ function die(msg) {
42
+ console.error(`gen-facts: ${msg}`);
43
+ process.exit(2);
44
+ }
45
+
46
+ function countSkillDirs(rel) {
47
+ const dir = join(ROOT, rel);
48
+ if (!existsSync(dir)) die(`missing directory: ${rel}`);
49
+ return readdirSync(dir, { withFileTypes: true }).filter(
50
+ (e) => e.isDirectory() && existsSync(join(dir, e.name, "SKILL.md")),
51
+ ).length;
52
+ }
53
+
54
+ let contract;
55
+ try {
56
+ contract = JSON.parse(readFileSync(join(ROOT, "pipeline", "schemas", "phases.json"), "utf8"));
57
+ } catch (err) {
58
+ die(`cannot read the phase contract - ${err.message}`);
59
+ }
60
+
61
+ let pkg;
62
+ try {
63
+ pkg = JSON.parse(readFileSync(join(ROOT, "package.json"), "utf8"));
64
+ } catch (err) {
65
+ die(`cannot read package.json - ${err.message}`);
66
+ }
67
+
68
+ // The toolkit is a separate repo and may not be checked out beside this one.
69
+ // Absent is reported as null rather than as a guess: a site that prints a stale
70
+ // tool count is the problem this file exists to remove, and a made-up one is
71
+ // worse than none.
72
+ let toolCount = null;
73
+ let toolkitVersion = null;
74
+ const toolkitDir = join(ROOT, "..", "multi-agent-toolkit-mcp");
75
+ if (existsSync(join(toolkitDir, "package.json"))) {
76
+ try {
77
+ toolkitVersion =
78
+ JSON.parse(readFileSync(join(toolkitDir, "package.json"), "utf8")).version ?? null;
79
+ } catch {
80
+ toolkitVersion = null;
81
+ }
82
+ // Asked of the server, not counted out of its source. Three tool families
83
+ // are defined in modules the main file only spreads in, so a regex over
84
+ // index.js returns a number that looks plausible and is wrong - the first
85
+ // version of this script said 2 when the answer was 99. tools/list is what
86
+ // a client actually receives, which is the number the site should print.
87
+ try {
88
+ const req =
89
+ [
90
+ JSON.stringify({
91
+ jsonrpc: "2.0",
92
+ id: 1,
93
+ method: "initialize",
94
+ params: {
95
+ protocolVersion: "2024-11-05",
96
+ capabilities: {},
97
+ clientInfo: { name: "gen-facts", version: "1" },
98
+ },
99
+ }),
100
+ JSON.stringify({ jsonrpc: "2.0", method: "notifications/initialized" }),
101
+ JSON.stringify({ jsonrpc: "2.0", id: 2, method: "tools/list", params: {} }),
102
+ ].join("\n") + "\n";
103
+ const res = spawnSync(process.execPath, [join(toolkitDir, "index.js")], {
104
+ input: req,
105
+ encoding: "utf8",
106
+ timeout: 30000,
107
+ });
108
+ for (const line of (res.stdout || "").split("\n")) {
109
+ if (!line.trim()) continue;
110
+ let msg;
111
+ try {
112
+ msg = JSON.parse(line);
113
+ } catch {
114
+ continue;
115
+ }
116
+ if (msg.id === 2 && Array.isArray(msg.result?.tools)) toolCount = msg.result.tools.length;
117
+ }
118
+ } catch {
119
+ toolCount = null;
120
+ }
121
+ }
122
+
123
+ const facts = {
124
+ $comment:
125
+ "Generated by pipeline/scripts/gen-facts.mjs. Do not hand-edit: the site reads this, and a number edited here instead of at its source is the drift this file removes.",
126
+ generatedAt: new Date().toISOString().slice(0, 10),
127
+ version: pkg.version,
128
+ phaseSchema: contract.phaseSchema,
129
+ phases: contract.phases.map((p) => ({ id: p.id, name: p.name })),
130
+ phaseCount: contract.phases.length,
131
+ modes: Object.fromEntries(Object.entries(contract.modes).map(([k, v]) => [k, v.phases])),
132
+ commandCount: countSkillDirs("pipeline/commands/multi-agent"),
133
+ skillCount: countSkillDirs("pipeline/skills/shared/external"),
134
+ toolCount,
135
+ toolkitVersion,
136
+ };
137
+
138
+ const body = `${JSON.stringify(facts, null, 2)}\n`;
139
+
140
+ if (process.argv.includes("--stdout")) {
141
+ process.stdout.write(body);
142
+ process.exit(0);
143
+ }
144
+
145
+ if (process.argv.includes("--check")) {
146
+ if (!existsSync(OUT)) {
147
+ console.error("gen-facts: docs/facts.json does not exist - run without --check");
148
+ process.exit(1);
149
+ }
150
+ const onDisk = JSON.parse(readFileSync(OUT, "utf8"));
151
+ const fresh = JSON.parse(body);
152
+ // generatedAt is a timestamp, not a fact: comparing it would fail every day.
153
+ delete onDisk.generatedAt;
154
+ delete fresh.generatedAt;
155
+ if (JSON.stringify(onDisk) !== JSON.stringify(fresh)) {
156
+ console.error(
157
+ "gen-facts: docs/facts.json is stale - run: node pipeline/scripts/gen-facts.mjs",
158
+ );
159
+ for (const k of Object.keys(fresh)) {
160
+ if (JSON.stringify(onDisk[k]) !== JSON.stringify(fresh[k])) {
161
+ console.error(
162
+ ` ${k}: on disk ${JSON.stringify(onDisk[k])}, derived ${JSON.stringify(fresh[k])}`,
163
+ );
164
+ }
165
+ }
166
+ process.exit(1);
167
+ }
168
+ console.log("gen-facts: docs/facts.json is current");
169
+ process.exit(0);
170
+ }
171
+
172
+ writeFileSync(OUT, body);
173
+ console.log(
174
+ `gen-facts: wrote docs/facts.json (${facts.phaseCount} phases, ${facts.commandCount} commands, ${facts.skillCount} skills, ${facts.toolCount ?? "?"} tools)`,
175
+ );
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { readFileSync } from "node:fs";
2
3
  /**
3
4
  * gen-mode-dispatch.mjs - emit the canonical Phase Tracker Contract block
4
5
  * for a given mode dispatch file (full / local / autopilot / analysis).
@@ -10,10 +11,10 @@
10
11
  * call, anti-pattern warning, and ref link are identical.
11
12
  *
12
13
  * Usage:
13
- * node pipeline/scripts/gen-mode-dispatch.mjs --mode=full # 0..7
14
- * node pipeline/scripts/gen-mode-dispatch.mjs --mode=local # 0/1/2/3/4/6/7 + local-mode caveat
15
- * node pipeline/scripts/gen-mode-dispatch.mjs --mode=autopilot # 0/1/2/3/4/6/7
16
- * node pipeline/scripts/gen-mode-dispatch.mjs --mode=analysis # 0/1/2/4/6/7 (no Dev, no Test)
14
+ * node pipeline/scripts/gen-mode-dispatch.mjs --mode=full # 0..5
15
+ * node pipeline/scripts/gen-mode-dispatch.mjs --mode=local # 0..5 + local-mode caveat
16
+ * node pipeline/scripts/gen-mode-dispatch.mjs --mode=autopilot # 0..5
17
+ * node pipeline/scripts/gen-mode-dispatch.mjs --mode=analysis # 0/1/3/4/5 (no Dev)
17
18
  *
18
19
  * v16.0.0 removed the four dev-* modes. Depth is no longer a command name: the
19
20
  * Phase 0 Step 7.5 picker asks Full or Short and sets `state.onlyDevelop`. That
@@ -35,22 +36,20 @@ const args = Object.fromEntries(
35
36
 
36
37
  const MODE = args.mode;
37
38
 
38
- const PHASE_NAMES = [
39
- "0:Init",
40
- "1:Analysis",
41
- "2:Planning",
42
- "3:Dev",
43
- "4:Review",
44
- "5:Test",
45
- "6:Commit",
46
- "7:Report",
47
- ];
48
-
49
- // Phase 5 (User Test) checks out the change from the git worktree and hands it
50
- // to the user interactively. It therefore only runs when the mode is BOTH
51
- // interactive (not autopilot) AND worktree-backed (not local), which since
52
- // v16.0.0 leaves exactly one command: `/multi-agent` itself.
53
- const PHASE_NAMES_NO_TEST = PHASE_NAMES.filter((p) => p !== "5:Test");
39
+ // The phase list has one owner: schemas/phases.json. This file used to restate
40
+ // it, which is how eight independent copies came to exist. smoke-phase-contract.sh
41
+ // holds every remaining copy to the same file.
42
+ const CONTRACT = JSON.parse(
43
+ readFileSync(new URL("../schemas/phases.json", import.meta.url), "utf8"),
44
+ );
45
+ const PHASES = CONTRACT.phases;
46
+ const modePhases = (name) =>
47
+ CONTRACT.modes[name].phases.map((id) => {
48
+ const p = PHASES.find((x) => x.id === id);
49
+ return `${p.id}:${p.name}`;
50
+ });
51
+
52
+ const PHASE_NAMES = PHASES.map((p) => `${p.id}:${p.name}`);
54
53
 
55
54
  /**
56
55
  * Mode → phases + flag descriptor. The descriptor controls the autopilot /
@@ -59,21 +58,17 @@ const PHASE_NAMES_NO_TEST = PHASE_NAMES.filter((p) => p !== "5:Test");
59
58
  * `smoke-mode-dispatch-drift.sh` can byte-equal-diff each on-disk section
60
59
  * against its generator output.
61
60
  */
62
- const MODES = {
63
- autopilot: { phases: PHASE_NAMES_NO_TEST, local: false, autopilot: true },
64
- full: { phases: PHASE_NAMES, local: false, autopilot: false, depth: true },
65
- local: { phases: PHASE_NAMES_NO_TEST, local: true, autopilot: false, depth: true },
66
- "local-autopilot": { phases: PHASE_NAMES_NO_TEST, local: true, autopilot: true },
67
- "full-local": { phases: PHASE_NAMES_NO_TEST, local: true, autopilot: false, depth: true },
68
- // Analysis produces a document, not code: no Dev, no Test, and Phase 6
69
- // publishes instead of committing. Same 8-phase contract, four of them
70
- // reinterpreted.
71
- analysis: {
72
- phases: ["0:Init", "1:Analysis", "2:Planning", "4:Review", "6:Commit", "7:Report"],
73
- local: false,
74
- autopilot: false,
75
- },
76
- };
61
+ const MODES = Object.fromEntries(
62
+ Object.entries(CONTRACT.modes).map(([name, m]) => [
63
+ name,
64
+ {
65
+ phases: modePhases(name),
66
+ local: m.local,
67
+ autopilot: m.autopilot,
68
+ ...(m.depth ? { depth: true } : {}),
69
+ },
70
+ ]),
71
+ );
77
72
 
78
73
  const spec = MODE ? MODES[MODE] : null;
79
74
  if (!spec) {
@@ -101,7 +96,7 @@ const modeLabel = MODE_LABELS[MODE] ?? `\`${MODE}\``;
101
96
  const skipNote =
102
97
  skippedIds.length > 0
103
98
  ? `${modeLabel} mode does NOT TaskCreate phases ${skippedIds.join("/")} - those are not part of the ${modeLabel} phase set (\`${spec.phases.join(" ")}\`). Only register tiles for the active set.`
104
- : `${modeLabel} mode TaskCreates all 8 phases (no phase is skipped).`;
99
+ : `${modeLabel} mode TaskCreates all ${PHASES.length} phases (no phase is skipped).`;
105
100
 
106
101
  const orderingNote = `**All TaskCreate calls in a batch fire in strict phase-number order BEFORE any TaskUpdate is applied.** For ${modeLabel} that means: ${spec.depth ? `Phase 0 at Step -1, then the rest in ascending order at Step 7.5 (${phaseSequence} minus whatever the depth answer drops)` : phaseSequence}. The native widget renders by creation order, not by phase number - out-of-order calls produce visually scrambled tile stacks. Full ordering contract in \`$HOME/.claude/multi-agent-refs/tracker-contract.md\` section "TaskCreate ordering (strict)".`;
107
102
 
@@ -119,7 +114,7 @@ const banner = spec.autopilot
119
114
  // tiles beside the question that decides whether two of them run is the failure this
120
115
  // split exists to remove.
121
116
  const fullSet = spec.phases.filter((p) => p !== "0:Init");
122
- const shortSet = fullSet.filter((p) => Number(p.split(":")[0]) >= 3);
117
+ const shortSet = fullSet.filter((p) => Number(p.split(":")[0]) >= 2);
123
118
  const loopFor = (list) =>
124
119
  `for p in ${list.map((x) => `"${x}"`).join(" ")}; do\n bash $HOME/.claude/scripts/phase-tracker.sh add "\${p%%:*}" "\${p#*:}"\ndone`;
125
120
 
@@ -13,7 +13,7 @@
13
13
  //
14
14
  // Section level is DERIVED, not assumed. These files are not consistent: some
15
15
  // open at `##` and section at `###` (keychain.md), others open at `###` and
16
- // section at `##` (phases/phase-3-dev.md). The rule is the shallowest heading
16
+ // section at `##` (phases/phase-2-dev.md). The rule is the shallowest heading
17
17
  // depth that occurs more than once - a depth used exactly once is a title, not
18
18
  // a section level.
19
19
  //
@@ -1,16 +1,60 @@
1
1
  #!/bin/bash
2
2
  # GitHub SSH Key Oluşturma ve Kurulum Scripti
3
+ #
4
+ # HEADLESS: her soru bir env değişkeniyle önceden cevaplanabilir ve terminal
5
+ # yoksa script SORMAZ. Üç `read -p` koruma olmadan duruyordu; bir launchd
6
+ # ajanının ya da uzak bir kabuğun altında ilki sonsuza kadar bekler ve dışarı
7
+ # hiçbir şey yazmaz, yani kurulum "asılı kaldı" diye görünür. Bir sunucuda
8
+ # çalışması hedeflenen bir aracın sessizce beklemesi, açıkça reddetmesinden
9
+ # kötüdür.
10
+ #
11
+ # MULTI_AGENT_UNATTENDED=1 terminal olsa bile soru sorulmaz
12
+ # SSH_SETUP_EMAIL anahtarın yorum alanına yazılacak e-posta (zorunlu)
13
+ # SSH_SETUP_OVERWRITE e|h - var olan anahtarın üzerine yazılsın mı (varsayılan h)
14
+ # SSH_SETUP_TEST e|h - sonunda github.com'a bağlantı denensin mi (varsayılan h)
3
15
 
4
16
  set -euo pipefail
5
17
 
18
+ # Soruyu sor, ama yalnız soracak birisi varsa. Terminal yoksa env'deki cevabı
19
+ # kullan; o da yoksa boş dön ve kararı çağırana bırak.
20
+ ask() {
21
+ local prompt="$1" preset="$2" __var="$3" reply=""
22
+ if [ -n "$preset" ]; then
23
+ printf '%s%s [env]\n' "$prompt" "$preset"
24
+ printf -v "$__var" '%s' "$preset"
25
+ return 0
26
+ fi
27
+ # "Terminal yok" başsızlığın olağan biçimi, tek biçimi değil: screen,
28
+ # tmux ya da bir sunucudaki login kabuğunun terminali VARDIR ve önünde
29
+ # kimse yoktur. MULTI_AGENT_UNATTENDED=1 operatörün bunu açıkça söylemesi;
30
+ # refs/unattended-contract.md. Tanımsızken hiçbir şey değişmez.
31
+ if [ ! -t 0 ] || [ "${MULTI_AGENT_UNATTENDED:-}" = "1" ]; then
32
+ printf -v "$__var" '%s' ""
33
+ return 0
34
+ fi
35
+ # EOF (Ctrl-D) is an answer, not a crash: without `|| true` `set -e`
36
+ # turns a user pressing Ctrl-D into an exit with no message at all.
37
+ read -r -p "$prompt" reply || true
38
+ printf -v "$__var" '%s' "$reply"
39
+ }
40
+
6
41
  echo "=== GitHub SSH Key Kurulumu ==="
7
42
  echo ""
8
43
 
9
44
  # E-posta adresi al
10
- read -p "GitHub e-posta adresinizi girin: " EMAIL
45
+ ask "GitHub e-posta adresinizi girin: " "${SSH_SETUP_EMAIL:-}" EMAIL
11
46
 
12
47
  if [ -z "$EMAIL" ]; then
13
- echo "Hata: E-posta adresi boş olamaz."
48
+ if [ -t 0 ] && [ "${MULTI_AGENT_UNATTENDED:-}" != "1" ]; then
49
+ echo "Hata: E-posta adresi boş olamaz."
50
+ else
51
+ if [ "${MULTI_AGENT_UNATTENDED:-}" = "1" ]; then
52
+ echo "Hata: MULTI_AGENT_UNATTENDED=1 ve SSH_SETUP_EMAIL tanımlı değil." >&2
53
+ else
54
+ echo "Hata: terminal yok ve SSH_SETUP_EMAIL tanımlı değil." >&2
55
+ fi
56
+ echo " Başsız çalıştırmak için: SSH_SETUP_EMAIL=you@example.com $0" >&2
57
+ fi
14
58
  exit 1
15
59
  fi
16
60
 
@@ -26,7 +70,9 @@ chmod 700 "$HOME/.ssh"
26
70
  if [ -f "$KEY_PATH" ]; then
27
71
  echo ""
28
72
  echo "Uyari: $KEY_PATH zaten mevcut."
29
- read -p "Üzerine yazmak istiyor musunuz? (e/h): " OVERWRITE
73
+ # Varsayılan HAYIR. Başsız bir koşuda cevapsız kalan bir "üzerine yazayım
74
+ # mı" sorusunun güvenli tarafı, var olan anahtarı korumaktır.
75
+ ask "Üzerine yazmak istiyor musunuz? (e/h): " "${SSH_SETUP_OVERWRITE:-}" OVERWRITE
30
76
  if [ "$OVERWRITE" != "e" ]; then
31
77
  echo "İşlem iptal edildi."
32
78
  exit 0
@@ -36,7 +82,11 @@ fi
36
82
  # SSH key oluştur (Ed25519 - modern ve güvenli)
37
83
  echo ""
38
84
  echo "SSH key oluşturuluyor..."
39
- ssh-keygen -t ed25519 -C "$EMAIL" -f "$KEY_PATH" -N ""
85
+ # ssh-keygen var olan bir dosyayı görünce KENDİ "Overwrite (y/n)?" sorusunu
86
+ # sorar - yani yukarıdaki onayı geçtikten sonra başsız koşu ikinci bir
87
+ # soruda asılır. Onay zaten alındı; dosyayı önce kaldır.
88
+ rm -f "$KEY_PATH" "${KEY_PATH}.pub"
89
+ ssh-keygen -t ed25519 -C "$EMAIL" -f "$KEY_PATH" -N "" -q
40
90
 
41
91
  echo ""
42
92
  echo "SSH key başarıyla oluşturuldu!"
@@ -66,7 +116,12 @@ EOF
66
116
  fi
67
117
 
68
118
  # Key'i agent'a ekle (macOS Keychain ile)
69
- ssh-add --apple-use-keychain "$KEY_PATH" 2>/dev/null || ssh-add "$KEY_PATH"
119
+ # Agent yoksa ekleme başarısız olur; anahtar yazıldıktan sonra bunun için
120
+ # çıkmak, kurulumu yarıda bırakıp kullanıcıya hiçbir sonraki adımı
121
+ # göstermemek demek.
122
+ ssh-add --apple-use-keychain "$KEY_PATH" 2>/dev/null \
123
+ || ssh-add "$KEY_PATH" 2>/dev/null \
124
+ || echo "[Uyari: anahtar ssh-agent'a eklenemedi - elle: ssh-add $KEY_PATH]"
70
125
 
71
126
  # Public key'i göster ve kopyala
72
127
  echo ""
@@ -97,11 +152,13 @@ echo "4. 'Add SSH key' butonuna tıklayın"
97
152
  echo ""
98
153
 
99
154
  # GitHub'a key eklendikten sonra test
100
- read -p "Key'i GitHub'a ekledikten sonra test etmek ister misiniz? (e/h): " TEST
155
+ ask "Key'i GitHub'a ekledikten sonra test etmek ister misiniz? (e/h): " "${SSH_SETUP_TEST:-}" TEST
101
156
  if [ "$TEST" = "e" ]; then
102
157
  echo ""
103
158
  echo "GitHub bağlantısı test ediliyor..."
104
- ssh -T git@github.com 2>&1 || true
159
+ # Bilinmeyen host anahtarı üçüncü bir interaktif soru demek; başsız
160
+ # koşuda orada asılırdı.
161
+ ssh -o StrictHostKeyChecking=accept-new -T git@github.com 2>&1 || true
105
162
  fi
106
163
 
107
164
  echo ""
@@ -41,6 +41,8 @@ import { resolve } from "node:path";
41
41
  import { parseFlags } from "./graph-build.mjs";
42
42
  import { loadGraph, defaultGraphPath } from "./graph-query.mjs";
43
43
  import { findByName, affected } from "./graph-affected.mjs";
44
+ import { runMain } from "../lib/fatal.mjs";
45
+ import { invokedDirectly } from "../lib/invoked-directly.mjs";
44
46
 
45
47
  const DEFAULT_MAX_NODES = 25;
46
48
 
@@ -246,6 +248,6 @@ function main() {
246
248
  }
247
249
  }
248
250
 
249
- if (import.meta.url === `file://${process.argv[1]}`) {
250
- main();
251
+ if (invokedDirectly(import.meta.url)) {
252
+ runMain("graph-mermaid", main);
251
253
  }
@@ -3,7 +3,7 @@
3
3
  /**
4
4
  * @file graph-report.mjs - GRAPH_REPORT.md, the human-and-model readable summary.
5
5
  *
6
- * Phase 1 reads this before deciding how wide to explore, and Phase 7 ships it
6
+ * Phase 1 reads this before deciding how wide to explore, and Phase 5 ships it
7
7
  * next to the knowledge base. Sections are ordered by how much they narrow a
8
8
  * search: hubs first (the types everything touches), then the module map, then
9
9
  * the long tail that is usually safe to ignore.
@@ -5,7 +5,7 @@
5
5
  #
6
6
  # Two callers need this and they used to carry their own curl: the issue
7
7
  # generator (`generate-issue.md` step 12) and visual evidence (Phase 3 / Phase 5
8
- # captures rendered into the Phase 7 Jira comment). Two copies of an upload is
8
+ # captures rendered into the Phase 5 Jira comment). Two copies of an upload is
9
9
  # two places for the `X-Atlassian-Token: no-check` header to go missing, which
10
10
  # fails as a 403 that reads like an auth problem.
11
11
  #
@@ -2,55 +2,126 @@
2
2
 
3
3
  set -uo pipefail
4
4
 
5
- # Kullanım: ./keychain-save.sh <service-adı>
6
- # Örnek: ./keychain-save.sh github-pat
7
- # ./keychain-save.sh firebase-sa
5
+ # Kullanım (interaktif): ./keychain-save.sh <service-adı>
6
+ # Örnek: ./keychain-save.sh github-pat
7
+ # ./keychain-save.sh firebase-sa
8
+ #
9
+ # HEADLESS: terminal yokken script SORMAZ. Üç `read` koruma olmadan duruyordu
10
+ # ve bir launchd ajanının altında ilki sonsuza kadar bekler; kurulum "asılı
11
+ # kaldı" diye görünür.
12
+ #
13
+ # MULTI_AGENT_UNATTENDED=1 terminal olsa bile sorulmaz
14
+ # ./keychain-save.sh <ad> --stdin token stdin'den okunur (satır değil,
15
+ # tüm gövde - JSON çok satırlıdır)
16
+ # ./keychain-save.sh <ad> --json <yol> JSON dosyadan okunur
17
+ #
18
+ # Secret İÇİN env değişkeni bilerek YOK. Bir env değeri çocuk süreçlere
19
+ # miras kalır ve bazı sistemlerde `ps e` ile görünür; borudan okumak onu
20
+ # yalnız bu sürecin belleğinde tutar. Aynı sebeple argv'ye de hiç değmez.
8
21
 
9
22
  SERVICE_NAME="${1:-}"
23
+ MODE="${2:-}"
24
+ MODE_ARG="${3:-}"
25
+
26
+ usage() {
27
+ echo "Kullanım: $0 <service-adı> (interaktif)"
28
+ echo " $0 <service-adı> --stdin (token borudan)"
29
+ echo " $0 <service-adı> --json <yol> (JSON dosyadan)"
30
+ }
10
31
 
11
32
  if [ -z "$SERVICE_NAME" ]; then
12
- echo "Kullanım: $0 <service-adı>"
13
- echo "Örnek: $0 github-pat"
33
+ usage
14
34
  exit 1
15
35
  fi
16
36
 
17
- echo "Ne tür bir secret kaydedeceksin?"
18
- echo " 1) Personal Access Token / API Key"
19
- echo " 2) JSON dosyası (service account vb.)"
20
- read -rp "Seçim (1/2): " CHOICE
37
+ # Başsızken mod verilmediyse, soruyu sormak yerine reddet. Sessizce beklemek
38
+ # en kötü seçenek: dışarı hiçbir şey yazmaz ve kimse neyi beklediğini bilmez.
39
+ if [ -z "$MODE" ] && { [ ! -t 0 ] || [ "${MULTI_AGENT_UNATTENDED:-}" = "1" ]; }; then
40
+ # Sebebi doğru söyle. "terminal yok" derken terminalin VAR olması,
41
+ # okuyanı kendi kurulumunu yanlış yerde aramaya gönderir.
42
+ if [ "${MULTI_AGENT_UNATTENDED:-}" = "1" ]; then
43
+ echo "Hata: MULTI_AGENT_UNATTENDED=1 ve mod verilmedi." >&2
44
+ else
45
+ echo "Hata: terminal yok ve mod verilmedi." >&2
46
+ fi
47
+ usage >&2
48
+ exit 1
49
+ fi
50
+
51
+ read_json_file() {
52
+ local path="$1"
53
+ # Kullanıcının girdiği tırnak işaretlerini temizle
54
+ path="${path//\'/}"
55
+ path="${path//\"/}"
56
+ # Tilde (~) expand
57
+ path="${path/#\~/$HOME}"
58
+ if [ ! -f "$path" ]; then
59
+ echo "Hata: Dosya bulunamadı: $path" >&2
60
+ return 1
61
+ fi
62
+ # JSON olduğu gibi saklanır. Kimlik deposu çok satırlı değeri
63
+ # bayt bayt geri verir; base64 sarmalı okuma tarafında çözülmeyen
64
+ # bir katman ekliyordu.
65
+ cat "$path"
66
+ }
21
67
 
22
- case "$CHOICE" in
23
- 1)
24
- read -rsp "Token'ı yapıştır (gizli yazılır): " SECRET
25
- echo ""
68
+ case "$MODE" in
69
+ --stdin)
70
+ # `read` DEĞİL `cat`: `read` ilk satırda durur ve bir service-account
71
+ # JSON'unun geri kalanını sessizce atar.
72
+ SECRET=$(cat)
26
73
  if [ -z "$SECRET" ]; then
27
- echo "Hata: Token boş olamaz."
74
+ echo "Hata: stdin boş." >&2
28
75
  exit 1
29
76
  fi
30
77
  ;;
31
- 2)
32
- read -rp "JSON dosya yolunu gir: " JSON_PATH
33
- # Kullanıcının girdiği tırnak işaretlerini temizle
34
- JSON_PATH="${JSON_PATH//\'/}"
35
- JSON_PATH="${JSON_PATH//\"/}"
36
- # Tilde (~) expand
37
- JSON_PATH="${JSON_PATH/#\~/$HOME}"
38
- if [ ! -f "$JSON_PATH" ]; then
39
- echo "Hata: Dosya bulunamadı: $JSON_PATH"
78
+ --json)
79
+ if [ -z "$MODE_ARG" ]; then
80
+ echo "Hata: --json bir dosya yolu ister." >&2
81
+ usage >&2
40
82
  exit 1
41
83
  fi
42
- # JSON olduğu gibi saklanır. Kimlik deposu çok satırlı değeri
43
- # bayt bayt geri verir; base64 sarmalı okuma tarafında çözülmeyen
44
- # bir katman ekliyordu.
45
- SECRET=$(cat "$JSON_PATH")
84
+ SECRET=$(read_json_file "$MODE_ARG") || exit 1
46
85
  if [ -z "$SECRET" ]; then
47
- echo "Hata: Dosya okunamadı."
86
+ echo "Hata: Dosya okunamadı." >&2
48
87
  exit 1
49
88
  fi
50
- echo "JSON olduğu gibi saklanacak."
89
+ ;;
90
+ "")
91
+ echo "Ne tür bir secret kaydedeceksin?"
92
+ echo " 1) Personal Access Token / API Key"
93
+ echo " 2) JSON dosyası (service account vb.)"
94
+ # EOF (Ctrl-D) bir cevaptır: korumasız `read` onu boş bir seçime
95
+ # çevirip aşağıdaki "Geçersiz seçim"e düşürür, ki doğru sonuç.
96
+ read -rp "Seçim (1/2): " CHOICE || CHOICE=""
97
+
98
+ case "$CHOICE" in
99
+ 1)
100
+ read -rsp "Token'ı yapıştır (gizli yazılır): " SECRET || SECRET=""
101
+ echo ""
102
+ if [ -z "$SECRET" ]; then
103
+ echo "Hata: Token boş olamaz."
104
+ exit 1
105
+ fi
106
+ ;;
107
+ 2)
108
+ read -rp "JSON dosya yolunu gir: " JSON_PATH || JSON_PATH=""
109
+ SECRET=$(read_json_file "$JSON_PATH") || exit 1
110
+ if [ -z "$SECRET" ]; then
111
+ echo "Hata: Dosya okunamadı."
112
+ exit 1
113
+ fi
114
+ echo "JSON olduğu gibi saklanacak."
115
+ ;;
116
+ *)
117
+ echo "Geçersiz seçim."
118
+ exit 1
119
+ ;;
120
+ esac
51
121
  ;;
52
122
  *)
53
- echo "Geçersiz seçim."
123
+ echo "Hata: bilinmeyen mod: $MODE" >&2
124
+ usage >&2
54
125
  exit 1
55
126
  ;;
56
127
  esac
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * WHY THIS EXISTS
6
6
  *
7
- * Phase 7 asks a subagent to read the run log and propose a few memory entries.
7
+ * Phase 5 asks a subagent to read the run log and propose a few memory entries.
8
8
  * That works for what the model noticed, and it is structurally blind to what it
9
9
  * did not: the same wrong path tried in three sessions, the command that fails
10
10
  * every time until its `--flag` variant is used, the directory that never has
@@ -66,6 +66,7 @@ import { execFileSync } from "node:child_process";
66
66
  import { basename, dirname, join } from "node:path";
67
67
  import { homedir, tmpdir } from "node:os";
68
68
  import { fileURLToPath } from "node:url";
69
+ import { runMain } from "../lib/fatal.mjs";
69
70
 
70
71
  const HERE = dirname(fileURLToPath(import.meta.url));
71
72
  const argv = process.argv.slice(2);
@@ -622,4 +623,4 @@ function main() {
622
623
  }
623
624
  }
624
625
 
625
- main();
626
+ runMain("learn-from-transcripts", main);