projectstore-codex 0.0.1 → 0.28.1
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.
- package/.codex-plugin/plugin.json +48 -0
- package/README.md +15 -7
- package/bin/projectstore-codex.mjs +88 -0
- package/hooks/hooks.json +59 -0
- package/node_modules/projectstore/.claude-plugin/marketplace.json +40 -0
- package/node_modules/projectstore/.claude-plugin/plugin.json +23 -0
- package/node_modules/projectstore/.mcp.json +14 -0
- package/node_modules/projectstore/AGENTS.md +26 -0
- package/node_modules/projectstore/LICENSE +21 -0
- package/node_modules/projectstore/README.md +284 -0
- package/node_modules/projectstore/agents/archaeologist.md +76 -0
- package/node_modules/projectstore/agents/clerk.md +93 -0
- package/node_modules/projectstore/agents/critic.md +94 -0
- package/node_modules/projectstore/agents/librarian.md +81 -0
- package/node_modules/projectstore/agents/planner.md +80 -0
- package/node_modules/projectstore/agents/reviewer.md +98 -0
- package/node_modules/projectstore/bin/projectstore.mjs +7 -0
- package/node_modules/projectstore/commands/adr.md +57 -0
- package/node_modules/projectstore/commands/agents.md +180 -0
- package/node_modules/projectstore/commands/bind.md +128 -0
- package/node_modules/projectstore/commands/codemap.md +50 -0
- package/node_modules/projectstore/commands/concept.md +17 -0
- package/node_modules/projectstore/commands/doctor.md +166 -0
- package/node_modules/projectstore/commands/epic.md +40 -0
- package/node_modules/projectstore/commands/graph.md +56 -0
- package/node_modules/projectstore/commands/kanban.md +40 -0
- package/node_modules/projectstore/commands/meeting.md +17 -0
- package/node_modules/projectstore/commands/reconcile.md +73 -0
- package/node_modules/projectstore/commands/research.md +17 -0
- package/node_modules/projectstore/commands/review.md +89 -0
- package/node_modules/projectstore/commands/runbook.md +17 -0
- package/node_modules/projectstore/commands/scaffold.md +23 -0
- package/node_modules/projectstore/commands/search.md +22 -0
- package/node_modules/projectstore/commands/spec.md +91 -0
- package/node_modules/projectstore/commands/status.md +27 -0
- package/node_modules/projectstore/commands/statusline.md +46 -0
- package/node_modules/projectstore/commands/story.md +113 -0
- package/node_modules/projectstore/docs/extending.md +172 -0
- package/node_modules/projectstore/docs/getting-started.md +133 -0
- package/node_modules/projectstore/docs/harnesses.md +163 -0
- package/node_modules/projectstore/docs/how-it-works.md +263 -0
- package/node_modules/projectstore/docs/images/loop-light.svg +94 -0
- package/node_modules/projectstore/docs/images/loop.svg +93 -0
- package/node_modules/projectstore/docs/images/statusline-hud.png +0 -0
- package/node_modules/projectstore/docs/images/team-light.svg +79 -0
- package/node_modules/projectstore/docs/images/team.svg +79 -0
- package/node_modules/projectstore/harnesses/claude-code.json +483 -0
- package/node_modules/projectstore/harnesses/codex.json +332 -0
- package/node_modules/projectstore/hooks/hooks.json +59 -0
- package/node_modules/projectstore/hooks/pre-compact.mjs +121 -0
- package/node_modules/projectstore/hooks/session-rules.mjs +63 -0
- package/node_modules/projectstore/hooks/session-start.mjs +301 -0
- package/node_modules/projectstore/hooks/session-stop.mjs +84 -0
- package/node_modules/projectstore/package.json +70 -0
- package/node_modules/projectstore/scaffold/checklists.json +88 -0
- package/node_modules/projectstore/scaffold/headings.json +171 -0
- package/node_modules/projectstore/scaffold/layouts/engineering.json +85 -0
- package/node_modules/projectstore/scripts/binding.mjs +165 -0
- package/node_modules/projectstore/scripts/build-adapters.mjs +264 -0
- package/node_modules/projectstore/scripts/cli.mjs +595 -0
- package/node_modules/projectstore/scripts/codemap.mjs +99 -0
- package/node_modules/projectstore/scripts/diff-refs.mjs +127 -0
- package/node_modules/projectstore/scripts/doctor.mjs +2127 -0
- package/node_modules/projectstore/scripts/draft.mjs +261 -0
- package/node_modules/projectstore/scripts/graph.mjs +219 -0
- package/node_modules/projectstore/scripts/harness.mjs +608 -0
- package/node_modules/projectstore/scripts/install-harness.mjs +1387 -0
- package/node_modules/projectstore/scripts/kanban.mjs +174 -0
- package/node_modules/projectstore/scripts/lib.mjs +3085 -0
- package/node_modules/projectstore/scripts/mcp.mjs +391 -0
- package/node_modules/projectstore/scripts/portable-registration.mjs +198 -0
- package/node_modules/projectstore/scripts/provenance.mjs +375 -0
- package/node_modules/projectstore/scripts/query.mjs +490 -0
- package/node_modules/projectstore/scripts/reconcile.mjs +422 -0
- package/node_modules/projectstore/scripts/statusline-launcher.mjs +141 -0
- package/node_modules/projectstore/scripts/statusline.mjs +253 -0
- package/node_modules/projectstore/scripts/story-section.mjs +209 -0
- package/node_modules/projectstore/scripts/surfaces.mjs +421 -0
- package/node_modules/projectstore/scripts/tokens.mjs +449 -0
- package/node_modules/projectstore/scripts/touch-session.mjs +336 -0
- package/node_modules/projectstore/scripts/version-guard.mjs +255 -0
- package/node_modules/projectstore/scripts/worktree.mjs +109 -0
- package/node_modules/projectstore/skills/projectstore-decision-detector/SKILL.md +40 -0
- package/node_modules/projectstore/skills/projectstore-peer-reviewer/SKILL.md +38 -0
- package/node_modules/projectstore/skills/projectstore-story-completion/SKILL.md +50 -0
- package/node_modules/projectstore/skills/projectstore-vault-communication/SKILL.md +96 -0
- package/node_modules/projectstore/templates/claude-md-block.md.tmpl +26 -0
- package/node_modules/projectstore/templates/de/adr.md.tmpl +67 -0
- package/node_modules/projectstore/templates/de/concept.md.tmpl +43 -0
- package/node_modules/projectstore/templates/de/epic.md.tmpl +59 -0
- package/node_modules/projectstore/templates/de/folder-readme.md.tmpl +14 -0
- package/node_modules/projectstore/templates/de/kanban.md.tmpl +36 -0
- package/node_modules/projectstore/templates/de/meeting.md.tmpl +38 -0
- package/node_modules/projectstore/templates/de/research.md.tmpl +47 -0
- package/node_modules/projectstore/templates/de/runbook.md.tmpl +53 -0
- package/node_modules/projectstore/templates/de/spec.md.tmpl +64 -0
- package/node_modules/projectstore/templates/de/story.md.tmpl +76 -0
- package/node_modules/projectstore/templates/de/strings.json +6 -0
- package/node_modules/projectstore/templates/en/adr.md.tmpl +67 -0
- package/node_modules/projectstore/templates/en/concept.md.tmpl +43 -0
- package/node_modules/projectstore/templates/en/epic.md.tmpl +59 -0
- package/node_modules/projectstore/templates/en/folder-readme.md.tmpl +14 -0
- package/node_modules/projectstore/templates/en/kanban.md.tmpl +36 -0
- package/node_modules/projectstore/templates/en/meeting.md.tmpl +38 -0
- package/node_modules/projectstore/templates/en/research.md.tmpl +47 -0
- package/node_modules/projectstore/templates/en/runbook.md.tmpl +53 -0
- package/node_modules/projectstore/templates/en/spec.md.tmpl +64 -0
- package/node_modules/projectstore/templates/en/story.md.tmpl +76 -0
- package/node_modules/projectstore/templates/en/strings.json +6 -0
- package/node_modules/projectstore/templates/es/adr.md.tmpl +67 -0
- package/node_modules/projectstore/templates/es/concept.md.tmpl +43 -0
- package/node_modules/projectstore/templates/es/epic.md.tmpl +59 -0
- package/node_modules/projectstore/templates/es/folder-readme.md.tmpl +14 -0
- package/node_modules/projectstore/templates/es/kanban.md.tmpl +36 -0
- package/node_modules/projectstore/templates/es/meeting.md.tmpl +38 -0
- package/node_modules/projectstore/templates/es/research.md.tmpl +47 -0
- package/node_modules/projectstore/templates/es/runbook.md.tmpl +53 -0
- package/node_modules/projectstore/templates/es/spec.md.tmpl +64 -0
- package/node_modules/projectstore/templates/es/story.md.tmpl +76 -0
- package/node_modules/projectstore/templates/es/strings.json +6 -0
- package/node_modules/projectstore/templates/fr/adr.md.tmpl +67 -0
- package/node_modules/projectstore/templates/fr/concept.md.tmpl +43 -0
- package/node_modules/projectstore/templates/fr/epic.md.tmpl +59 -0
- package/node_modules/projectstore/templates/fr/folder-readme.md.tmpl +14 -0
- package/node_modules/projectstore/templates/fr/kanban.md.tmpl +36 -0
- package/node_modules/projectstore/templates/fr/meeting.md.tmpl +38 -0
- package/node_modules/projectstore/templates/fr/research.md.tmpl +47 -0
- package/node_modules/projectstore/templates/fr/runbook.md.tmpl +53 -0
- package/node_modules/projectstore/templates/fr/spec.md.tmpl +64 -0
- package/node_modules/projectstore/templates/fr/story.md.tmpl +76 -0
- package/node_modules/projectstore/templates/fr/strings.json +6 -0
- package/node_modules/projectstore/templates/ru/adr.md.tmpl +67 -0
- package/node_modules/projectstore/templates/ru/concept.md.tmpl +43 -0
- package/node_modules/projectstore/templates/ru/epic.md.tmpl +59 -0
- package/node_modules/projectstore/templates/ru/folder-readme.md.tmpl +14 -0
- package/node_modules/projectstore/templates/ru/kanban.md.tmpl +36 -0
- package/node_modules/projectstore/templates/ru/meeting.md.tmpl +38 -0
- package/node_modules/projectstore/templates/ru/research.md.tmpl +47 -0
- package/node_modules/projectstore/templates/ru/runbook.md.tmpl +53 -0
- package/node_modules/projectstore/templates/ru/spec.md.tmpl +64 -0
- package/node_modules/projectstore/templates/ru/story.md.tmpl +76 -0
- package/node_modules/projectstore/templates/ru/strings.json +6 -0
- package/node_modules/projectstore/templates/zh/adr.md.tmpl +67 -0
- package/node_modules/projectstore/templates/zh/concept.md.tmpl +43 -0
- package/node_modules/projectstore/templates/zh/epic.md.tmpl +59 -0
- package/node_modules/projectstore/templates/zh/folder-readme.md.tmpl +14 -0
- package/node_modules/projectstore/templates/zh/kanban.md.tmpl +36 -0
- package/node_modules/projectstore/templates/zh/meeting.md.tmpl +38 -0
- package/node_modules/projectstore/templates/zh/research.md.tmpl +47 -0
- package/node_modules/projectstore/templates/zh/runbook.md.tmpl +53 -0
- package/node_modules/projectstore/templates/zh/spec.md.tmpl +64 -0
- package/node_modules/projectstore/templates/zh/story.md.tmpl +76 -0
- package/node_modules/projectstore/templates/zh/strings.json +6 -0
- package/package.json +36 -14
- package/plugin.json +53 -0
- package/skills/projectstore-adr/SKILL.md +76 -0
- package/skills/projectstore-agents/SKILL.md +50 -0
- package/skills/projectstore-archaeologist/SKILL.md +109 -0
- package/skills/projectstore-bind/SKILL.md +44 -0
- package/skills/projectstore-clerk/SKILL.md +126 -0
- package/skills/projectstore-codemap/SKILL.md +69 -0
- package/skills/projectstore-concept/SKILL.md +36 -0
- package/skills/projectstore-critic/SKILL.md +127 -0
- package/skills/projectstore-decision-detector/SKILL.md +59 -0
- package/skills/projectstore-doctor/SKILL.md +33 -0
- package/skills/projectstore-epic/SKILL.md +59 -0
- package/skills/projectstore-graph/SKILL.md +75 -0
- package/skills/projectstore-kanban/SKILL.md +60 -0
- package/skills/projectstore-librarian/SKILL.md +114 -0
- package/skills/projectstore-meeting/SKILL.md +36 -0
- package/skills/projectstore-peer-reviewer/SKILL.md +57 -0
- package/skills/projectstore-planner/SKILL.md +113 -0
- package/skills/projectstore-reconcile/SKILL.md +92 -0
- package/skills/projectstore-research/SKILL.md +36 -0
- package/skills/projectstore-review/SKILL.md +108 -0
- package/skills/projectstore-reviewer/SKILL.md +131 -0
- package/skills/projectstore-runbook/SKILL.md +36 -0
- package/skills/projectstore-scaffold/SKILL.md +42 -0
- package/skills/projectstore-search/SKILL.md +41 -0
- package/skills/projectstore-spec/SKILL.md +110 -0
- package/skills/projectstore-status/SKILL.md +47 -0
- package/skills/projectstore-statusline/SKILL.md +29 -0
- package/skills/projectstore-story/SKILL.md +132 -0
- package/skills/projectstore-story-completion/SKILL.md +69 -0
- 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
|
+
}
|