@zenspc/pi-pstack 0.1.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 (128) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +49 -0
  3. package/agents/comment-sicko.md +34 -0
  4. package/agents/poteto-agent.md +13 -0
  5. package/extensions/pstack/config.ts +228 -0
  6. package/extensions/pstack/index.ts +211 -0
  7. package/package.json +57 -0
  8. package/skills/architect/SKILL.md +82 -0
  9. package/skills/architect/references/design-red-flags.md +33 -0
  10. package/skills/architect/references/rationale-template.md +35 -0
  11. package/skills/architect/references/runner-prompt.md +20 -0
  12. package/skills/arena/SKILL.md +70 -0
  13. package/skills/automate-me/SKILL.md +114 -0
  14. package/skills/blast-radius/SKILL.md +49 -0
  15. package/skills/bro/SKILL.md +6 -0
  16. package/skills/create-verification-skill/SKILL.md +43 -0
  17. package/skills/create-verification-skill/references/feature-map-example/README.md +47 -0
  18. package/skills/create-verification-skill/references/feature-map-example/create-note.md +39 -0
  19. package/skills/create-verification-skill/references/feature-map-example/search.md +45 -0
  20. package/skills/figure-it-out/SKILL.md +54 -0
  21. package/skills/how/SKILL.md +134 -0
  22. package/skills/how/references/critic-prompt.md +59 -0
  23. package/skills/how/references/critique-rubric.md +58 -0
  24. package/skills/how/references/explainer-prompt.md +55 -0
  25. package/skills/how/references/explorer-prompt.md +52 -0
  26. package/skills/interrogate/SKILL.md +109 -0
  27. package/skills/interrogate/references/code-quality-review.md +47 -0
  28. package/skills/interrogate/references/lead-judgment.md +58 -0
  29. package/skills/interrogate/references/reviewer-prompt.md +72 -0
  30. package/skills/interrogate/references/rubric.md +77 -0
  31. package/skills/maintain-verification-skill/SKILL.md +38 -0
  32. package/skills/no-comments/SKILL.md +23 -0
  33. package/skills/poteto-mode/SKILL.md +140 -0
  34. package/skills/poteto-mode/playbooks/authoring-a-skill.md +12 -0
  35. package/skills/poteto-mode/playbooks/autonomous-run.md +13 -0
  36. package/skills/poteto-mode/playbooks/autopilot-full.md +13 -0
  37. package/skills/poteto-mode/playbooks/autopilot-stack.md +31 -0
  38. package/skills/poteto-mode/playbooks/babysit.md +27 -0
  39. package/skills/poteto-mode/playbooks/bug-fix.md +17 -0
  40. package/skills/poteto-mode/playbooks/eval.md +27 -0
  41. package/skills/poteto-mode/playbooks/feature.md +21 -0
  42. package/skills/poteto-mode/playbooks/hillclimb.md +21 -0
  43. package/skills/poteto-mode/playbooks/investigation.md +14 -0
  44. package/skills/poteto-mode/playbooks/multi-phase-plan.md +3 -0
  45. package/skills/poteto-mode/playbooks/opening-a-pr.md +35 -0
  46. package/skills/poteto-mode/playbooks/orchestrate.md +113 -0
  47. package/skills/poteto-mode/playbooks/pause-safely.md +10 -0
  48. package/skills/poteto-mode/playbooks/perf-issue.md +24 -0
  49. package/skills/poteto-mode/playbooks/prototype.md +14 -0
  50. package/skills/poteto-mode/playbooks/refactoring.md +16 -0
  51. package/skills/poteto-mode/playbooks/runtime-forensics.md +11 -0
  52. package/skills/poteto-mode/playbooks/session-pickup.md +13 -0
  53. package/skills/poteto-mode/playbooks/shipping.md +40 -0
  54. package/skills/poteto-mode/playbooks/trace-forensics.md +14 -0
  55. package/skills/poteto-mode/playbooks/visual-parity.md +11 -0
  56. package/skills/poteto-mode/playbooks/worktree-cleanup.md +14 -0
  57. package/skills/poteto-mode/references/bugbot-triage.md +142 -0
  58. package/skills/poteto-mode/references/plan.md +105 -0
  59. package/skills/poteto-mode/scripts/bootstrap.ts +62 -0
  60. package/skills/poteto-mode/scripts/bun.lock +67 -0
  61. package/skills/poteto-mode/scripts/orch/orch.test.ts +634 -0
  62. package/skills/poteto-mode/scripts/orch/orch.ts +578 -0
  63. package/skills/poteto-mode/scripts/orch/store.ts +1607 -0
  64. package/skills/poteto-mode/scripts/package.json +16 -0
  65. package/skills/poteto-mode/scripts/watch-pr/cli.test.ts +224 -0
  66. package/skills/poteto-mode/scripts/watch-pr/cli.ts +223 -0
  67. package/skills/poteto-mode/scripts/watch-pr/fakes.test-helper.ts +118 -0
  68. package/skills/poteto-mode/scripts/watch-pr/github.test.ts +306 -0
  69. package/skills/poteto-mode/scripts/watch-pr/github.ts +699 -0
  70. package/skills/poteto-mode/scripts/watch-pr/policy.test.ts +420 -0
  71. package/skills/poteto-mode/scripts/watch-pr/policy.ts +832 -0
  72. package/skills/poteto-mode/scripts/watch-pr/render.ts +169 -0
  73. package/skills/poteto-mode/scripts/watch-pr/tsconfig.json +13 -0
  74. package/skills/poteto-mode/scripts/watch-pr/types.compile.ts +93 -0
  75. package/skills/poteto-mode/scripts/watch-pr/types.ts +401 -0
  76. package/skills/poteto-mode/scripts/watch-pr/watch-pr +6 -0
  77. package/skills/poteto-mode/scripts/worktree-audit.sh +85 -0
  78. package/skills/principle-boundary-discipline/SKILL.md +33 -0
  79. package/skills/principle-build-the-lever/SKILL.md +22 -0
  80. package/skills/principle-encode-lessons-in-structure/SKILL.md +30 -0
  81. package/skills/principle-exhaust-the-design-space/SKILL.md +20 -0
  82. package/skills/principle-experience-first/SKILL.md +18 -0
  83. package/skills/principle-fix-root-causes/SKILL.md +22 -0
  84. package/skills/principle-foundational-thinking/SKILL.md +20 -0
  85. package/skills/principle-guard-the-context-window/SKILL.md +16 -0
  86. package/skills/principle-laziness-protocol/SKILL.md +17 -0
  87. package/skills/principle-make-operations-idempotent/SKILL.md +23 -0
  88. package/skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md +21 -0
  89. package/skills/principle-minimize-reader-load/SKILL.md +22 -0
  90. package/skills/principle-model-the-domain/SKILL.md +25 -0
  91. package/skills/principle-never-block-on-the-human/SKILL.md +22 -0
  92. package/skills/principle-outcome-oriented-execution/SKILL.md +21 -0
  93. package/skills/principle-prove-it-works/SKILL.md +32 -0
  94. package/skills/principle-redesign-from-first-principles/SKILL.md +15 -0
  95. package/skills/principle-separate-before-serializing-shared-state/SKILL.md +15 -0
  96. package/skills/principle-sequence-verifiable-units/SKILL.md +21 -0
  97. package/skills/principle-subtract-before-you-add/SKILL.md +21 -0
  98. package/skills/principle-type-system-discipline/SKILL.md +30 -0
  99. package/skills/recall/SKILL.md +40 -0
  100. package/skills/reflect/SKILL.md +77 -0
  101. package/skills/reflect/references/divergent-reviewer.md +43 -0
  102. package/skills/reflect/references/judgment-reviewer.md +42 -0
  103. package/skills/reflect/references/synthesizer.md +56 -0
  104. package/skills/reflect/references/tooling-reviewer.md +57 -0
  105. package/skills/setup-pstack/SKILL.md +28 -0
  106. package/skills/show-me-your-work/SKILL.md +89 -0
  107. package/skills/show-me-your-work/references/decision-log-template.tsv +1 -0
  108. package/skills/show-me-your-work/scripts/log.sh +40 -0
  109. package/skills/swarm/SKILL.md +45 -0
  110. package/skills/tdd/SKILL.md +43 -0
  111. package/skills/teach/SKILL.md +20 -0
  112. package/skills/technical-writing/SKILL.md +129 -0
  113. package/skills/typescript-best-practices/SKILL.md +28 -0
  114. package/skills/typescript-best-practices/references/patterns.md +292 -0
  115. package/skills/unslop/SKILL.md +80 -0
  116. package/skills/why/SKILL.md +229 -0
  117. package/skills/why/references/epistemics.md +144 -0
  118. package/skills/why/references/investigator-prompt.md +103 -0
  119. package/skills/why/references/source-playbook.md +17 -0
  120. package/skills/why/references/sources/code-archaeology.md +88 -0
  121. package/skills/why/references/sources/databricks.md +70 -0
  122. package/skills/why/references/sources/datadog.md +99 -0
  123. package/skills/why/references/sources/incident-postmortem.md +15 -0
  124. package/skills/why/references/sources/linear.md +48 -0
  125. package/skills/why/references/sources/notion.md +55 -0
  126. package/skills/why/references/sources/sentry.md +100 -0
  127. package/skills/why/references/sources/slack.md +54 -0
  128. package/skills/why/references/synthesizer-prompt.md +135 -0
@@ -0,0 +1,306 @@
1
+ import { describe, expect, it } from "bun:test";
2
+ import {
3
+ ChecksUnavailable,
4
+ WatcherQueryError,
5
+ mapRollupNode,
6
+ orderStack,
7
+ parsePullRequest,
8
+ parseReviewThreads,
9
+ resolveChecks,
10
+ resolveContext,
11
+ } from "./github.ts";
12
+ import {
13
+ fakeReader,
14
+ failedCheck,
15
+ passingCheck,
16
+ pendingCheck,
17
+ } from "./fakes.test-helper.ts";
18
+ import { parsePrNumber } from "./types.ts";
19
+
20
+ const context = {
21
+ owner: "owner",
22
+ repo: "repo",
23
+ number: parsePrNumber(42),
24
+ };
25
+
26
+ describe("checks fallback chain", () => {
27
+ it("uses a non-empty fast-path result without a rollup query", async () => {
28
+ const reader = fakeReader({
29
+ fastPath: { kind: "checks", checks: [passingCheck("fast")] },
30
+ });
31
+ const read = await resolveChecks(reader, context);
32
+ expect(read.source).toBe("gh-pr-checks");
33
+ expect(read.checks.map((check) => check.name)).toEqual(["fast"]);
34
+ expect(reader.calls).toEqual(["checksFastPath"]);
35
+ });
36
+
37
+ it("paginates GraphQL when the fast path is unusable", async () => {
38
+ const reader = fakeReader({
39
+ fastPath: { kind: "unusable", exitCode: 8, stderr: "" },
40
+ rollupPages: [
41
+ { checks: [passingCheck("first")], endCursor: "next" },
42
+ { checks: [failedCheck("second")], endCursor: null },
43
+ ],
44
+ });
45
+ const read = await resolveChecks(reader, context);
46
+ expect(read.source).toBe("graphql-rollup");
47
+ expect(read.checks.map((check) => check.name)).toEqual(["first", "second"]);
48
+ expect(reader.calls).toEqual([
49
+ "checksFastPath",
50
+ "checkRollupPage:null",
51
+ "checkRollupPage:next",
52
+ ]);
53
+ });
54
+
55
+ it("falls back when valid fast-path JSON represented an empty list", async () => {
56
+ const reader = fakeReader({
57
+ fastPath: { kind: "checks", checks: [] },
58
+ rollupPages: [{ checks: [pendingCheck("fallback")], endCursor: null }],
59
+ });
60
+ expect((await resolveChecks(reader, context)).checks[0].name).toBe(
61
+ "fallback"
62
+ );
63
+ expect(reader.calls).toEqual(["checksFastPath", "checkRollupPage:null"]);
64
+ });
65
+
66
+ it("fails closed when both paths are empty", async () => {
67
+ const reader = fakeReader({
68
+ fastPath: {
69
+ kind: "unusable",
70
+ exitCode: 8,
71
+ stderr: "credential cannot read checks",
72
+ },
73
+ });
74
+ await expect(resolveChecks(reader, context)).rejects.toBeInstanceOf(
75
+ ChecksUnavailable
76
+ );
77
+ expect(reader.calls).toEqual(["checksFastPath", "checkRollupPage:null"]);
78
+ });
79
+ });
80
+
81
+ describe("rollup node mapping", () => {
82
+ it("maps terminal and non-terminal CheckRun states fail closed", () => {
83
+ const cases = [
84
+ ["IN_PROGRESS", null, "pending", "PENDING"],
85
+ ["COMPLETED", "SUCCESS", "passed", "SUCCESS"],
86
+ ["COMPLETED", "NEUTRAL", "skipped", "NEUTRAL"],
87
+ ["COMPLETED", "SKIPPED", "skipped", "SKIPPED"],
88
+ ["COMPLETED", "ACTION_REQUIRED", "failed", "ACTION_REQUIRED"],
89
+ ["COMPLETED", "TIMED_OUT", "failed", "FAILURE"],
90
+ ["COMPLETED", "FUTURE_VALUE", "failed", "FAILURE"],
91
+ ] as const;
92
+ for (const [status, conclusion, kind, reportedState] of cases) {
93
+ expect(
94
+ mapRollupNode({
95
+ __typename: "CheckRun",
96
+ name: "ci",
97
+ status,
98
+ conclusion,
99
+ })
100
+ ).toMatchObject({ kind, reportedState });
101
+ }
102
+ });
103
+
104
+ it("classifies an in-progress Code Review Gate from the rollup as the gate", () => {
105
+ expect(
106
+ mapRollupNode({
107
+ __typename: "CheckRun",
108
+ name: "Code Review Gate",
109
+ status: "IN_PROGRESS",
110
+ conclusion: null,
111
+ })
112
+ ).toMatchObject({ kind: "code-review-gate" });
113
+ expect(
114
+ mapRollupNode({
115
+ __typename: "StatusContext",
116
+ context: "Code Review Gate",
117
+ state: "PENDING",
118
+ })
119
+ ).toMatchObject({ kind: "code-review-gate" });
120
+ });
121
+
122
+ it("maps StatusContext states and drops unknown typenames", () => {
123
+ expect(
124
+ mapRollupNode({
125
+ __typename: "StatusContext",
126
+ context: "ci",
127
+ state: "EXPECTED",
128
+ })
129
+ ).toMatchObject({ kind: "pending", reportedState: "PENDING" });
130
+ expect(
131
+ mapRollupNode({
132
+ __typename: "StatusContext",
133
+ context: "ci",
134
+ state: "FUTURE_VALUE",
135
+ })
136
+ ).toMatchObject({ kind: "failed", reportedState: "FUTURE_VALUE" });
137
+ expect(mapRollupNode({ __typename: "FutureNode" })).toBeNull();
138
+ });
139
+ });
140
+
141
+ describe("closed enum parsing", () => {
142
+ const rawPullRequest = {
143
+ mergeable: "MERGEABLE",
144
+ mergeStateStatus: "CLEAN",
145
+ reviewDecision: "APPROVED",
146
+ headRefOid: "head",
147
+ headRefName: "feature",
148
+ baseRefName: "main",
149
+ state: "OPEN",
150
+ mergedAt: null,
151
+ isDraft: false,
152
+ };
153
+
154
+ it("accepts mergeStateStatus CONFLICTING", () => {
155
+ expect(
156
+ parsePullRequest(
157
+ { ...rawPullRequest, mergeStateStatus: "CONFLICTING" },
158
+ context
159
+ ).mergeStateStatus
160
+ ).toBe("CONFLICTING");
161
+ });
162
+
163
+ it("reads gh's empty reviewDecision as no decision rather than a parse failure", () => {
164
+ expect(
165
+ parsePullRequest({ ...rawPullRequest, reviewDecision: "" }, context)
166
+ .reviewDecision
167
+ ).toBeNull();
168
+ });
169
+
170
+ it("still rejects an unknown reviewDecision", () => {
171
+ expect(() =>
172
+ parsePullRequest({ ...rawPullRequest, reviewDecision: "MAYBE" }, context)
173
+ ).toThrow(WatcherQueryError);
174
+ });
175
+
176
+ it("rejects unknown enum values as retryable errors carrying the raw value", () => {
177
+ try {
178
+ parsePullRequest(
179
+ { ...rawPullRequest, mergeStateStatus: "FUTURE_STATE" },
180
+ context
181
+ );
182
+ throw new Error("expected parser to throw");
183
+ } catch (error) {
184
+ expect(error).toBeInstanceOf(WatcherQueryError);
185
+ if (!(error instanceof WatcherQueryError)) throw error;
186
+ expect(error.failure).toMatchObject({
187
+ kind: "missing-key",
188
+ retryable: true,
189
+ rawValue: '"FUTURE_STATE"',
190
+ });
191
+ }
192
+ });
193
+ });
194
+
195
+ it("annotates Bugbot threads with distinct review-pass counts", () => {
196
+ const response = {
197
+ data: {
198
+ repository: {
199
+ pullRequest: {
200
+ reviewThreads: {
201
+ nodes: [
202
+ {
203
+ id: "one",
204
+ isResolved: false,
205
+ comments: {
206
+ nodes: [
207
+ {
208
+ body: "RUN_ID: run-1",
209
+ createdAt: "now",
210
+ path: "a.ts",
211
+ line: 1,
212
+ author: { login: "bugbot" },
213
+ },
214
+ ],
215
+ },
216
+ },
217
+ {
218
+ id: "two",
219
+ isResolved: false,
220
+ comments: {
221
+ nodes: [
222
+ {
223
+ body: "CURSOR_AUTOMATION_ID: run-2 severity high",
224
+ createdAt: "now",
225
+ path: null,
226
+ line: null,
227
+ author: { login: "cursor" },
228
+ },
229
+ ],
230
+ },
231
+ },
232
+ {
233
+ id: "resolved",
234
+ isResolved: true,
235
+ comments: {
236
+ nodes: [
237
+ {
238
+ body: "RUN_ID: run-3",
239
+ createdAt: "now",
240
+ path: null,
241
+ line: null,
242
+ author: { login: "bugbot" },
243
+ },
244
+ ],
245
+ },
246
+ },
247
+ ],
248
+ },
249
+ },
250
+ },
251
+ },
252
+ };
253
+ const threads = parseReviewThreads(response);
254
+ expect(threads).toHaveLength(2);
255
+ expect(threads.map((thread) => thread.isBugbot)).toEqual([true, true]);
256
+ expect(threads.map((thread) => thread.bugbotReviewPasses)).toEqual([3, 3]);
257
+ });
258
+
259
+ describe("context and stack discovery", () => {
260
+ it("returns a fully explicit context without any reader call", async () => {
261
+ const reader = fakeReader();
262
+ expect(
263
+ await resolveContext({
264
+ reader,
265
+ owner: "explicit",
266
+ repo: "repo",
267
+ pr: context.number,
268
+ })
269
+ ).toEqual({ owner: "explicit", repo: "repo", number: context.number });
270
+ expect(reader.calls).toEqual([]);
271
+ });
272
+
273
+ it("uses the local origin before currentPr for an explicit number", async () => {
274
+ const reader = fakeReader({ origin: { owner: "local", repo: "checkout" } });
275
+ expect(
276
+ await resolveContext({
277
+ reader,
278
+ owner: null,
279
+ repo: null,
280
+ pr: context.number,
281
+ })
282
+ ).toEqual({ owner: "local", repo: "checkout", number: context.number });
283
+ expect(reader.calls).toEqual(["originRepo"]);
284
+ });
285
+
286
+ it("orders the connected stack bottom-to-top", () => {
287
+ const ordered = orderStack(context, [
288
+ {
289
+ number: parsePrNumber(41),
290
+ headRefName: "base-feature",
291
+ baseRefName: "main",
292
+ },
293
+ {
294
+ number: context.number,
295
+ headRefName: "feature",
296
+ baseRefName: "base-feature",
297
+ },
298
+ {
299
+ number: parsePrNumber(43),
300
+ headRefName: "upstack",
301
+ baseRefName: "feature",
302
+ },
303
+ ]);
304
+ expect(ordered.map((item) => Number(item.number))).toEqual([41, 42, 43]);
305
+ });
306
+ });