Skip to content

Commit 909812b

Browse files
johnlindquistclaude
andcommitted
fix(pkg): whitelist published files; add site facts generator
The files whitelist keeps site/ and repo tooling out of the npm tarball (prerelease tarballs were packing the whole tree). generate-facts.ts keeps site/src/facts.json in sync with the CLI's actual surface. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 8da6266 commit 909812b

3 files changed

Lines changed: 274 additions & 1 deletion

File tree

package.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,23 @@
1111
"mdflow": "./bin/mdflow.mjs",
1212
"md": "./src/index.ts"
1313
},
14+
"files": [
15+
"bin",
16+
"src",
17+
"!src/**/*.test.ts",
18+
"assets",
19+
"skills",
20+
"docs/public-api.md",
21+
"README.md"
22+
],
1423
"scripts": {
1524
"test": "bun test --bail=1",
1625
"md": "bun run src/index.ts",
1726
"bundle": "bun run scripts/bundle.ts -o",
1827
"bundle:core": "bun run scripts/bundle.ts --core -o",
19-
"bundle:stdout": "bun run scripts/bundle.ts"
28+
"bundle:stdout": "bun run scripts/bundle.ts",
29+
"facts": "bun run scripts/generate-facts.ts",
30+
"facts:check": "bun run scripts/generate-facts.ts --check"
2031
},
2132
"devDependencies": {
2233
"@semantic-release/changelog": "^6.0.3",

scripts/generate-facts.ts

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/**
2+
* generate-facts.ts — single source of truth for the factual copy shared by
3+
* the CLI docs and the website (site/src/facts.json).
4+
*
5+
* Derivations:
6+
* - engines + default engine: the live adapter registry (src/adapters) and
7+
* DEFAULT_ENGINE (src/command.ts)
8+
* - subcommand names: scanned from src/cli-runner.ts (`subcommand === "x"`),
9+
* so a new subcommand without a description entry here FAILS the build
10+
* - version: package.json
11+
*
12+
* Usage:
13+
* bun run scripts/generate-facts.ts # write site/src/facts.json
14+
* bun run scripts/generate-facts.ts --check # exit 1 if the file is stale
15+
*/
16+
17+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
18+
import { join, dirname } from "path";
19+
import { getRegisteredAdapters } from "../src/adapters";
20+
import { DEFAULT_ENGINE } from "../src/command";
21+
22+
const ROOT = join(import.meta.dir, "..");
23+
const FACTS_PATH = join(ROOT, "site", "src", "facts.json");
24+
25+
// --- version -----------------------------------------------------------
26+
// Only the base version is embedded: semantic-release bumps the prerelease
27+
// number on every release commit, and the site badge shouldn't churn (or
28+
// fail facts:check) each time.
29+
const pkg = JSON.parse(readFileSync(join(ROOT, "package.json"), "utf-8"));
30+
const versionBase = (pkg.version as string).split("-")[0]; // 3.0.0-next.4 → 3.0.0
31+
32+
// --- engines -----------------------------------------------------------
33+
const ENGINE_LABELS: Record<string, string> = {
34+
agy: "agy (Antigravity)",
35+
};
36+
const engines = getRegisteredAdapters();
37+
const enginesLabel = engines.map((e) => ENGINE_LABELS[e] ?? e).join(", ");
38+
39+
// --- subcommands (names derived from cli-runner.ts) ---------------------
40+
const cliRunnerSource = readFileSync(join(ROOT, "src", "cli-runner.ts"), "utf-8");
41+
const discovered = new Set<string>();
42+
for (const match of cliRunnerSource.matchAll(/subcommand === "([a-z-]+)"/g)) {
43+
discovered.add(match[1]!);
44+
}
45+
discovered.add("help"); // handled as a flag in src/cli.ts
46+
47+
/** Display order + copy. Every discovered subcommand MUST appear here. */
48+
const COMMAND_DOCS: Record<string, { usage: string; description: string }> = {
49+
init: { usage: "init [--engine <e>] [-y]", description: "bootstrap a flow roster (agent-guided; -y scaffolds deterministically)" },
50+
create: { usage: "create [name] [flags]", description: "create a new flow file" },
51+
explain: { usage: "explain <flow.md>", description: "show resolved config without executing (free)" },
52+
eval: { usage: "eval <flow.md>", description: "run the flow's eval suite — costs engine turns" },
53+
complain: { usage: 'complain <flow.md> "msg"', description: "record evolution evidence (free)" },
54+
evolve: { usage: "evolve <flow.md> [--check]", description: "evidence-gated prompt evolution; --check is free" },
55+
install: { usage: "install <url|gh:org/repo/path@ref>", description: "install a flow from a registry" },
56+
remove: { usage: "remove <name>", description: "remove an installed flow" },
57+
list: { usage: "list", description: "list installed registry flows" },
58+
setup: { usage: "setup", description: "configure shell (PATH, aliases)" },
59+
logs: { usage: "logs", description: "show the flow log directory" },
60+
help: { usage: "help", description: "full built-in help" },
61+
};
62+
63+
const undocumented = [...discovered].filter((name) => !COMMAND_DOCS[name]);
64+
if (undocumented.length > 0) {
65+
console.error(
66+
`generate-facts: subcommand(s) handled in cli-runner.ts but missing from COMMAND_DOCS: ${undocumented.join(", ")}`
67+
);
68+
process.exit(1);
69+
}
70+
const stale = Object.keys(COMMAND_DOCS).filter((name) => !discovered.has(name));
71+
if (stale.length > 0) {
72+
console.error(
73+
`generate-facts: COMMAND_DOCS documents subcommand(s) no longer handled in cli-runner.ts: ${stale.join(", ")}`
74+
);
75+
process.exit(1);
76+
}
77+
const commands = Object.entries(COMMAND_DOCS).map(([name, doc]) => ({ name, ...doc }));
78+
79+
// --- static-but-centralized facts ---------------------------------------
80+
const ladder = [
81+
{ rung: "--engine flag", note: "deprecated aliases: --_command/-_c, --tool" },
82+
{ rung: "MDFLOW_ENGINE env var", note: "" },
83+
{ rung: "filename (task.claude.md)", note: "must name a real engine" },
84+
{ rung: "frontmatter engine:", note: "deprecated aliases: tool:/_tool: (they warn)" },
85+
{ rung: "config engine:", note: "project config beats ~/.mdflow/config.yaml" },
86+
{ rung: `default: ${DEFAULT_ENGINE}`, note: "implicit picks are announced on stderr" },
87+
];
88+
89+
const mdFlags = [
90+
{ flag: "--engine", description: "specify the engine to run" },
91+
{ flag: "--_dry-run", description: "preview without executing" },
92+
{ flag: "--_edit", description: "edit prompt in $EDITOR" },
93+
{ flag: "--_context", description: "show context tree" },
94+
{ flag: "--raw", description: "raw output (for piping)" },
95+
{ flag: "--json", description: "single JSON result object" },
96+
];
97+
98+
const facts = {
99+
$generated: "by scripts/generate-facts.ts — DO NOT EDIT; run `bun run facts`",
100+
versionBase,
101+
defaultEngine: DEFAULT_ENGINE,
102+
engines,
103+
enginesLabel,
104+
install: "npx mdflow init",
105+
repo: "https://github.com/johnlindquist/mdflow",
106+
ladder,
107+
commands,
108+
mdFlags,
109+
};
110+
111+
// --- write / check -------------------------------------------------------
112+
const output = JSON.stringify(facts, null, 2) + "\n";
113+
const checkMode = process.argv.includes("--check");
114+
115+
if (checkMode) {
116+
const current = existsSync(FACTS_PATH) ? readFileSync(FACTS_PATH, "utf-8") : "";
117+
if (current !== output) {
118+
console.error(
119+
"generate-facts: site/src/facts.json is stale. Run `bun run facts` and commit the result."
120+
);
121+
process.exit(1);
122+
}
123+
console.log("generate-facts: site/src/facts.json is up to date.");
124+
} else {
125+
mkdirSync(dirname(FACTS_PATH), { recursive: true });
126+
writeFileSync(FACTS_PATH, output);
127+
console.log(`generate-facts: wrote ${FACTS_PATH}`);
128+
}

site/src/facts.json

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
{
2+
"$generated": "by scripts/generate-facts.ts — DO NOT EDIT; run `bun run facts`",
3+
"version": "3.0.0-next.5",
4+
"versionBase": "3.0.0",
5+
"defaultEngine": "pi",
6+
"engines": [
7+
"claude",
8+
"copilot",
9+
"codex",
10+
"gemini",
11+
"droid",
12+
"opencode",
13+
"pi",
14+
"cursor-agent",
15+
"agy"
16+
],
17+
"enginesLabel": "claude, copilot, codex, gemini, droid, opencode, pi, cursor-agent, agy (Antigravity)",
18+
"install": "npx mdflow init",
19+
"repo": "https://github.com/johnlindquist/mdflow",
20+
"ladder": [
21+
{
22+
"rung": "--engine flag",
23+
"note": "deprecated aliases: --_command/-_c, --tool"
24+
},
25+
{
26+
"rung": "MDFLOW_ENGINE env var",
27+
"note": ""
28+
},
29+
{
30+
"rung": "filename (task.claude.md)",
31+
"note": "must name a real engine"
32+
},
33+
{
34+
"rung": "frontmatter engine:",
35+
"note": "deprecated aliases: tool:/_tool: (they warn)"
36+
},
37+
{
38+
"rung": "config engine:",
39+
"note": "project config beats ~/.mdflow/config.yaml"
40+
},
41+
{
42+
"rung": "default: pi",
43+
"note": "implicit picks are announced on stderr"
44+
}
45+
],
46+
"commands": [
47+
{
48+
"name": "init",
49+
"usage": "init [--engine <e>] [-y]",
50+
"description": "bootstrap a flow roster (agent-guided; -y scaffolds deterministically)"
51+
},
52+
{
53+
"name": "create",
54+
"usage": "create [name] [flags]",
55+
"description": "create a new flow file"
56+
},
57+
{
58+
"name": "explain",
59+
"usage": "explain <flow.md>",
60+
"description": "show resolved config without executing (free)"
61+
},
62+
{
63+
"name": "eval",
64+
"usage": "eval <flow.md>",
65+
"description": "run the flow's eval suite — costs engine turns"
66+
},
67+
{
68+
"name": "complain",
69+
"usage": "complain <flow.md> \"msg\"",
70+
"description": "record evolution evidence (free)"
71+
},
72+
{
73+
"name": "evolve",
74+
"usage": "evolve <flow.md> [--check]",
75+
"description": "evidence-gated prompt evolution; --check is free"
76+
},
77+
{
78+
"name": "install",
79+
"usage": "install <url|gh:org/repo/path@ref>",
80+
"description": "install a flow from a registry"
81+
},
82+
{
83+
"name": "remove",
84+
"usage": "remove <name>",
85+
"description": "remove an installed flow"
86+
},
87+
{
88+
"name": "list",
89+
"usage": "list",
90+
"description": "list installed registry flows"
91+
},
92+
{
93+
"name": "setup",
94+
"usage": "setup",
95+
"description": "configure shell (PATH, aliases)"
96+
},
97+
{
98+
"name": "logs",
99+
"usage": "logs",
100+
"description": "show the flow log directory"
101+
},
102+
{
103+
"name": "help",
104+
"usage": "help",
105+
"description": "full built-in help"
106+
}
107+
],
108+
"mdFlags": [
109+
{
110+
"flag": "--engine",
111+
"description": "specify the engine to run"
112+
},
113+
{
114+
"flag": "--_dry-run",
115+
"description": "preview without executing"
116+
},
117+
{
118+
"flag": "--_edit",
119+
"description": "edit prompt in $EDITOR"
120+
},
121+
{
122+
"flag": "--_context",
123+
"description": "show context tree"
124+
},
125+
{
126+
"flag": "--raw",
127+
"description": "raw output (for piping)"
128+
},
129+
{
130+
"flag": "--json",
131+
"description": "single JSON result object"
132+
}
133+
]
134+
}

0 commit comments

Comments
 (0)