@shiwenbin1617/pstack 0.14.4
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/LICENSE +28 -0
- package/README.md +332 -0
- package/adapters/claude-code/overrides/setup-pstack/SKILL.md +48 -0
- package/adapters/claude-code.md +29 -0
- package/adapters/codex/agents/comment-sicko.toml +7 -0
- package/adapters/codex/agents/poteto-agent.toml +7 -0
- package/adapters/codex/overrides/setup-pstack/SKILL.md +40 -0
- package/adapters/codex.md +34 -0
- package/agents/comment-sicko.md +32 -0
- package/agents/poteto-agent.md +9 -0
- package/automations/benny/FOR_AGENTS.md +89 -0
- package/automations/benny/README.md +23 -0
- package/automations/benny/skills/reproduce-and-fix-issues/SKILL.md +310 -0
- package/automations/benny/skills/reproduce-and-fix-issues/references/control-adapter.md +169 -0
- package/automations/benny/skills/reproduce-and-fix-issues/references/feature-map.example.md +205 -0
- package/automations/benny/skills/reproduce-and-fix-issues/references/verify-existing-fix.md +93 -0
- package/automations/benny/skills/setup-benny/SKILL.md +266 -0
- package/automations/benny/skills/triage-issue-reports/SKILL.md +240 -0
- package/automations/benny/skills/triage-issue-reports/references/routing.example.md +61 -0
- package/automations/benny/templates/configuration.example.yaml +84 -0
- package/automations/benny/templates/reproduce-automation-prompt.md +33 -0
- package/automations/benny/templates/triage-automation-prompt.md +39 -0
- package/bin/pstack.mjs +331 -0
- package/package.json +48 -0
- package/scripts/build.mjs +218 -0
- package/scripts/host-adapters.mjs +128 -0
- package/scripts/lib.mjs +181 -0
- package/scripts/test.mjs +106 -0
- package/skills/architect/SKILL.md +83 -0
- package/skills/architect/references/design-red-flags.md +33 -0
- package/skills/architect/references/rationale-template.md +35 -0
- package/skills/architect/references/runner-prompt.md +20 -0
- package/skills/arena/SKILL.md +71 -0
- package/skills/automate-me/SKILL.md +109 -0
- package/skills/blast-radius/SKILL.md +50 -0
- package/skills/bro/SKILL.md +7 -0
- package/skills/create-verification-skill/SKILL.md +44 -0
- package/skills/create-verification-skill/references/feature-map-example/README.md +47 -0
- package/skills/create-verification-skill/references/feature-map-example/create-note.md +39 -0
- package/skills/create-verification-skill/references/feature-map-example/search.md +45 -0
- package/skills/figure-it-out/SKILL.md +55 -0
- package/skills/how/SKILL.md +134 -0
- package/skills/how/references/critic-prompt.md +59 -0
- package/skills/how/references/critique-rubric.md +58 -0
- package/skills/how/references/explainer-prompt.md +55 -0
- package/skills/how/references/explorer-prompt.md +52 -0
- package/skills/interrogate/SKILL.md +113 -0
- package/skills/interrogate/references/code-quality-review.md +47 -0
- package/skills/interrogate/references/lead-judgment.md +58 -0
- package/skills/interrogate/references/reviewer-prompt.md +72 -0
- package/skills/interrogate/references/rubric.md +77 -0
- package/skills/maintain-verification-skill/SKILL.md +39 -0
- package/skills/no-comments/SKILL.md +24 -0
- package/skills/poteto-mode/SKILL.md +140 -0
- package/skills/poteto-mode/playbooks/authoring-a-skill.md +12 -0
- package/skills/poteto-mode/playbooks/autonomous-run.md +13 -0
- package/skills/poteto-mode/playbooks/autopilot-full.md +13 -0
- package/skills/poteto-mode/playbooks/autopilot-stack.md +16 -0
- package/skills/poteto-mode/playbooks/babysit.md +27 -0
- package/skills/poteto-mode/playbooks/bug-fix.md +17 -0
- package/skills/poteto-mode/playbooks/eval.md +27 -0
- package/skills/poteto-mode/playbooks/feature.md +21 -0
- package/skills/poteto-mode/playbooks/hillclimb.md +21 -0
- package/skills/poteto-mode/playbooks/investigation.md +14 -0
- package/skills/poteto-mode/playbooks/multi-phase-plan.md +155 -0
- package/skills/poteto-mode/playbooks/opening-a-pr.md +29 -0
- package/skills/poteto-mode/playbooks/orchestrate.md +113 -0
- package/skills/poteto-mode/playbooks/pause-safely.md +10 -0
- package/skills/poteto-mode/playbooks/perf-issue.md +24 -0
- package/skills/poteto-mode/playbooks/prototype.md +14 -0
- package/skills/poteto-mode/playbooks/refactoring.md +16 -0
- package/skills/poteto-mode/playbooks/runtime-forensics.md +11 -0
- package/skills/poteto-mode/playbooks/session-pickup.md +13 -0
- package/skills/poteto-mode/playbooks/shipping.md +20 -0
- package/skills/poteto-mode/playbooks/trace-forensics.md +14 -0
- package/skills/poteto-mode/playbooks/visual-parity.md +11 -0
- package/skills/poteto-mode/playbooks/worktree-cleanup.md +14 -0
- package/skills/poteto-mode/references/bugbot-triage.md +142 -0
- package/skills/poteto-mode/scripts/bootstrap.ts +30 -0
- package/skills/poteto-mode/scripts/bun.lock +67 -0
- package/skills/poteto-mode/scripts/check-plan.mjs +186 -0
- package/skills/poteto-mode/scripts/orch/orch.test.ts +634 -0
- package/skills/poteto-mode/scripts/orch/orch.ts +578 -0
- package/skills/poteto-mode/scripts/orch/store.ts +1607 -0
- package/skills/poteto-mode/scripts/package.json +16 -0
- package/skills/poteto-mode/scripts/watch-pr/cli.test.ts +224 -0
- package/skills/poteto-mode/scripts/watch-pr/cli.ts +223 -0
- package/skills/poteto-mode/scripts/watch-pr/fakes.test-helper.ts +118 -0
- package/skills/poteto-mode/scripts/watch-pr/github.test.ts +306 -0
- package/skills/poteto-mode/scripts/watch-pr/github.ts +699 -0
- package/skills/poteto-mode/scripts/watch-pr/policy.test.ts +420 -0
- package/skills/poteto-mode/scripts/watch-pr/policy.ts +832 -0
- package/skills/poteto-mode/scripts/watch-pr/render.ts +169 -0
- package/skills/poteto-mode/scripts/watch-pr/tsconfig.json +13 -0
- package/skills/poteto-mode/scripts/watch-pr/types.compile.ts +93 -0
- package/skills/poteto-mode/scripts/watch-pr/types.ts +401 -0
- package/skills/poteto-mode/scripts/watch-pr/watch-pr +6 -0
- package/skills/poteto-mode/scripts/worktree-audit.sh +89 -0
- package/skills/principle-boundary-discipline/SKILL.md +34 -0
- package/skills/principle-build-the-lever/SKILL.md +23 -0
- package/skills/principle-encode-lessons-in-structure/SKILL.md +31 -0
- package/skills/principle-exhaust-the-design-space/SKILL.md +21 -0
- package/skills/principle-experience-first/SKILL.md +19 -0
- package/skills/principle-fix-root-causes/SKILL.md +23 -0
- package/skills/principle-foundational-thinking/SKILL.md +21 -0
- package/skills/principle-guard-the-context-window/SKILL.md +17 -0
- package/skills/principle-laziness-protocol/SKILL.md +18 -0
- package/skills/principle-make-operations-idempotent/SKILL.md +24 -0
- package/skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md +22 -0
- package/skills/principle-minimize-reader-load/SKILL.md +23 -0
- package/skills/principle-model-the-domain/SKILL.md +26 -0
- package/skills/principle-never-block-on-the-human/SKILL.md +23 -0
- package/skills/principle-outcome-oriented-execution/SKILL.md +22 -0
- package/skills/principle-prove-it-works/SKILL.md +33 -0
- package/skills/principle-redesign-from-first-principles/SKILL.md +16 -0
- package/skills/principle-separate-before-serializing-shared-state/SKILL.md +16 -0
- package/skills/principle-sequence-verifiable-units/SKILL.md +22 -0
- package/skills/principle-subtract-before-you-add/SKILL.md +22 -0
- package/skills/principle-type-system-discipline/SKILL.md +31 -0
- package/skills/recall/SKILL.md +35 -0
- package/skills/reflect/SKILL.md +77 -0
- package/skills/reflect/references/divergent-reviewer.md +43 -0
- package/skills/reflect/references/judgment-reviewer.md +42 -0
- package/skills/reflect/references/synthesizer.md +56 -0
- package/skills/reflect/references/tooling-reviewer.md +57 -0
- package/skills/setup-pstack/SKILL.md +106 -0
- package/skills/show-me-your-work/SKILL.md +82 -0
- package/skills/show-me-your-work/references/decision-log-template.tsv +1 -0
- package/skills/show-me-your-work/scripts/log.sh +40 -0
- package/skills/swarm/SKILL.md +46 -0
- package/skills/tdd/SKILL.md +44 -0
- package/skills/teach/SKILL.md +21 -0
- package/skills/technical-writing/SKILL.md +130 -0
- package/skills/typescript-best-practices/SKILL.md +28 -0
- package/skills/typescript-best-practices/references/patterns.md +292 -0
- package/skills/unslop/SKILL.md +80 -0
- package/skills/why/SKILL.md +229 -0
- package/skills/why/references/epistemics.md +144 -0
- package/skills/why/references/investigator-prompt.md +103 -0
- package/skills/why/references/source-playbook.md +17 -0
- package/skills/why/references/sources/code-archaeology.md +88 -0
- package/skills/why/references/sources/databricks.md +70 -0
- package/skills/why/references/sources/datadog.md +99 -0
- package/skills/why/references/sources/incident-postmortem.md +15 -0
- package/skills/why/references/sources/linear.md +48 -0
- package/skills/why/references/sources/notion.md +55 -0
- package/skills/why/references/sources/sentry.md +100 -0
- package/skills/why/references/sources/slack.md +54 -0
- package/skills/why/references/synthesizer-prompt.md +135 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
|
|
5
|
+
const RULE =
|
|
6
|
+
"Tests alone are not sufficient verification. A PR is verified only when its unit, live, and perf boxes are all checked.";
|
|
7
|
+
const LANES = "Ten lanes on your fast code model at the PR head";
|
|
8
|
+
const SUB_BLOCKS = [
|
|
9
|
+
"Depends on.",
|
|
10
|
+
"Files.",
|
|
11
|
+
"Build.",
|
|
12
|
+
"You see.",
|
|
13
|
+
"Verify, unit.",
|
|
14
|
+
"Verify, live.",
|
|
15
|
+
"Verify, perf.",
|
|
16
|
+
"Review gate.",
|
|
17
|
+
"Merge.",
|
|
18
|
+
];
|
|
19
|
+
const PROGRAM_H3 = ["Arm the program", "Spawn owners", "PR mechanics", "Verdict and merge", "Boot recipe"];
|
|
20
|
+
const PROGRAM_MARKERS = ["/goal", "Read the installed", /30[- ]minute/, "status message"];
|
|
21
|
+
const HOW_TO_READ_MARKERS = [
|
|
22
|
+
"One box is one unit of work",
|
|
23
|
+
"names the evidence",
|
|
24
|
+
"Check a box only when its evidence exists",
|
|
25
|
+
"playbooks/",
|
|
26
|
+
RULE,
|
|
27
|
+
];
|
|
28
|
+
const PERF_ITEMS = ["Metric.", "Probe.", "Baseline.", "Rule."];
|
|
29
|
+
const BOX = /^\s*- \[[ x]\] (.*)$/;
|
|
30
|
+
|
|
31
|
+
const file = process.argv[2];
|
|
32
|
+
if (!file) {
|
|
33
|
+
console.error("Usage: node check-plan.mjs <plan.md>");
|
|
34
|
+
process.exit(2);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const raw = fs.readFileSync(file, "utf8").split(/\r?\n/);
|
|
38
|
+
const problems = [];
|
|
39
|
+
const fail = (line, message) => problems.push(`${file}:${line}: ${message}`);
|
|
40
|
+
|
|
41
|
+
let start = 0;
|
|
42
|
+
if (raw[0] === "---") {
|
|
43
|
+
start = raw.indexOf("---", 1) + 1;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const lines = [];
|
|
47
|
+
let fence = false;
|
|
48
|
+
for (let i = start; i < raw.length; i++) {
|
|
49
|
+
const text = raw[i];
|
|
50
|
+
const n = i + 1;
|
|
51
|
+
if (/^```/.test(text)) fence = !fence;
|
|
52
|
+
lines.push({ n, text, code: fence });
|
|
53
|
+
if (fence) continue;
|
|
54
|
+
const prose = text
|
|
55
|
+
.replace(/`[^`]*`/g, "`")
|
|
56
|
+
.replace(/!\[[^\]]*\]\([^)]*\)/g, "")
|
|
57
|
+
.replace(/\]\([^)]*\)/g, "]");
|
|
58
|
+
if (/[\u2013\u2014]/.test(prose)) fail(n, "long dash");
|
|
59
|
+
if (/[\u2018\u2019\u201c\u201d]/.test(prose)) fail(n, "curly quote");
|
|
60
|
+
if (/: \S/.test(prose)) fail(n, "mid-sentence colon");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const h2 = (l) => (!l.code && l.text.startsWith("## ") ? l.text.slice(3).trim() : null);
|
|
64
|
+
const sections = [];
|
|
65
|
+
for (const l of lines) {
|
|
66
|
+
const title = h2(l);
|
|
67
|
+
if (title !== null) sections.push({ title, n: l.n, body: [] });
|
|
68
|
+
else if (sections.length) sections.at(-1).body.push(l);
|
|
69
|
+
}
|
|
70
|
+
const find = (title) => sections.find((s) => s.title === title);
|
|
71
|
+
const bodyText = (s) => s.body.map((l) => l.text).join("\n");
|
|
72
|
+
const boxes = (ls) => ls.filter((l) => !l.code && BOX.test(l.text)).map((l) => ({ n: l.n, text: l.text.match(BOX)[1] }));
|
|
73
|
+
|
|
74
|
+
const h1 = lines.findIndex((l) => !l.code && l.text.startsWith("# "));
|
|
75
|
+
if (h1 === -1) fail(1, "no H1 title");
|
|
76
|
+
const howToRead = find("How to read this");
|
|
77
|
+
if (!howToRead) fail(1, 'no "## How to read this" section');
|
|
78
|
+
if (h1 !== -1 && howToRead) {
|
|
79
|
+
const intro = lines.slice(h1 + 1).filter((l) => l.n < howToRead.n && l.text.trim() !== "");
|
|
80
|
+
if (intro.length >= 10) fail(lines[h1].n, `intro is ${intro.length} lines, under ten required`);
|
|
81
|
+
for (const marker of HOW_TO_READ_MARKERS) {
|
|
82
|
+
if (!bodyText(howToRead).includes(marker)) fail(howToRead.n, `How to read this lacks "${marker}"`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const program = find("Program checklist");
|
|
87
|
+
if (!program) fail(1, 'no "## Program checklist" section');
|
|
88
|
+
else {
|
|
89
|
+
const h3s = program.body.filter((l) => !l.code && l.text.startsWith("### ")).map((l) => l.text.slice(4).trim());
|
|
90
|
+
let cursor = 0;
|
|
91
|
+
for (const name of PROGRAM_H3) {
|
|
92
|
+
const at = h3s.findIndex((t, i) => i >= cursor && t.startsWith(name));
|
|
93
|
+
if (at === -1) fail(program.n, `Program checklist lacks "### ${name}" in order`);
|
|
94
|
+
else cursor = at + 1;
|
|
95
|
+
}
|
|
96
|
+
for (const marker of PROGRAM_MARKERS) {
|
|
97
|
+
const ok = marker instanceof RegExp ? marker.test(bodyText(program)) : bodyText(program).includes(marker);
|
|
98
|
+
if (!ok) fail(program.n, `Program checklist lacks "${marker}"`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const close = find("Close the program");
|
|
103
|
+
if (!close) fail(1, 'no "## Close the program" section');
|
|
104
|
+
const programIndex = sections.indexOf(program);
|
|
105
|
+
const closeIndex = sections.indexOf(close);
|
|
106
|
+
const prSections = programIndex === -1 || closeIndex === -1 ? [] : sections.slice(programIndex + 1, closeIndex);
|
|
107
|
+
if (prSections.length === 0) fail(1, "no PR sections between Program checklist and Close the program");
|
|
108
|
+
|
|
109
|
+
const report = [];
|
|
110
|
+
for (const pr of prSections) {
|
|
111
|
+
const heads = [];
|
|
112
|
+
for (const l of pr.body) {
|
|
113
|
+
if (l.code) continue;
|
|
114
|
+
const m = l.text.match(/^\*\*([^*]+)\*\*(.*)$/);
|
|
115
|
+
if (m && SUB_BLOCKS.includes(m[1])) heads.push({ name: m[1], n: l.n, rest: m[2].trim(), lines: [] });
|
|
116
|
+
else if (heads.length) heads.at(-1).lines.push(l);
|
|
117
|
+
}
|
|
118
|
+
const names = heads.map((h) => h.name);
|
|
119
|
+
if (names.join("|") !== SUB_BLOCKS.join("|")) {
|
|
120
|
+
fail(pr.n, `${pr.title}: sub-blocks are [${names.join(", ")}], expected [${SUB_BLOCKS.join(", ")}]`);
|
|
121
|
+
}
|
|
122
|
+
const block = (name) => heads.find((h) => h.name === name);
|
|
123
|
+
const counts = {};
|
|
124
|
+
for (const h of heads) counts[h.name] = boxes(h.lines).length;
|
|
125
|
+
|
|
126
|
+
const depends = block("Depends on.");
|
|
127
|
+
if (depends && depends.rest === "") fail(depends.n, `${pr.title}: Depends on names nothing`);
|
|
128
|
+
for (const name of ["Files.", "Build.", "You see.", "Verify, unit.", "Merge."]) {
|
|
129
|
+
const b = block(name);
|
|
130
|
+
if (b && boxes(b.lines).length === 0) fail(b.n, `${pr.title}: ${name} has no box`);
|
|
131
|
+
}
|
|
132
|
+
for (const name of ["Verify, unit.", "Verify, live.", "Verify, perf."]) {
|
|
133
|
+
const b = block(name);
|
|
134
|
+
if (b && !b.rest.startsWith(RULE)) fail(b.n, `${pr.title}: ${name} does not open with the rule`);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const live = block("Verify, live.");
|
|
138
|
+
if (live) {
|
|
139
|
+
if (!live.rest.includes(LANES)) fail(live.n, `${pr.title}: Verify, live lacks "${LANES}"`);
|
|
140
|
+
const lanes = boxes(live.lines).map((b) => ({ ...b, m: b.text.match(/^Lane (\d+)\. /) }));
|
|
141
|
+
const numbers = lanes.filter((b) => b.m).map((b) => Number(b.m[1])).sort((a, b) => a - b);
|
|
142
|
+
if (numbers.join(",") !== "1,2,3,4,5,6,7,8,9,10") fail(live.n, `${pr.title}: lanes are [${numbers.join(",")}], expected 1 to 10`);
|
|
143
|
+
for (const lane of lanes) {
|
|
144
|
+
if (!lane.m) fail(lane.n, `${pr.title}: live box is not a lane`);
|
|
145
|
+
else if (!/Save `[^`]+`/.test(lane.text)) fail(lane.n, `${pr.title}: lane ${lane.m[1]} names no screenshot`);
|
|
146
|
+
else if (!lane.text.includes("Pass when")) fail(lane.n, `${pr.title}: lane ${lane.m[1]} has no pass predicate`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const perf = block("Verify, perf.");
|
|
151
|
+
if (perf) {
|
|
152
|
+
const items = boxes(perf.lines).map((b) => b.text.split(" ")[0]);
|
|
153
|
+
if (items.join("|") !== PERF_ITEMS.join("|")) fail(perf.n, `${pr.title}: perf boxes are [${items.join(", ")}], expected [${PERF_ITEMS.join(", ")}]`);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const gate = block("Review gate.");
|
|
157
|
+
if (gate) {
|
|
158
|
+
const gateBoxes = boxes(gate.lines);
|
|
159
|
+
if (gate.rest.startsWith("None.")) {
|
|
160
|
+
if (gateBoxes.length) fail(gate.n, `${pr.title}: Review gate says None but has boxes`);
|
|
161
|
+
} else {
|
|
162
|
+
const text = gate.lines.map((l) => l.text).join("\n");
|
|
163
|
+
if (gateBoxes.length === 0) fail(gate.n, `${pr.title}: Review gate has no box`);
|
|
164
|
+
for (const word of ["screenshot", "video", "operator"]) {
|
|
165
|
+
if (!text.includes(word)) fail(gate.n, `${pr.title}: Review gate lacks "${word}"`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const total = boxes(pr.body).length;
|
|
171
|
+
const cells = SUB_BLOCKS.filter((s) => s !== "Depends on.").map((s) => `${s.replace(/[ ,.]+/g, "-").replace(/-$/, "").toLowerCase()}=${counts[s] ?? 0}`);
|
|
172
|
+
report.push(`${pr.title} boxes=${total} ${cells.join(" ")}`);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (closeIndex !== -1) {
|
|
176
|
+
const tail = sections.slice(closeIndex + 1);
|
|
177
|
+
for (const s of tail) {
|
|
178
|
+
if (!s.title.startsWith("Appendix")) fail(s.n, `"## ${s.title}" after Close the program is not an appendix`);
|
|
179
|
+
}
|
|
180
|
+
if (!tail.some((s) => s.title.includes("Prototype evidence"))) fail(close.n, 'no "## Appendix ... Prototype evidence" section');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
for (const line of report) console.log(line);
|
|
184
|
+
console.log(`${prSections.length} PR sections, ${problems.length} problems`);
|
|
185
|
+
for (const p of problems) console.error(p);
|
|
186
|
+
process.exit(problems.length ? 1 : 0);
|