projectstore-codex 0.0.1 → 0.28.2

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 (184) hide show
  1. package/.codex-plugin/plugin.json +48 -0
  2. package/README.md +15 -7
  3. package/bin/projectstore-codex.mjs +88 -0
  4. package/hooks/hooks.json +59 -0
  5. package/node_modules/projectstore/.claude-plugin/marketplace.json +40 -0
  6. package/node_modules/projectstore/.claude-plugin/plugin.json +23 -0
  7. package/node_modules/projectstore/.mcp.json +14 -0
  8. package/node_modules/projectstore/AGENTS.md +26 -0
  9. package/node_modules/projectstore/LICENSE +21 -0
  10. package/node_modules/projectstore/README.md +284 -0
  11. package/node_modules/projectstore/agents/archaeologist.md +76 -0
  12. package/node_modules/projectstore/agents/clerk.md +93 -0
  13. package/node_modules/projectstore/agents/critic.md +94 -0
  14. package/node_modules/projectstore/agents/librarian.md +81 -0
  15. package/node_modules/projectstore/agents/planner.md +80 -0
  16. package/node_modules/projectstore/agents/reviewer.md +98 -0
  17. package/node_modules/projectstore/bin/projectstore.mjs +7 -0
  18. package/node_modules/projectstore/commands/adr.md +57 -0
  19. package/node_modules/projectstore/commands/agents.md +180 -0
  20. package/node_modules/projectstore/commands/bind.md +128 -0
  21. package/node_modules/projectstore/commands/codemap.md +50 -0
  22. package/node_modules/projectstore/commands/concept.md +17 -0
  23. package/node_modules/projectstore/commands/doctor.md +166 -0
  24. package/node_modules/projectstore/commands/epic.md +40 -0
  25. package/node_modules/projectstore/commands/graph.md +56 -0
  26. package/node_modules/projectstore/commands/kanban.md +40 -0
  27. package/node_modules/projectstore/commands/meeting.md +17 -0
  28. package/node_modules/projectstore/commands/reconcile.md +73 -0
  29. package/node_modules/projectstore/commands/research.md +17 -0
  30. package/node_modules/projectstore/commands/review.md +89 -0
  31. package/node_modules/projectstore/commands/runbook.md +17 -0
  32. package/node_modules/projectstore/commands/scaffold.md +23 -0
  33. package/node_modules/projectstore/commands/search.md +22 -0
  34. package/node_modules/projectstore/commands/spec.md +91 -0
  35. package/node_modules/projectstore/commands/status.md +27 -0
  36. package/node_modules/projectstore/commands/statusline.md +46 -0
  37. package/node_modules/projectstore/commands/story.md +113 -0
  38. package/node_modules/projectstore/docs/extending.md +172 -0
  39. package/node_modules/projectstore/docs/getting-started.md +133 -0
  40. package/node_modules/projectstore/docs/harnesses.md +176 -0
  41. package/node_modules/projectstore/docs/how-it-works.md +263 -0
  42. package/node_modules/projectstore/docs/images/loop-light.svg +94 -0
  43. package/node_modules/projectstore/docs/images/loop.svg +93 -0
  44. package/node_modules/projectstore/docs/images/statusline-hud.png +0 -0
  45. package/node_modules/projectstore/docs/images/team-light.svg +79 -0
  46. package/node_modules/projectstore/docs/images/team.svg +79 -0
  47. package/node_modules/projectstore/harnesses/claude-code.json +483 -0
  48. package/node_modules/projectstore/harnesses/codex.json +332 -0
  49. package/node_modules/projectstore/hooks/hooks.json +59 -0
  50. package/node_modules/projectstore/hooks/pre-compact.mjs +121 -0
  51. package/node_modules/projectstore/hooks/session-rules.mjs +63 -0
  52. package/node_modules/projectstore/hooks/session-start.mjs +301 -0
  53. package/node_modules/projectstore/hooks/session-stop.mjs +84 -0
  54. package/node_modules/projectstore/package.json +70 -0
  55. package/node_modules/projectstore/scaffold/checklists.json +88 -0
  56. package/node_modules/projectstore/scaffold/headings.json +171 -0
  57. package/node_modules/projectstore/scaffold/layouts/engineering.json +85 -0
  58. package/node_modules/projectstore/scripts/binding.mjs +165 -0
  59. package/node_modules/projectstore/scripts/build-adapters.mjs +264 -0
  60. package/node_modules/projectstore/scripts/cli.mjs +595 -0
  61. package/node_modules/projectstore/scripts/codemap.mjs +99 -0
  62. package/node_modules/projectstore/scripts/diff-refs.mjs +127 -0
  63. package/node_modules/projectstore/scripts/doctor.mjs +2127 -0
  64. package/node_modules/projectstore/scripts/draft.mjs +261 -0
  65. package/node_modules/projectstore/scripts/graph.mjs +219 -0
  66. package/node_modules/projectstore/scripts/harness.mjs +608 -0
  67. package/node_modules/projectstore/scripts/install-harness.mjs +1387 -0
  68. package/node_modules/projectstore/scripts/kanban.mjs +174 -0
  69. package/node_modules/projectstore/scripts/lib.mjs +3085 -0
  70. package/node_modules/projectstore/scripts/mcp.mjs +391 -0
  71. package/node_modules/projectstore/scripts/portable-registration.mjs +198 -0
  72. package/node_modules/projectstore/scripts/provenance.mjs +375 -0
  73. package/node_modules/projectstore/scripts/query.mjs +490 -0
  74. package/node_modules/projectstore/scripts/reconcile.mjs +422 -0
  75. package/node_modules/projectstore/scripts/statusline-launcher.mjs +141 -0
  76. package/node_modules/projectstore/scripts/statusline.mjs +253 -0
  77. package/node_modules/projectstore/scripts/story-section.mjs +209 -0
  78. package/node_modules/projectstore/scripts/surfaces.mjs +421 -0
  79. package/node_modules/projectstore/scripts/tokens.mjs +449 -0
  80. package/node_modules/projectstore/scripts/touch-session.mjs +336 -0
  81. package/node_modules/projectstore/scripts/version-guard.mjs +261 -0
  82. package/node_modules/projectstore/scripts/worktree.mjs +109 -0
  83. package/node_modules/projectstore/skills/projectstore-decision-detector/SKILL.md +40 -0
  84. package/node_modules/projectstore/skills/projectstore-peer-reviewer/SKILL.md +38 -0
  85. package/node_modules/projectstore/skills/projectstore-story-completion/SKILL.md +50 -0
  86. package/node_modules/projectstore/skills/projectstore-vault-communication/SKILL.md +96 -0
  87. package/node_modules/projectstore/templates/claude-md-block.md.tmpl +26 -0
  88. package/node_modules/projectstore/templates/de/adr.md.tmpl +67 -0
  89. package/node_modules/projectstore/templates/de/concept.md.tmpl +43 -0
  90. package/node_modules/projectstore/templates/de/epic.md.tmpl +59 -0
  91. package/node_modules/projectstore/templates/de/folder-readme.md.tmpl +14 -0
  92. package/node_modules/projectstore/templates/de/kanban.md.tmpl +36 -0
  93. package/node_modules/projectstore/templates/de/meeting.md.tmpl +38 -0
  94. package/node_modules/projectstore/templates/de/research.md.tmpl +47 -0
  95. package/node_modules/projectstore/templates/de/runbook.md.tmpl +53 -0
  96. package/node_modules/projectstore/templates/de/spec.md.tmpl +64 -0
  97. package/node_modules/projectstore/templates/de/story.md.tmpl +76 -0
  98. package/node_modules/projectstore/templates/de/strings.json +6 -0
  99. package/node_modules/projectstore/templates/en/adr.md.tmpl +67 -0
  100. package/node_modules/projectstore/templates/en/concept.md.tmpl +43 -0
  101. package/node_modules/projectstore/templates/en/epic.md.tmpl +59 -0
  102. package/node_modules/projectstore/templates/en/folder-readme.md.tmpl +14 -0
  103. package/node_modules/projectstore/templates/en/kanban.md.tmpl +36 -0
  104. package/node_modules/projectstore/templates/en/meeting.md.tmpl +38 -0
  105. package/node_modules/projectstore/templates/en/research.md.tmpl +47 -0
  106. package/node_modules/projectstore/templates/en/runbook.md.tmpl +53 -0
  107. package/node_modules/projectstore/templates/en/spec.md.tmpl +64 -0
  108. package/node_modules/projectstore/templates/en/story.md.tmpl +76 -0
  109. package/node_modules/projectstore/templates/en/strings.json +6 -0
  110. package/node_modules/projectstore/templates/es/adr.md.tmpl +67 -0
  111. package/node_modules/projectstore/templates/es/concept.md.tmpl +43 -0
  112. package/node_modules/projectstore/templates/es/epic.md.tmpl +59 -0
  113. package/node_modules/projectstore/templates/es/folder-readme.md.tmpl +14 -0
  114. package/node_modules/projectstore/templates/es/kanban.md.tmpl +36 -0
  115. package/node_modules/projectstore/templates/es/meeting.md.tmpl +38 -0
  116. package/node_modules/projectstore/templates/es/research.md.tmpl +47 -0
  117. package/node_modules/projectstore/templates/es/runbook.md.tmpl +53 -0
  118. package/node_modules/projectstore/templates/es/spec.md.tmpl +64 -0
  119. package/node_modules/projectstore/templates/es/story.md.tmpl +76 -0
  120. package/node_modules/projectstore/templates/es/strings.json +6 -0
  121. package/node_modules/projectstore/templates/fr/adr.md.tmpl +67 -0
  122. package/node_modules/projectstore/templates/fr/concept.md.tmpl +43 -0
  123. package/node_modules/projectstore/templates/fr/epic.md.tmpl +59 -0
  124. package/node_modules/projectstore/templates/fr/folder-readme.md.tmpl +14 -0
  125. package/node_modules/projectstore/templates/fr/kanban.md.tmpl +36 -0
  126. package/node_modules/projectstore/templates/fr/meeting.md.tmpl +38 -0
  127. package/node_modules/projectstore/templates/fr/research.md.tmpl +47 -0
  128. package/node_modules/projectstore/templates/fr/runbook.md.tmpl +53 -0
  129. package/node_modules/projectstore/templates/fr/spec.md.tmpl +64 -0
  130. package/node_modules/projectstore/templates/fr/story.md.tmpl +76 -0
  131. package/node_modules/projectstore/templates/fr/strings.json +6 -0
  132. package/node_modules/projectstore/templates/ru/adr.md.tmpl +67 -0
  133. package/node_modules/projectstore/templates/ru/concept.md.tmpl +43 -0
  134. package/node_modules/projectstore/templates/ru/epic.md.tmpl +59 -0
  135. package/node_modules/projectstore/templates/ru/folder-readme.md.tmpl +14 -0
  136. package/node_modules/projectstore/templates/ru/kanban.md.tmpl +36 -0
  137. package/node_modules/projectstore/templates/ru/meeting.md.tmpl +38 -0
  138. package/node_modules/projectstore/templates/ru/research.md.tmpl +47 -0
  139. package/node_modules/projectstore/templates/ru/runbook.md.tmpl +53 -0
  140. package/node_modules/projectstore/templates/ru/spec.md.tmpl +64 -0
  141. package/node_modules/projectstore/templates/ru/story.md.tmpl +76 -0
  142. package/node_modules/projectstore/templates/ru/strings.json +6 -0
  143. package/node_modules/projectstore/templates/zh/adr.md.tmpl +67 -0
  144. package/node_modules/projectstore/templates/zh/concept.md.tmpl +43 -0
  145. package/node_modules/projectstore/templates/zh/epic.md.tmpl +59 -0
  146. package/node_modules/projectstore/templates/zh/folder-readme.md.tmpl +14 -0
  147. package/node_modules/projectstore/templates/zh/kanban.md.tmpl +36 -0
  148. package/node_modules/projectstore/templates/zh/meeting.md.tmpl +38 -0
  149. package/node_modules/projectstore/templates/zh/research.md.tmpl +47 -0
  150. package/node_modules/projectstore/templates/zh/runbook.md.tmpl +53 -0
  151. package/node_modules/projectstore/templates/zh/spec.md.tmpl +64 -0
  152. package/node_modules/projectstore/templates/zh/story.md.tmpl +76 -0
  153. package/node_modules/projectstore/templates/zh/strings.json +6 -0
  154. package/package.json +35 -14
  155. package/skills/projectstore-adr/SKILL.md +76 -0
  156. package/skills/projectstore-agents/SKILL.md +50 -0
  157. package/skills/projectstore-archaeologist/SKILL.md +109 -0
  158. package/skills/projectstore-bind/SKILL.md +44 -0
  159. package/skills/projectstore-clerk/SKILL.md +126 -0
  160. package/skills/projectstore-codemap/SKILL.md +69 -0
  161. package/skills/projectstore-concept/SKILL.md +36 -0
  162. package/skills/projectstore-critic/SKILL.md +127 -0
  163. package/skills/projectstore-decision-detector/SKILL.md +59 -0
  164. package/skills/projectstore-doctor/SKILL.md +33 -0
  165. package/skills/projectstore-epic/SKILL.md +59 -0
  166. package/skills/projectstore-graph/SKILL.md +75 -0
  167. package/skills/projectstore-kanban/SKILL.md +60 -0
  168. package/skills/projectstore-librarian/SKILL.md +114 -0
  169. package/skills/projectstore-meeting/SKILL.md +36 -0
  170. package/skills/projectstore-peer-reviewer/SKILL.md +57 -0
  171. package/skills/projectstore-planner/SKILL.md +113 -0
  172. package/skills/projectstore-reconcile/SKILL.md +92 -0
  173. package/skills/projectstore-research/SKILL.md +36 -0
  174. package/skills/projectstore-review/SKILL.md +108 -0
  175. package/skills/projectstore-reviewer/SKILL.md +131 -0
  176. package/skills/projectstore-runbook/SKILL.md +36 -0
  177. package/skills/projectstore-scaffold/SKILL.md +42 -0
  178. package/skills/projectstore-search/SKILL.md +41 -0
  179. package/skills/projectstore-spec/SKILL.md +110 -0
  180. package/skills/projectstore-status/SKILL.md +47 -0
  181. package/skills/projectstore-statusline/SKILL.md +29 -0
  182. package/skills/projectstore-story/SKILL.md +132 -0
  183. package/skills/projectstore-story-completion/SKILL.md +69 -0
  184. package/skills/projectstore-vault-communication/SKILL.md +115 -0
@@ -0,0 +1,174 @@
1
+ #!/usr/bin/env node
2
+ // projectstore — kanban.mjs
3
+ // Regenerates kanban.md by scanning every story under epics/<id>/stories/ —
4
+ // both flat files and story folders (see listStoryFiles) — reading their
5
+ // frontmatter (status, priority, title, epic) and rendering into the kanban
6
+ // template. Source of truth = story frontmatter.
7
+ //
8
+ // Output: JSON { path, content, stats } — compute only. The applier is
9
+ // reconcile.mjs --write (atomic replace, recompute-at-write), not the
10
+ // harness: no Write-tool step remains in the derived-view flows.
11
+
12
+ import { readdirSync, readFileSync, existsSync } from "node:fs";
13
+ import { join } from "node:path";
14
+ import {
15
+ readConfig,
16
+ loadLayout,
17
+ loadTemplate,
18
+ renderTemplate,
19
+ parseFrontmatter,
20
+ nowIso,
21
+ listEpicStories,
22
+ slugIdentity,
23
+ displayNumberOf,
24
+ compareArtifactOrder, isMain
25
+ } from "./lib.mjs";
26
+
27
+ function die(msg) {
28
+ process.stderr.write(`projectstore/kanban: ${msg}\n`);
29
+ process.exit(1);
30
+ }
31
+
32
+ // Statuses that describe work which is not on the board by definition: it was
33
+ // replaced, postponed, or set aside. Putting them in a column would claim the
34
+ // work is queued, which is the opposite of what the status says.
35
+ const NOT_ACTIONABLE = new Set(["superseded", "deferred", "parked"]);
36
+
37
+ export function findStories(vault, epicsPath) {
38
+ const root = join(vault, epicsPath);
39
+ const stories = [];
40
+ const skipped = { no_status: [], not_actionable: [] };
41
+ if (!existsSync(root)) return { stories, skipped };
42
+ // Epics iterate in sorted order and each epic's stories are ordered by
43
+ // created date (number, then slug, as tiebreak — SPEC-002 contract 8), so
44
+ // the board keeps its per-epic grouping and regenerates deterministically.
45
+ for (const epicId of readdirSync(root).sort()) {
46
+ // `_templates` and friends hold blanks, not work.
47
+ if (epicId.startsWith("_") || epicId.startsWith(".")) continue;
48
+ const epicStories = [];
49
+ for (const story of listEpicStories(join(root, epicId))) {
50
+ const md = readFileSync(story.abs, "utf8");
51
+ const { data } = parseFrontmatter(md);
52
+ const relPath = `${epicsPath}/${epicId}/${story.rel}`;
53
+
54
+ // A story with no status has no column. Defaulting it to "planned" would
55
+ // invent a claim about work nobody made — legacy stories written before
56
+ // frontmatter existed would show up as queued. They return to the board
57
+ // the moment they get a status.
58
+ if (!data.status) {
59
+ skipped.no_status.push(relPath);
60
+ continue;
61
+ }
62
+ const status = String(data.status).toLowerCase();
63
+ if (NOT_ACTIONABLE.has(status)) {
64
+ skipped.not_actionable.push(relPath);
65
+ continue;
66
+ }
67
+
68
+ // The card is labelled by the epic the story claims in its frontmatter,
69
+ // falling back to the folder. Stories get re-filed under a new tracker key
70
+ // without moving on disk, and a standalone story writes `epic: null` —
71
+ // in both cases the folder name is the better answer only when frontmatter
72
+ // has nothing to say.
73
+ const claimed = data.epic == null ? "" : String(data.epic).trim();
74
+ const epicLabel = claimed && claimed !== "null" ? claimed : epicId;
75
+
76
+ epicStories.push({
77
+ path: story.abs,
78
+ relPath,
79
+ epicId: epicLabel,
80
+ status,
81
+ priority: data.priority || "p2",
82
+ title: data.title || story.slug,
83
+ id: data.id || story.slug,
84
+ date: String(data.created || data.date || ""),
85
+ number: displayNumberOf(data, story.slug, { story: true }),
86
+ slug: slugIdentity(story.slug, { story: true }).primary,
87
+ });
88
+ }
89
+ stories.push(...epicStories.sort(compareArtifactOrder));
90
+ }
91
+ return { stories, skipped };
92
+ }
93
+
94
+ export function statusToColumn(status) {
95
+ const m = {
96
+ planned: "Backlog",
97
+ todo: "ToDo",
98
+ "to-do": "ToDo",
99
+ "in-progress": "In Progress",
100
+ in_progress: "In Progress",
101
+ "in progress": "In Progress",
102
+ review: "Review",
103
+ done: "Done",
104
+ closed: "Done",
105
+ };
106
+ return m[status] || "Backlog";
107
+ }
108
+
109
+ function renderItem(story) {
110
+ const tags = [`#${story.priority}`];
111
+ if (story.status === "done") tags.push("#done");
112
+ if (story.status === "review") tags.push("#review");
113
+ const wikilink = `[[${story.relPath.replace(/\.md$/, "")}|${story.epicId}: ${story.title}]]`;
114
+ const check = story.status === "done" ? "[x]" : "[ ]";
115
+ return `- ${check} ${wikilink} ${tags.join(" ")}`;
116
+ }
117
+
118
+ function main() {
119
+ const cfg = readConfig();
120
+ if (!cfg) die("No projectstore config. Run /projectstore:bind first.");
121
+ const layout = loadLayout(cfg.layout);
122
+ if (!layout.kanban) die(`Layout ${cfg.layout} does not declare a kanban config.`);
123
+
124
+ const epicsFolder = layout.folders.find((f) => f.kind === "epic");
125
+ if (!epicsFolder) die("No epic folder in layout — kanban needs epics.");
126
+
127
+ const { stories, skipped } = findStories(cfg.vault_path, epicsFolder.path);
128
+
129
+ const columns = {};
130
+ for (const col of layout.kanban.columns) columns[col] = [];
131
+ for (const s of stories) {
132
+ const col = statusToColumn(s.status);
133
+ if (!columns[col]) columns[col] = [];
134
+ columns[col].push(renderItem(s));
135
+ }
136
+
137
+ const tpl = loadTemplate(cfg.language || "en", "kanban");
138
+ const vars = {
139
+ // Full ISO, not date-only (spec contract 6). The template var is named
140
+ // generated_at — renderTemplate substitutes "" for unknown vars, so the
141
+ // var rename here and in BOTH kanban templates must land together.
142
+ generated_at: nowIso(),
143
+ backlog_items: (columns["Backlog"] || []).join("\n") || "",
144
+ todo_items: (columns["ToDo"] || []).join("\n") || "",
145
+ in_progress_items: (columns["In Progress"] || []).join("\n") || "",
146
+ review_items: (columns["Review"] || []).join("\n") || "",
147
+ done_items: (columns["Done"] || []).join("\n") || "",
148
+ };
149
+
150
+ const out = {
151
+ path: join(cfg.vault_path, layout.kanban.file || "kanban.md"),
152
+ content: renderTemplate(tpl, vars),
153
+ stats: {
154
+ total: stories.length,
155
+ by_column: Object.fromEntries(Object.entries(columns).map(([k, v]) => [k, v.length])),
156
+ // Reported, not hidden: a story missing from the board must be explainable
157
+ // without reading the generator.
158
+ skipped: {
159
+ no_status: skipped.no_status.length,
160
+ not_actionable: skipped.not_actionable.length,
161
+ files: { no_status: skipped.no_status, not_actionable: skipped.not_actionable },
162
+ },
163
+ },
164
+ };
165
+
166
+ process.stdout.write(JSON.stringify(out, null, 2) + "\n");
167
+ }
168
+
169
+ // A module now (the query verbs import findStories); the generator runs only
170
+ // as the entry file — importing it must never print to stdout, which is the
171
+ // MCP server's protocol channel.
172
+ if (isMain(import.meta.url)) {
173
+ main();
174
+ }