@chiralkit/cli 0.1.0-alpha.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 (198) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +97 -0
  3. package/dist/add.d.ts +4 -0
  4. package/dist/add.js +118 -0
  5. package/dist/add.js.map +1 -0
  6. package/dist/agents/subprocess.d.ts +10 -0
  7. package/dist/agents/subprocess.js +43 -0
  8. package/dist/agents/subprocess.js.map +1 -0
  9. package/dist/automation/index.d.ts +14 -0
  10. package/dist/automation/index.js +129 -0
  11. package/dist/automation/index.js.map +1 -0
  12. package/dist/automation/install.d.ts +19 -0
  13. package/dist/automation/install.js +116 -0
  14. package/dist/automation/install.js.map +1 -0
  15. package/dist/automation/parsers/audit-report.d.ts +2 -0
  16. package/dist/automation/parsers/audit-report.js +42 -0
  17. package/dist/automation/parsers/audit-report.js.map +1 -0
  18. package/dist/automation/parsers/exit-code.d.ts +2 -0
  19. package/dist/automation/parsers/exit-code.js +6 -0
  20. package/dist/automation/parsers/exit-code.js.map +1 -0
  21. package/dist/automation/parsers/index.d.ts +10 -0
  22. package/dist/automation/parsers/index.js +13 -0
  23. package/dist/automation/parsers/index.js.map +1 -0
  24. package/dist/automation/parsers/observer-snapshot.d.ts +2 -0
  25. package/dist/automation/parsers/observer-snapshot.js +30 -0
  26. package/dist/automation/parsers/observer-snapshot.js.map +1 -0
  27. package/dist/automation/parsers/plan-report.d.ts +2 -0
  28. package/dist/automation/parsers/plan-report.js +53 -0
  29. package/dist/automation/parsers/plan-report.js.map +1 -0
  30. package/dist/automation/parsers/refinement-report.d.ts +2 -0
  31. package/dist/automation/parsers/refinement-report.js +149 -0
  32. package/dist/automation/parsers/refinement-report.js.map +1 -0
  33. package/dist/automation/parsers/types.d.ts +7 -0
  34. package/dist/automation/parsers/types.js +2 -0
  35. package/dist/automation/parsers/types.js.map +1 -0
  36. package/dist/automation/run.d.ts +25 -0
  37. package/dist/automation/run.js +68 -0
  38. package/dist/automation/run.js.map +1 -0
  39. package/dist/automation/schema.d.ts +130 -0
  40. package/dist/automation/schema.js +46 -0
  41. package/dist/automation/schema.js.map +1 -0
  42. package/dist/automation/status.d.ts +16 -0
  43. package/dist/automation/status.js +56 -0
  44. package/dist/automation/status.js.map +1 -0
  45. package/dist/automation/verifiers/index.d.ts +7 -0
  46. package/dist/automation/verifiers/index.js +5 -0
  47. package/dist/automation/verifiers/index.js.map +1 -0
  48. package/dist/automation/verifiers/shell.d.ts +5 -0
  49. package/dist/automation/verifiers/shell.js +17 -0
  50. package/dist/automation/verifiers/shell.js.map +1 -0
  51. package/dist/automation/verifiers/types.d.ts +12 -0
  52. package/dist/automation/verifiers/types.js +2 -0
  53. package/dist/automation/verifiers/types.js.map +1 -0
  54. package/dist/backlog/add.d.ts +10 -0
  55. package/dist/backlog/add.js +30 -0
  56. package/dist/backlog/add.js.map +1 -0
  57. package/dist/backlog/index.d.ts +1 -0
  58. package/dist/backlog/index.js +53 -0
  59. package/dist/backlog/index.js.map +1 -0
  60. package/dist/config.d.ts +26 -0
  61. package/dist/config.js +110 -0
  62. package/dist/config.js.map +1 -0
  63. package/dist/detect.d.ts +2 -0
  64. package/dist/detect.js +26 -0
  65. package/dist/detect.js.map +1 -0
  66. package/dist/doctor-invariants.d.ts +6 -0
  67. package/dist/doctor-invariants.js +50 -0
  68. package/dist/doctor-invariants.js.map +1 -0
  69. package/dist/doctor.d.ts +13 -0
  70. package/dist/doctor.js +281 -0
  71. package/dist/doctor.js.map +1 -0
  72. package/dist/generate.d.ts +1 -0
  73. package/dist/generate.js +275 -0
  74. package/dist/generate.js.map +1 -0
  75. package/dist/generator/agent.d.ts +8 -0
  76. package/dist/generator/agent.js +66 -0
  77. package/dist/generator/agent.js.map +1 -0
  78. package/dist/generator/api.d.ts +7 -0
  79. package/dist/generator/api.js +42 -0
  80. package/dist/generator/api.js.map +1 -0
  81. package/dist/generator/config.d.ts +23 -0
  82. package/dist/generator/config.js +121 -0
  83. package/dist/generator/config.js.map +1 -0
  84. package/dist/generator/parse-response.d.ts +5 -0
  85. package/dist/generator/parse-response.js +58 -0
  86. package/dist/generator/parse-response.js.map +1 -0
  87. package/dist/generator/prompt.d.ts +9 -0
  88. package/dist/generator/prompt.js +166 -0
  89. package/dist/generator/prompt.js.map +1 -0
  90. package/dist/generator/request.d.ts +17 -0
  91. package/dist/generator/request.js +15 -0
  92. package/dist/generator/request.js.map +1 -0
  93. package/dist/generators/prompts/stencil.md +45 -0
  94. package/dist/generators/prompts/vue.md +54 -0
  95. package/dist/index.d.ts +2 -0
  96. package/dist/index.js +102 -0
  97. package/dist/index.js.map +1 -0
  98. package/dist/init.d.ts +1 -0
  99. package/dist/init.js +89 -0
  100. package/dist/init.js.map +1 -0
  101. package/dist/installers/context.d.ts +4 -0
  102. package/dist/installers/context.js +120 -0
  103. package/dist/installers/context.js.map +1 -0
  104. package/dist/installers/index.d.ts +7 -0
  105. package/dist/installers/index.js +22 -0
  106. package/dist/installers/index.js.map +1 -0
  107. package/dist/installers/installer.d.ts +12 -0
  108. package/dist/installers/installer.js +30 -0
  109. package/dist/installers/installer.js.map +1 -0
  110. package/dist/installers/stencil/django-template/installer.d.ts +10 -0
  111. package/dist/installers/stencil/django-template/installer.js +77 -0
  112. package/dist/installers/stencil/django-template/installer.js.map +1 -0
  113. package/dist/installers/stencil/react/installer.d.ts +9 -0
  114. package/dist/installers/stencil/react/installer.js +22 -0
  115. package/dist/installers/stencil/react/installer.js.map +1 -0
  116. package/dist/installers/stencil/react/manifest.json +17 -0
  117. package/dist/installers/types.d.ts +24 -0
  118. package/dist/installers/types.js +2 -0
  119. package/dist/installers/types.js.map +1 -0
  120. package/dist/lock.d.ts +25 -0
  121. package/dist/lock.js +86 -0
  122. package/dist/lock.js.map +1 -0
  123. package/dist/manifest.d.ts +1 -0
  124. package/dist/manifest.js +93 -0
  125. package/dist/manifest.js.map +1 -0
  126. package/dist/pm/audit.d.ts +36 -0
  127. package/dist/pm/audit.js +147 -0
  128. package/dist/pm/audit.js.map +1 -0
  129. package/dist/pm/backlog.d.ts +3 -0
  130. package/dist/pm/backlog.js +123 -0
  131. package/dist/pm/backlog.js.map +1 -0
  132. package/dist/pm/brief.d.ts +4 -0
  133. package/dist/pm/brief.js +18 -0
  134. package/dist/pm/brief.js.map +1 -0
  135. package/dist/pm/git.d.ts +3 -0
  136. package/dist/pm/git.js +43 -0
  137. package/dist/pm/git.js.map +1 -0
  138. package/dist/pm/grid.d.ts +8 -0
  139. package/dist/pm/grid.js +16 -0
  140. package/dist/pm/grid.js.map +1 -0
  141. package/dist/pm/index.d.ts +25 -0
  142. package/dist/pm/index.js +199 -0
  143. package/dist/pm/index.js.map +1 -0
  144. package/dist/pm/observe.d.ts +55 -0
  145. package/dist/pm/observe.js +177 -0
  146. package/dist/pm/observe.js.map +1 -0
  147. package/dist/pm/plan.d.ts +54 -0
  148. package/dist/pm/plan.js +151 -0
  149. package/dist/pm/plan.js.map +1 -0
  150. package/dist/pm/refinement-worktree.d.ts +31 -0
  151. package/dist/pm/refinement-worktree.js +160 -0
  152. package/dist/pm/refinement-worktree.js.map +1 -0
  153. package/dist/pm/refinement.d.ts +79 -0
  154. package/dist/pm/refinement.js +326 -0
  155. package/dist/pm/refinement.js.map +1 -0
  156. package/dist/pm/render.d.ts +2 -0
  157. package/dist/pm/render.js +39 -0
  158. package/dist/pm/render.js.map +1 -0
  159. package/dist/pm/roadmap-rings.d.ts +7 -0
  160. package/dist/pm/roadmap-rings.js +31 -0
  161. package/dist/pm/roadmap-rings.js.map +1 -0
  162. package/dist/pm/roadmap.d.ts +2 -0
  163. package/dist/pm/roadmap.js +118 -0
  164. package/dist/pm/roadmap.js.map +1 -0
  165. package/dist/pm/snapshot.d.ts +10 -0
  166. package/dist/pm/snapshot.js +129 -0
  167. package/dist/pm/snapshot.js.map +1 -0
  168. package/dist/pm/types.d.ts +99 -0
  169. package/dist/pm/types.js +29 -0
  170. package/dist/pm/types.js.map +1 -0
  171. package/dist/registry-layout.d.ts +18 -0
  172. package/dist/registry-layout.js +122 -0
  173. package/dist/registry-layout.js.map +1 -0
  174. package/dist/scaffold-registry.d.ts +10 -0
  175. package/dist/scaffold-registry.js +283 -0
  176. package/dist/scaffold-registry.js.map +1 -0
  177. package/dist/scaffold.d.ts +1 -0
  178. package/dist/scaffold.js +32 -0
  179. package/dist/scaffold.js.map +1 -0
  180. package/dist/spec-from-react.d.ts +11 -0
  181. package/dist/spec-from-react.js +522 -0
  182. package/dist/spec-from-react.js.map +1 -0
  183. package/dist/spec-from-stencil.d.ts +7 -0
  184. package/dist/spec-from-stencil.js +275 -0
  185. package/dist/spec-from-stencil.js.map +1 -0
  186. package/dist/spec.d.ts +1 -0
  187. package/dist/spec.js +60 -0
  188. package/dist/spec.js.map +1 -0
  189. package/dist/tokens-map.d.ts +11 -0
  190. package/dist/tokens-map.js +43 -0
  191. package/dist/tokens-map.js.map +1 -0
  192. package/dist/update.d.ts +39 -0
  193. package/dist/update.js +490 -0
  194. package/dist/update.js.map +1 -0
  195. package/dist/workspace-init.d.ts +9 -0
  196. package/dist/workspace-init.js +119 -0
  197. package/dist/workspace-init.js.map +1 -0
  198. package/package.json +53 -0
package/dist/lock.d.ts ADDED
@@ -0,0 +1,25 @@
1
+ import type { ModuleType } from "@chiralkit/registry-schema";
2
+ export declare const LOCK_FILE = "chiralkit.lock.json";
3
+ export declare function lockPath(cwd: string): string;
4
+ export declare function legacyLockExists(cwd: string): Promise<boolean>;
5
+ export declare function legacyLockMigrationHint(cwd: string): string;
6
+ export interface LockedModule {
7
+ type: ModuleType;
8
+ version: string;
9
+ installed_at: string;
10
+ files: Record<string, string>;
11
+ }
12
+ export interface Lock {
13
+ modules: Record<string, LockedModule>;
14
+ }
15
+ export declare function lockKey(name: string, type: ModuleType): string;
16
+ export declare function parseLockKey(key: string): {
17
+ name: string;
18
+ type: ModuleType;
19
+ };
20
+ export declare function lockExists(cwd: string): Promise<boolean>;
21
+ export declare function readLock(cwd: string): Promise<Lock>;
22
+ export declare function writeLock(cwd: string, lock: Lock): Promise<void>;
23
+ export declare function sha256(content: string | Buffer): string;
24
+ export declare function hashFile(absPath: string): Promise<string>;
25
+ export declare function toRelativePosix(cwd: string, absPath: string): string;
package/dist/lock.js ADDED
@@ -0,0 +1,86 @@
1
+ import { createHash } from "node:crypto";
2
+ import { access, mkdir, readFile, writeFile } from "node:fs/promises";
3
+ import { dirname, join, relative } from "node:path";
4
+ import { CONFIG_DIR } from "./config.js";
5
+ // The consumer-project ledger. Sits next to chiralkit.config.json under ck/.
6
+ // Auto-managed by `add` / `update` / `lock --init` — humans read it,
7
+ // they don't edit it. Committed. Same social contract as pnpm-lock.yaml.
8
+ export const LOCK_FILE = "chiralkit.lock.json";
9
+ export function lockPath(cwd) {
10
+ return join(cwd, CONFIG_DIR, LOCK_FILE);
11
+ }
12
+ // Legacy: chiralkit.lock.json at the project root, before the ck/ folder.
13
+ // Detected so entry points can refuse instead of orphaning it under ck/.
14
+ export async function legacyLockExists(cwd) {
15
+ try {
16
+ await access(join(cwd, LOCK_FILE));
17
+ return true;
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }
23
+ export function legacyLockMigrationHint(cwd) {
24
+ return `Legacy lock at ${join(cwd, LOCK_FILE)} — move it: \`mkdir -p ${CONFIG_DIR} && git mv ${LOCK_FILE} ${CONFIG_DIR}/${LOCK_FILE}\`.`;
25
+ }
26
+ // The wire schema uses `${moduleName}@${type}` as key when disambiguating
27
+ // cross-family name collisions, so update <name> can find the right entry
28
+ // without a --type flag in the common case AND still work when two
29
+ // families ship a `card` module. Present in the lock format from day one
30
+ // so we do not need a schema bump the first time a collision appears.
31
+ export function lockKey(name, type) {
32
+ return `${name}@${type}`;
33
+ }
34
+ export function parseLockKey(key) {
35
+ const at = key.lastIndexOf("@");
36
+ const name = key.slice(0, at);
37
+ const type = key.slice(at + 1);
38
+ return { name, type };
39
+ }
40
+ export async function lockExists(cwd) {
41
+ try {
42
+ await access(lockPath(cwd));
43
+ return true;
44
+ }
45
+ catch {
46
+ return false;
47
+ }
48
+ }
49
+ export async function readLock(cwd) {
50
+ const path = lockPath(cwd);
51
+ const raw = await readFile(path, "utf8");
52
+ return JSON.parse(raw);
53
+ }
54
+ export async function writeLock(cwd, lock) {
55
+ const path = lockPath(cwd);
56
+ await mkdir(dirname(path), { recursive: true });
57
+ // Stable field ordering + trailing newline so diffs stay small.
58
+ const sortedModules = {};
59
+ for (const key of Object.keys(lock.modules).sort()) {
60
+ const m = lock.modules[key];
61
+ const sortedFiles = {};
62
+ for (const p of Object.keys(m.files).sort())
63
+ sortedFiles[p] = m.files[p];
64
+ sortedModules[key] = {
65
+ type: m.type,
66
+ version: m.version,
67
+ installed_at: m.installed_at,
68
+ files: sortedFiles,
69
+ };
70
+ }
71
+ const serialized = JSON.stringify({ modules: sortedModules }, null, 2) + "\n";
72
+ await writeFile(path, serialized, "utf8");
73
+ }
74
+ export function sha256(content) {
75
+ return "sha256:" + createHash("sha256").update(content).digest("hex");
76
+ }
77
+ export async function hashFile(absPath) {
78
+ const raw = await readFile(absPath);
79
+ return sha256(raw);
80
+ }
81
+ // Project-relative POSIX path (forward slashes) so the lock is portable
82
+ // between macOS/Linux and Windows checkouts.
83
+ export function toRelativePosix(cwd, absPath) {
84
+ return relative(cwd, absPath).split("\\").join("/");
85
+ }
86
+ //# sourceMappingURL=lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.js","sourceRoot":"","sources":["../src/lock.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function runManifest(rest: string[]): void;
@@ -0,0 +1,93 @@
1
+ // `chiralkit manifest` — prints the project mark + manifesto to stdout.
2
+ //
3
+ // The mark is a sculpted block-drawn C with chamfered corners (▟▙▛▜
4
+ // quadrant chars). The wordmark carries an `(R)-` prefix — chemistry
5
+ // chirality notation ("R-configuration"). Rhymes with the project name;
6
+ // molecular-chemistry folks catch the reference, others read it as a
7
+ // version tag or a trademark and skip past. Zero cost, mild depth.
8
+ //
9
+ // Color: when stdout is a TTY and NO_COLOR is unset, the mark renders
10
+ // in Chiralkit's brand violet (approx --ds-color-primary rendered as
11
+ // ANSI truecolor RGB 138,90,191). Falls back to plain block chars for
12
+ // piped output, NO_COLOR terminals, and CI logs — respects the
13
+ // no-surprises rule for machine-consumed output.
14
+ //
15
+ // The manifesto text is hardcoded in two locales here. This intentionally
16
+ // duplicates the same content in `apps/web/src/i18n/{en,es}.json`
17
+ // (`manifesto.body`) — the web + CLI have separate lifecycles and the
18
+ // text is short + stable. If it grows into paragraphs, promote to a
19
+ // shared source (`packages/manifesto/`) so drift becomes impossible.
20
+ const CHIRAL_MARK = ` ▄█████████▄
21
+ ▐██▀▀▀▀▀▀▀▀▀
22
+ ▐██
23
+ ▐██
24
+ ▐██
25
+ ▐██▄▄▄▄▄▄▄▄▄
26
+ ▀█████████▀`;
27
+ const BRAND_VIOLET_FG = "\x1b[38;2;138;90;191m";
28
+ const DIM = "\x1b[2m";
29
+ const RESET = "\x1b[0m";
30
+ function shouldColor() {
31
+ if (process.env.NO_COLOR !== undefined)
32
+ return false;
33
+ return process.stdout.isTTY === true;
34
+ }
35
+ function colorize(mark, wordmark) {
36
+ if (!shouldColor())
37
+ return { mark, wordmark };
38
+ return {
39
+ mark: `${BRAND_VIOLET_FG}${mark}${RESET}`,
40
+ wordmark: `${DIM}(R)-${RESET}${wordmark}`,
41
+ };
42
+ }
43
+ const MANIFESTO = {
44
+ en: "Complex systems emerge from simple rules. Our work is to find those patterns and make them reusable.",
45
+ es: "Los sistemas complejos emergen de reglas simples. Nuestro objetivo es encontrar esos patrones y hacerlos reutilizables.",
46
+ };
47
+ function isLang(x) {
48
+ return x === "en" || x === "es";
49
+ }
50
+ // Word-wraps `text` to `width` columns, prefixing every line with `indent`.
51
+ // Single-space between words; drops leading/trailing whitespace on the source.
52
+ function wrap(text, width, indent) {
53
+ const words = text.trim().split(/\s+/);
54
+ const lines = [];
55
+ let current = "";
56
+ for (const w of words) {
57
+ const next = current === "" ? w : `${current} ${w}`;
58
+ if (indent.length + next.length > width) {
59
+ lines.push(indent + current);
60
+ current = w;
61
+ }
62
+ else {
63
+ current = next;
64
+ }
65
+ }
66
+ if (current !== "")
67
+ lines.push(indent + current);
68
+ return lines.join("\n");
69
+ }
70
+ export function runManifest(rest) {
71
+ // Parse `--lang <en|es>`; defaults to `en`. Unknown values fall back
72
+ // to `en` rather than erroring — `manifest` is a display command,
73
+ // failing it for a typo would be user-hostile.
74
+ const langIdx = rest.indexOf("--lang");
75
+ const requestedLang = langIdx >= 0 && rest[langIdx + 1] !== undefined ? rest[langIdx + 1] : "en";
76
+ const lang = isLang(requestedLang) ? requestedLang : "en";
77
+ const width = 72;
78
+ const indent = " ";
79
+ // Wordmark's `(R)-` prefix is a chirality-notation Easter egg. In
80
+ // color mode the `(R)-` is dim so `chiralkit` stays the visual focus;
81
+ // in plain mode we skip the prefix (looks like clutter without the
82
+ // dim treatment to soften it).
83
+ const plainWordmark = "chiralkit";
84
+ const { mark, wordmark } = colorize(CHIRAL_MARK, plainWordmark);
85
+ console.log("");
86
+ console.log(mark);
87
+ console.log("");
88
+ console.log(`${indent}${wordmark}`);
89
+ console.log("");
90
+ console.log(wrap(MANIFESTO[lang], width, indent));
91
+ console.log("");
92
+ }
93
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import type { GitExec } from "./git.js";
2
+ import type { ProjectSnapshot } from "./types.js";
3
+ export interface MergedBranch {
4
+ name: string;
5
+ scope: "local" | "remote";
6
+ }
7
+ export interface StaleWorktree {
8
+ path: string;
9
+ branch: string;
10
+ lastCommitISO: string;
11
+ daysStale: number;
12
+ }
13
+ export interface RoadmapCandidate {
14
+ line: number;
15
+ title: string;
16
+ area: string;
17
+ command: string;
18
+ evidence: string[];
19
+ }
20
+ export interface AuditReport {
21
+ mergedBranches: MergedBranch[];
22
+ staleWorktrees: StaleWorktree[];
23
+ roadmapCandidates: RoadmapCandidate[];
24
+ errors: string[];
25
+ }
26
+ export interface AuditDependencies {
27
+ cwd: string;
28
+ git: GitExec;
29
+ fileExists: (path: string) => Promise<boolean>;
30
+ readText: (path: string) => Promise<string>;
31
+ now?: () => Date;
32
+ mainBranch?: string;
33
+ staleDays?: number;
34
+ }
35
+ export declare function runAudit(deps: AuditDependencies, snapshot: ProjectSnapshot): Promise<AuditReport>;
36
+ export declare function renderAuditReport(report: AuditReport, main: string): string;
@@ -0,0 +1,147 @@
1
+ import { join } from "node:path";
2
+ const CMD_PATTERN = /`(?:chiralkit|ck) ([a-z][a-z0-9-]*(?: [a-z][a-z0-9-]*)?)(?:[^a-z0-9-][^`]*)?`/;
3
+ async function findMergedBranches(deps, main) {
4
+ const merged = [];
5
+ try {
6
+ const local = (await deps.git(deps.cwd, ["branch", "--format=%(refname:short)", "--merged", main])).trim().split(/\r?\n/);
7
+ for (const raw of local) {
8
+ const name = raw.replace(/^\*\s*/, "").trim();
9
+ if (!name || name === main)
10
+ continue;
11
+ merged.push({ name, scope: "local" });
12
+ }
13
+ }
14
+ catch { /* branch listing failed — skip local scope */ }
15
+ try {
16
+ const remote = (await deps.git(deps.cwd, ["branch", "-r", "--format=%(refname:short)", "--merged", main])).trim().split(/\r?\n/);
17
+ for (const raw of remote) {
18
+ const name = raw.trim();
19
+ if (!name || name === `origin/${main}` || name.startsWith("origin/HEAD") || !name.includes("/"))
20
+ continue;
21
+ merged.push({ name, scope: "remote" });
22
+ }
23
+ }
24
+ catch { /* remote listing failed — skip remote scope */ }
25
+ return merged;
26
+ }
27
+ async function listWorktrees(deps) {
28
+ try {
29
+ const output = await deps.git(deps.cwd, ["worktree", "list", "--porcelain"]);
30
+ return output.trim().split(/\r?\n\r?\n/).map((record) => {
31
+ const lines = record.split(/\r?\n/);
32
+ if (lines.some((line) => line.startsWith("prunable")))
33
+ return undefined;
34
+ const path = lines.find((line) => line.startsWith("worktree "))?.slice(9);
35
+ if (!path)
36
+ return undefined;
37
+ const branch = lines.find((line) => line.startsWith("branch "))?.slice(7).replace(/^refs\/heads\//, "") ?? "detached";
38
+ return { path, branch, current: false, dirty: false };
39
+ }).filter((worktree) => worktree !== undefined);
40
+ }
41
+ catch {
42
+ return [];
43
+ }
44
+ }
45
+ async function findStaleWorktrees(deps, worktrees, staleDays, now) {
46
+ const stale = [];
47
+ for (const worktree of worktrees) {
48
+ if (worktree.current)
49
+ continue;
50
+ try {
51
+ const isoRaw = (await deps.git(worktree.path, ["log", "-1", "--format=%cI", "HEAD"])).trim();
52
+ if (!isoRaw)
53
+ continue;
54
+ const lastCommit = new Date(isoRaw);
55
+ const daysStale = Math.floor((now.getTime() - lastCommit.getTime()) / 86_400_000);
56
+ if (daysStale >= staleDays)
57
+ stale.push({ path: worktree.path, branch: worktree.branch, lastCommitISO: isoRaw, daysStale });
58
+ }
59
+ catch { /* worktree unreadable — skip */ }
60
+ }
61
+ return stale;
62
+ }
63
+ function extractCommand(item) {
64
+ const source = `${item.title} ${item.description}`;
65
+ const match = CMD_PATTERN.exec(source);
66
+ return match?.[1];
67
+ }
68
+ async function evaluateRoadmap(deps, snapshot) {
69
+ const errors = [];
70
+ const cliIndex = join(deps.cwd, "packages/cli/src/index.ts");
71
+ let indexText = "";
72
+ try {
73
+ indexText = await deps.readText(cliIndex);
74
+ }
75
+ catch (error) {
76
+ errors.push(`audit: read ${cliIndex}: ${error.message}`);
77
+ }
78
+ const candidates = [];
79
+ for (const horizon of snapshot.roadmap.horizons) {
80
+ for (const item of horizon.items) {
81
+ if (item.checked)
82
+ continue;
83
+ if (item.area !== "CLI")
84
+ continue;
85
+ const command = extractCommand(item);
86
+ if (!command)
87
+ continue;
88
+ const top = command.split(" ")[0];
89
+ const evidence = [];
90
+ const caseNeedle = `case "${top}":`;
91
+ if (indexText.includes(caseNeedle))
92
+ evidence.push(`case "${top}" wired in cli/src/index.ts`);
93
+ const primary = join(deps.cwd, `packages/cli/src/${top}.ts`);
94
+ if (await deps.fileExists(primary))
95
+ evidence.push(`packages/cli/src/${top}.ts exists`);
96
+ const secondary = join(deps.cwd, `packages/cli/src/${top}-${command.split(" ")[1] ?? ""}.ts`);
97
+ if (command.includes(" ") && await deps.fileExists(secondary))
98
+ evidence.push(`packages/cli/src/${top}-${command.split(" ")[1]}.ts exists`);
99
+ const testFile = join(deps.cwd, `packages/cli/src/${top}.test.ts`);
100
+ if (await deps.fileExists(testFile))
101
+ evidence.push(`packages/cli/src/${top}.test.ts exists`);
102
+ if (evidence.length >= 2)
103
+ candidates.push({ line: item.line, title: item.title, area: item.area, command, evidence });
104
+ }
105
+ }
106
+ return { candidates, errors };
107
+ }
108
+ export async function runAudit(deps, snapshot) {
109
+ const now = (deps.now ?? (() => new Date()))();
110
+ const staleDays = deps.staleDays ?? 14;
111
+ const main = deps.mainBranch ?? "main";
112
+ const errors = [];
113
+ const mergedBranches = await findMergedBranches(deps, main);
114
+ const worktrees = snapshot.git.available ? snapshot.git.worktrees : await listWorktrees(deps);
115
+ const staleWorktrees = await findStaleWorktrees(deps, worktrees, staleDays, now);
116
+ const roadmap = await evaluateRoadmap(deps, snapshot);
117
+ errors.push(...roadmap.errors);
118
+ return { mergedBranches, staleWorktrees, roadmapCandidates: roadmap.candidates, errors };
119
+ }
120
+ export function renderAuditReport(report, main) {
121
+ const lines = ["", "AUDIT — pruning & drift"];
122
+ lines.push(` branches merged into ${main} (safe to delete):`);
123
+ if (report.mergedBranches.length === 0)
124
+ lines.push(" none");
125
+ for (const branch of report.mergedBranches)
126
+ lines.push(` - ${branch.scope.padEnd(6)} ${branch.name}`);
127
+ lines.push(" stale worktrees:");
128
+ if (report.staleWorktrees.length === 0)
129
+ lines.push(" none");
130
+ for (const worktree of report.staleWorktrees)
131
+ lines.push(` - ${worktree.branch} ${worktree.daysStale}d idle ${worktree.path}`);
132
+ lines.push(" roadmap items that look done (heuristic — verify before checking):");
133
+ if (report.roadmapCandidates.length === 0)
134
+ lines.push(" none");
135
+ for (const candidate of report.roadmapCandidates) {
136
+ lines.push(` - ROADMAP.md:${candidate.line} ck ${candidate.command} — ${candidate.title}`);
137
+ for (const evidence of candidate.evidence)
138
+ lines.push(` · ${evidence}`);
139
+ }
140
+ if (report.errors.length > 0) {
141
+ lines.push(" audit errors:");
142
+ for (const error of report.errors)
143
+ lines.push(` ! ${error}`);
144
+ }
145
+ return `${lines.join("\n")}\n`;
146
+ }
147
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/pm/audit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type BacklogParseResult } from "./types.js";
2
+ export declare function normalizeAreaFromHeading(heading: string): string;
3
+ export declare function parseBacklog(source: string): BacklogParseResult;
@@ -0,0 +1,123 @@
1
+ import { AREAS, FIB_VALUES, PRIORITY_VALUES, STATUS_VALUES, } from "./types.js";
2
+ const TIME_PATTERN = /\[time:([^\]]*)\]/g;
3
+ const DIFFICULTY_PATTERN = /\[difficulty:([^\]]*)\]/g;
4
+ const PRIORITY_PATTERN = /\[priority:([^\]]*)\]/g;
5
+ const STATUS_PATTERN = /\[status:([^\]]*)\]/g;
6
+ const LEGACY_FIB_PATTERN = /\[fib:[^\]]*\]/;
7
+ const KIT_PATTERN = /\[kit:([^\]]*)\]/g;
8
+ const AREA_PATTERN = /\[area:([^\]]*)\]/g;
9
+ const TAG_STRIP = /\[(?:time|difficulty|priority|status|kit|area):[^\]]+\]\s*/g;
10
+ const AREAS_SET = new Set(AREAS);
11
+ // Fallback: extract a canonical area from an H2 heading when a task has no
12
+ // `[area:X]` inline tag. Strips epic-style prefixes (Feat/Bug/Epic/Task/Chore),
13
+ // parenthetical suffixes, and the repo-specific `Chiral` prefix, then splits
14
+ // on em-dash/colon, slugifies, and tries to match the first word against
15
+ // AREAS. Falls back to the raw slug when no canonical match exists.
16
+ export function normalizeAreaFromHeading(heading) {
17
+ const cleaned = heading
18
+ .replace(/^(Feat|Bug|Epic|Task|Chore):\s+/i, "")
19
+ .replace(/\s*\([^)]*\)/g, "")
20
+ .split(/\s*[—:]\s*/)[0]
21
+ .trim();
22
+ const slug = cleaned
23
+ .toLowerCase()
24
+ .replace(/[^a-z0-9]+/g, "-")
25
+ .replace(/^-+|-+$/g, "");
26
+ const dechiraled = slug.startsWith("chiral") ? slug.slice(6).replace(/^-+/, "") : slug;
27
+ const firstWord = dechiraled.split("-")[0] ?? "";
28
+ if (AREAS_SET.has(firstWord))
29
+ return firstWord;
30
+ return dechiraled || slug;
31
+ }
32
+ const ALLOWED_FIB = FIB_VALUES.map(String);
33
+ function isPriority(v) { return PRIORITY_VALUES.includes(v); }
34
+ function isStatus(v) { return STATUS_VALUES.includes(v); }
35
+ function isFib(v) { return ALLOWED_FIB.includes(v); }
36
+ function checkAxis(axis, matches) {
37
+ if (matches.length === 0)
38
+ return { reason: `missing ${axis}` };
39
+ if (matches.length > 1)
40
+ return { reason: `${axis} must appear exactly once` };
41
+ const raw = matches[0][1] ?? "";
42
+ if (!isFib(raw))
43
+ return { reason: `${axis} must be one of 0,1,2,3,5,8,13` };
44
+ return { value: Number(raw) };
45
+ }
46
+ export function parseBacklog(source) {
47
+ const tasks = [];
48
+ const invalid = [];
49
+ let headingArea = "";
50
+ let order = 0;
51
+ for (const [index, line] of source.split(/\r?\n/).entries()) {
52
+ const heading = line.match(/^#{2,3}\s+(.+?)\s*#*\s*$/);
53
+ if (heading) {
54
+ headingArea = normalizeAreaFromHeading(heading[1].trim());
55
+ continue;
56
+ }
57
+ const checklist = line.match(/^- \[([ xX])\] (.*)$/);
58
+ if (!checklist)
59
+ continue;
60
+ const lineNumber = index + 1;
61
+ const raw = checklist[2];
62
+ const checked = checklist[1].toLowerCase() === "x";
63
+ if (LEGACY_FIB_PATTERN.test(raw)) {
64
+ invalid.push({ area: headingArea, raw, line: lineNumber, reason: "legacy fib tag — migrate to [time:N] [difficulty:N]" });
65
+ continue;
66
+ }
67
+ const timeMatches = [...raw.matchAll(TIME_PATTERN)];
68
+ const difficultyMatches = [...raw.matchAll(DIFFICULTY_PATTERN)];
69
+ const priorityMatches = [...raw.matchAll(PRIORITY_PATTERN)];
70
+ const statusMatches = [...raw.matchAll(STATUS_PATTERN)];
71
+ const kitMatches = [...raw.matchAll(KIT_PATTERN)];
72
+ const areaMatches = [...raw.matchAll(AREA_PATTERN)];
73
+ const reasons = [];
74
+ const timeCheck = checkAxis("time", timeMatches);
75
+ if (timeCheck.reason)
76
+ reasons.push(timeCheck.reason);
77
+ const difficultyCheck = checkAxis("difficulty", difficultyMatches);
78
+ if (difficultyCheck.reason)
79
+ reasons.push(difficultyCheck.reason);
80
+ if (priorityMatches.length === 0)
81
+ reasons.push("missing priority");
82
+ else if (priorityMatches.length > 1)
83
+ reasons.push("priority must appear exactly once");
84
+ if (statusMatches.length === 0)
85
+ reasons.push("missing status");
86
+ else if (statusMatches.length > 1)
87
+ reasons.push("status must appear exactly once");
88
+ const priorityValue = priorityMatches[0]?.[1] ?? "";
89
+ const statusValue = statusMatches[0]?.[1] ?? "";
90
+ if (priorityMatches.length === 1 && !isPriority(priorityValue))
91
+ reasons.push("priority must be one of P0,P1,P2,P3");
92
+ if (statusMatches.length === 1 && !isStatus(statusValue))
93
+ reasons.push("status must be one of ready,active,blocked,done");
94
+ if (checked && statusValue !== "done")
95
+ reasons.push("checked task must have status:done");
96
+ if (!checked && statusValue === "done")
97
+ reasons.push("unchecked task must not have status:done");
98
+ if (kitMatches.length > 1)
99
+ reasons.push("kit must appear at most once");
100
+ if (areaMatches.length > 1)
101
+ reasons.push("area must appear at most once");
102
+ if (reasons.length > 0) {
103
+ invalid.push({ area: headingArea, raw, line: lineNumber, reason: reasons.join(", ") });
104
+ continue;
105
+ }
106
+ const kitFromTag = kitMatches[0]?.[1];
107
+ const areaFromTag = areaMatches[0]?.[1]?.trim();
108
+ tasks.push({
109
+ area: areaFromTag || headingArea,
110
+ text: raw.replace(TAG_STRIP, "").trim(),
111
+ checked,
112
+ time: timeCheck.value,
113
+ difficulty: difficultyCheck.value,
114
+ priority: priorityValue,
115
+ status: statusValue,
116
+ ...(kitFromTag ? { kit: kitFromTag } : {}),
117
+ line: lineNumber,
118
+ order: order++,
119
+ });
120
+ }
121
+ return { tasks, invalid };
122
+ }
123
+ //# sourceMappingURL=backlog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backlog.js","sourceRoot":"","sources":["../../src/pm/backlog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { type LocalAgentOptions } from "../agents/subprocess.js";
2
+ import type { ProjectSnapshot } from "./types.js";
3
+ export declare function serializePmBrief(snapshot: ProjectSnapshot): string;
4
+ export declare function runPmBrief(snapshot: ProjectSnapshot, options?: LocalAgentOptions): Promise<string>;
@@ -0,0 +1,18 @@
1
+ import { runLocalAgent } from "../agents/subprocess.js";
2
+ export function serializePmBrief(snapshot) {
3
+ return [
4
+ "ROLE: ck-pm, read-only L5 project observer",
5
+ "CONSTRAINTS:",
6
+ "- Do not invent fib, priority, status, branch, or worktree data.",
7
+ "- Do not propose file edits or Git mutations.",
8
+ "- Return only: focus, blockers, attraction↔resistance balance, anomalies, decomposition suggestions.",
9
+ "PROJECT SNAPSHOT JSON:",
10
+ JSON.stringify(snapshot, null, 2),
11
+ ].join("\n");
12
+ }
13
+ export function runPmBrief(snapshot, options = {}) {
14
+ const bin = process.env.CHIRALKIT_CLAUDE_BIN ?? "claude";
15
+ const args = process.env.CHIRALKIT_CLAUDE_ARGS ? JSON.parse(process.env.CHIRALKIT_CLAUDE_ARGS) : ["-p"];
16
+ return runLocalAgent({ bin, args, label: "ck-pm" }, serializePmBrief(snapshot), options);
17
+ }
18
+ //# sourceMappingURL=brief.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brief.js","sourceRoot":"","sources":["../../src/pm/brief.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAA0B,MAAM,yBAAyB,CAAC;AAGhF,MAAM,UAAU,gBAAgB,CAAC,QAAyB;IACxD,OAAO;QACL,4CAA4C;QAC5C,cAAc;QACd,kEAAkE;QAClE,+CAA+C;QAC/C,sGAAsG;QACtG,wBAAwB;QACxB,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;KAClC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAAyB,EAAE,UAA6B,EAAE;IACnF,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,QAAQ,CAAC;IACzD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAa,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACpH,OAAO,aAAa,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,gBAAgB,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;AAC3F,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { GitObservation } from "./types.js";
2
+ export type GitExec = (cwd: string, args: string[]) => Promise<string>;
3
+ export declare function observeGit(cwd: string, exec?: GitExec): Promise<GitObservation>;
package/dist/pm/git.js ADDED
@@ -0,0 +1,43 @@
1
+ import { execFile } from "node:child_process";
2
+ import { resolve } from "node:path";
3
+ import { promisify } from "node:util";
4
+ const execFileAsync = promisify(execFile);
5
+ const defaultGitExec = async (cwd, args) => {
6
+ const { stdout } = await execFileAsync("git", args, { cwd });
7
+ return stdout;
8
+ };
9
+ function parseWorktrees(output, cwd) {
10
+ const currentPath = resolve(cwd);
11
+ return output
12
+ .trim()
13
+ .split(/\r?\n\r?\n/)
14
+ .map((record) => record.split(/\r?\n/))
15
+ .map((lines) => {
16
+ if (lines.some((line) => line.startsWith("prunable")))
17
+ return undefined;
18
+ const path = lines.find((line) => line.startsWith("worktree "))?.slice(9);
19
+ if (!path)
20
+ return undefined;
21
+ const branchLine = lines.find((line) => line.startsWith("branch "));
22
+ const branch = branchLine?.slice(7).replace(/^refs\/heads\//, "") ?? "detached";
23
+ return { path, branch, current: resolve(path) === currentPath, dirty: false };
24
+ })
25
+ .filter((worktree) => worktree !== undefined);
26
+ }
27
+ export async function observeGit(cwd, exec = defaultGitExec) {
28
+ try {
29
+ const worktrees = parseWorktrees(await exec(cwd, ["worktree", "list", "--porcelain"]), cwd);
30
+ for (const worktree of worktrees) {
31
+ worktree.dirty = (await exec(worktree.path, ["status", "--porcelain"])).trim() !== "";
32
+ }
33
+ return { available: true, worktrees };
34
+ }
35
+ catch (error) {
36
+ return {
37
+ available: false,
38
+ reason: error instanceof Error ? error.message : String(error),
39
+ worktrees: [],
40
+ };
41
+ }
42
+ }
43
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/pm/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAI1C,MAAM,cAAc,GAAY,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IAClD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IAC7D,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,SAAS,cAAc,CAAC,MAAc,EAAE,GAAW;IACjD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACjC,OAAO,MAAM;SACV,IAAI,EAAE;SACN,KAAK,CAAC,YAAY,CAAC;SACnB,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;SACtC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACb,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;YAAE,OAAO,SAAS,CAAC;QACxE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;QAC1E,IAAI,CAAC,IAAI;YAAE,OAAO,SAAS,CAAC;QAC5B,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;QACpE,MAAM,MAAM,GAAG,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,IAAI,UAAU,CAAC;QAChF,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAChF,CAAC,CAAC;SACD,MAAM,CAAC,CAAC,QAAQ,EAA2B,EAAE,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,GAAW,EACX,OAAgB,cAAc;IAE9B,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,cAAc,CAC9B,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,EACpD,GAAG,CACJ,CAAC;QACF,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,QAAQ,CAAC,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;QACxF,CAAC;QACD,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,MAAM,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YAC9D,SAAS,EAAE,EAAE;SACd,CAAC;IACJ,CAAC;AACH,CAAC"}