@bastani/atomic 0.6.5 → 0.6.6-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.
Files changed (148) hide show
  1. package/.agents/skills/ado-commit/SKILL.md +2 -0
  2. package/.agents/skills/ado-create-pr/SKILL.md +2 -0
  3. package/.agents/skills/advanced-evaluation/SKILL.md +2 -0
  4. package/.agents/skills/ast-grep/SKILL.md +2 -0
  5. package/.agents/skills/bdi-mental-states/SKILL.md +2 -0
  6. package/.agents/skills/bun/SKILL.md +156 -122
  7. package/.agents/skills/context-compression/SKILL.md +2 -0
  8. package/.agents/skills/context-degradation/SKILL.md +2 -0
  9. package/.agents/skills/context-fundamentals/SKILL.md +2 -0
  10. package/.agents/skills/context-optimization/SKILL.md +2 -0
  11. package/.agents/skills/create-spec/SKILL.md +2 -0
  12. package/.agents/skills/docx/SKILL.md +2 -0
  13. package/.agents/skills/evaluation/SKILL.md +2 -0
  14. package/.agents/skills/explain-code/SKILL.md +2 -0
  15. package/.agents/skills/filesystem-context/SKILL.md +2 -0
  16. package/.agents/skills/find-skills/SKILL.md +2 -0
  17. package/.agents/skills/gh-commit/SKILL.md +2 -0
  18. package/.agents/skills/gh-create-pr/SKILL.md +2 -0
  19. package/.agents/skills/hosted-agents/SKILL.md +2 -0
  20. package/.agents/skills/impeccable/SKILL.md +117 -304
  21. package/.agents/skills/impeccable/agents/openai.yaml +4 -0
  22. package/.agents/skills/{adapt/SKILL.md → impeccable/reference/adapt.md} +2 -11
  23. package/.agents/skills/{animate/SKILL.md → impeccable/reference/animate.md} +15 -15
  24. package/.agents/skills/{audit/SKILL.md → impeccable/reference/audit.md} +8 -22
  25. package/.agents/skills/{bolder/SKILL.md → impeccable/reference/bolder.md} +9 -13
  26. package/.agents/skills/impeccable/reference/brand.md +114 -0
  27. package/.agents/skills/{clarify/SKILL.md → impeccable/reference/clarify.md} +2 -11
  28. package/.agents/skills/{colorize/SKILL.md → impeccable/reference/colorize.md} +23 -12
  29. package/.agents/skills/impeccable/reference/craft.md +152 -29
  30. package/.agents/skills/{critique/SKILL.md → impeccable/reference/critique.md} +25 -37
  31. package/.agents/skills/{delight/SKILL.md → impeccable/reference/delight.md} +9 -11
  32. package/.agents/skills/{distill/SKILL.md → impeccable/reference/distill.md} +2 -13
  33. package/.agents/skills/impeccable/reference/document.md +427 -0
  34. package/.agents/skills/impeccable/reference/extract.md +1 -1
  35. package/.agents/skills/{harden/SKILL.md → impeccable/reference/harden.md} +1 -43
  36. package/.agents/skills/{layout/SKILL.md → impeccable/reference/layout.md} +27 -11
  37. package/.agents/skills/impeccable/reference/live.md +594 -0
  38. package/.agents/skills/impeccable/reference/motion-design.md +12 -2
  39. package/.agents/skills/impeccable/reference/onboard.md +234 -0
  40. package/.agents/skills/{optimize/SKILL.md → impeccable/reference/optimize.md} +4 -12
  41. package/.agents/skills/{overdrive/SKILL.md → impeccable/reference/overdrive.md} +9 -21
  42. package/.agents/skills/{critique → impeccable}/reference/personas.md +1 -1
  43. package/.agents/skills/{polish/SKILL.md → impeccable/reference/polish.md} +31 -23
  44. package/.agents/skills/impeccable/reference/product.md +62 -0
  45. package/.agents/skills/{quieter/SKILL.md → impeccable/reference/quieter.md} +7 -11
  46. package/.agents/skills/impeccable/reference/shape.md +151 -0
  47. package/.agents/skills/impeccable/reference/teach.md +156 -0
  48. package/.agents/skills/{typeset/SKILL.md → impeccable/reference/typeset.md} +19 -11
  49. package/.agents/skills/impeccable/reference/typography.md +31 -14
  50. package/.agents/skills/impeccable/scripts/cleanup-deprecated.mjs +87 -17
  51. package/.agents/skills/impeccable/scripts/command-metadata.json +94 -0
  52. package/.agents/skills/impeccable/scripts/design-parser.mjs +820 -0
  53. package/.agents/skills/impeccable/scripts/detect-csp.mjs +198 -0
  54. package/.agents/skills/impeccable/scripts/is-generated.mjs +69 -0
  55. package/.agents/skills/impeccable/scripts/live-accept.mjs +595 -0
  56. package/.agents/skills/impeccable/scripts/live-browser.js +4781 -0
  57. package/.agents/skills/impeccable/scripts/live-inject.mjs +445 -0
  58. package/.agents/skills/impeccable/scripts/live-poll.mjs +186 -0
  59. package/.agents/skills/impeccable/scripts/live-server.mjs +694 -0
  60. package/.agents/skills/impeccable/scripts/live-wrap.mjs +571 -0
  61. package/.agents/skills/impeccable/scripts/live.mjs +247 -0
  62. package/.agents/skills/impeccable/scripts/load-context.mjs +141 -0
  63. package/.agents/skills/impeccable/scripts/modern-screenshot.umd.js +14 -0
  64. package/.agents/skills/impeccable/scripts/pin.mjs +214 -0
  65. package/.agents/skills/init/SKILL.md +2 -0
  66. package/.agents/skills/liteparse/SKILL.md +1 -0
  67. package/.agents/skills/memory-systems/SKILL.md +2 -0
  68. package/.agents/skills/multi-agent-patterns/SKILL.md +2 -0
  69. package/.agents/skills/opentui/SKILL.md +1 -0
  70. package/.agents/skills/pdf/SKILL.md +2 -0
  71. package/.agents/skills/playwright-cli/SKILL.md +51 -5
  72. package/.agents/skills/playwright-cli/references/playwright-tests.md +1 -1
  73. package/.agents/skills/playwright-cli/references/running-code.md +10 -0
  74. package/.agents/skills/playwright-cli/references/session-management.md +56 -0
  75. package/.agents/skills/playwright-cli/references/spec-driven-testing.md +305 -0
  76. package/.agents/skills/playwright-cli/references/test-generation.md +49 -3
  77. package/.agents/skills/pptx/SKILL.md +2 -0
  78. package/.agents/skills/project-development/SKILL.md +2 -0
  79. package/.agents/skills/prompt-engineer/SKILL.md +2 -0
  80. package/.agents/skills/research-codebase/SKILL.md +2 -0
  81. package/.agents/skills/ripgrep/SKILL.md +2 -0
  82. package/.agents/skills/skill-creator/LICENSE.txt +1 -1
  83. package/.agents/skills/skill-creator/SKILL.md +2 -0
  84. package/.agents/skills/sl-commit/SKILL.md +2 -0
  85. package/.agents/skills/sl-submit-diff/SKILL.md +2 -0
  86. package/.agents/skills/tdd/SKILL.md +4 -0
  87. package/.agents/skills/tool-design/SKILL.md +2 -0
  88. package/.agents/skills/typescript-advanced-types/SKILL.md +2 -1
  89. package/.agents/skills/typescript-expert/SKILL.md +7 -1
  90. package/.agents/skills/typescript-react-reviewer/SKILL.md +2 -1
  91. package/.agents/skills/workflow-creator/SKILL.md +75 -72
  92. package/.agents/skills/workflow-creator/references/session-config.md +48 -1
  93. package/.agents/skills/xlsx/SKILL.md +2 -0
  94. package/.opencode/opencode.json +6 -2
  95. package/README.md +39 -38
  96. package/dist/lib/atomic-temp.d.ts +8 -0
  97. package/dist/lib/atomic-temp.d.ts.map +1 -0
  98. package/dist/lib/terminal-env.d.ts +9 -0
  99. package/dist/lib/terminal-env.d.ts.map +1 -0
  100. package/dist/sdk/providers/claude.d.ts.map +1 -1
  101. package/dist/sdk/providers/copilot.d.ts +24 -14
  102. package/dist/sdk/providers/copilot.d.ts.map +1 -1
  103. package/dist/sdk/runtime/executor.d.ts +8 -0
  104. package/dist/sdk/runtime/executor.d.ts.map +1 -1
  105. package/dist/sdk/runtime/port-discovery.d.ts +71 -0
  106. package/dist/sdk/runtime/port-discovery.d.ts.map +1 -0
  107. package/dist/sdk/runtime/tmux.d.ts +10 -0
  108. package/dist/sdk/runtime/tmux.d.ts.map +1 -1
  109. package/dist/sdk/types.d.ts +1 -0
  110. package/dist/sdk/types.d.ts.map +1 -1
  111. package/dist/sdk/workflows/builtin/deep-research-codebase/opencode/index.d.ts.map +1 -1
  112. package/dist/sdk/workflows/builtin/open-claude-design/opencode/index.d.ts.map +1 -1
  113. package/dist/sdk/workflows/builtin/ralph/claude/index.d.ts.map +1 -1
  114. package/dist/sdk/workflows/builtin/ralph/copilot/index.d.ts.map +1 -1
  115. package/dist/sdk/workflows/builtin/ralph/helpers/prompts.d.ts +15 -0
  116. package/dist/sdk/workflows/builtin/ralph/helpers/prompts.d.ts.map +1 -1
  117. package/dist/sdk/workflows/builtin/ralph/opencode/index.d.ts.map +1 -1
  118. package/package.json +10 -10
  119. package/src/commands/cli/chat/index.test.ts +194 -2
  120. package/src/commands/cli/chat/index.ts +83 -28
  121. package/src/lib/atomic-temp.test.ts +86 -0
  122. package/src/lib/atomic-temp.ts +62 -0
  123. package/src/lib/terminal-env.test.ts +343 -0
  124. package/src/lib/terminal-env.ts +100 -0
  125. package/src/scripts/clean-dist.test.ts +53 -0
  126. package/src/scripts/clean-dist.ts +37 -0
  127. package/src/sdk/providers/claude.ts +42 -20
  128. package/src/sdk/providers/copilot.test.ts +365 -0
  129. package/src/sdk/providers/copilot.ts +117 -15
  130. package/src/sdk/runtime/cc-debounce.ts +2 -2
  131. package/src/sdk/runtime/executor.test.ts +322 -1
  132. package/src/sdk/runtime/executor.ts +159 -96
  133. package/src/sdk/runtime/port-discovery.test.ts +573 -0
  134. package/src/sdk/runtime/port-discovery.ts +496 -0
  135. package/src/sdk/runtime/tmux.ts +22 -2
  136. package/src/sdk/types.ts +1 -0
  137. package/src/sdk/workflows/builtin/deep-research-codebase/opencode/index.ts +24 -6
  138. package/src/sdk/workflows/builtin/open-claude-design/opencode/index.ts +52 -13
  139. package/src/sdk/workflows/builtin/ralph/claude/index.ts +31 -3
  140. package/src/sdk/workflows/builtin/ralph/copilot/index.ts +16 -0
  141. package/src/sdk/workflows/builtin/ralph/helpers/prompts.ts +70 -3
  142. package/src/sdk/workflows/builtin/ralph/opencode/index.ts +50 -6
  143. package/src/services/system/auth.test.ts +53 -0
  144. package/src/services/system/auth.ts +31 -28
  145. package/src/services/system/detect.ts +1 -1
  146. package/.agents/skills/shape/SKILL.md +0 -96
  147. /package/.agents/skills/{critique → impeccable}/reference/cognitive-load.md +0 -0
  148. /package/.agents/skills/{critique → impeccable}/reference/heuristics-scoring.md +0 -0
@@ -151,7 +151,10 @@ export default defineWorkflow({
151
151
  description: "Locate design files and tokens",
152
152
  },
153
153
  {},
154
- { title: "ds-locator" },
154
+ {
155
+ title: "ds-locator",
156
+ permission: [{ permission: "*", pattern: "*", action: "allow" }],
157
+ },
155
158
  async (s) => {
156
159
  const result = await s.client.session.prompt({
157
160
  sessionID: s.session.id,
@@ -171,7 +174,10 @@ export default defineWorkflow({
171
174
  description: "Analyze design tokens and patterns",
172
175
  },
173
176
  {},
174
- { title: "ds-analyzer" },
177
+ {
178
+ title: "ds-analyzer",
179
+ permission: [{ permission: "*", pattern: "*", action: "allow" }],
180
+ },
175
181
  async (s) => {
176
182
  const result = await s.client.session.prompt({
177
183
  sessionID: s.session.id,
@@ -191,7 +197,10 @@ export default defineWorkflow({
191
197
  description: "Find existing design patterns",
192
198
  },
193
199
  {},
194
- { title: "ds-patterns" },
200
+ {
201
+ title: "ds-patterns",
202
+ permission: [{ permission: "*", pattern: "*", action: "allow" }],
203
+ },
195
204
  async (s) => {
196
205
  const result = await s.client.session.prompt({
197
206
  sessionID: s.session.id,
@@ -214,7 +223,10 @@ export default defineWorkflow({
214
223
  description: "Build design system with user approval (HIL)",
215
224
  },
216
225
  {},
217
- { title: "design-system-builder" },
226
+ {
227
+ title: "design-system-builder",
228
+ permission: [{ permission: "*", pattern: "*", action: "allow" }],
229
+ },
218
230
  async (s) => {
219
231
  const result = await s.client.session.prompt({
220
232
  sessionID: s.session.id,
@@ -253,7 +265,10 @@ export default defineWorkflow({
253
265
  description: "Capture web reference via playwright",
254
266
  },
255
267
  {},
256
- { title: "web-capture" },
268
+ {
269
+ title: "web-capture",
270
+ permission: [{ permission: "*", pattern: "*", action: "allow" }],
271
+ },
257
272
  async (s) => {
258
273
  const result = await s.client.session.prompt({
259
274
  sessionID: s.session.id,
@@ -283,7 +298,10 @@ export default defineWorkflow({
283
298
  description: "Parse reference document",
284
299
  },
285
300
  {},
286
- { title: "file-parser" },
301
+ {
302
+ title: "file-parser",
303
+ permission: [{ permission: "*", pattern: "*", action: "allow" }],
304
+ },
287
305
  async (s) => {
288
306
  const result = await s.client.session.prompt({
289
307
  sessionID: s.session.id,
@@ -317,7 +335,10 @@ export default defineWorkflow({
317
335
  await ctx.stage(
318
336
  { name: "generator", description: "Generate first design version" },
319
337
  {},
320
- { title: "generator" },
338
+ {
339
+ title: "generator",
340
+ permission: [{ permission: "*", pattern: "*", action: "allow" }],
341
+ },
321
342
  async (s) => {
322
343
  const result = await s.client.session.prompt({
323
344
  sessionID: s.session.id,
@@ -351,7 +372,10 @@ export default defineWorkflow({
351
372
  description: `Collect refinement feedback (iteration ${iteration})`,
352
373
  },
353
374
  {},
354
- { title: `user-feedback-${iteration}` },
375
+ {
376
+ title: `user-feedback-${iteration}`,
377
+ permission: [{ permission: "*", pattern: "*", action: "allow" }],
378
+ },
355
379
  async (s) => {
356
380
  const result = await s.client.session.prompt({
357
381
  sessionID: s.session.id,
@@ -384,7 +408,10 @@ export default defineWorkflow({
384
408
  description: `Design critique (iteration ${iteration})`,
385
409
  },
386
410
  {},
387
- { title: `critique-${iteration}` },
411
+ {
412
+ title: `critique-${iteration}`,
413
+ permission: [{ permission: "*", pattern: "*", action: "allow" }],
414
+ },
388
415
  async (s) => {
389
416
  const result = await s.client.session.prompt({
390
417
  sessionID: s.session.id,
@@ -411,7 +438,10 @@ export default defineWorkflow({
411
438
  description: `Visual validation (iteration ${iteration})`,
412
439
  },
413
440
  {},
414
- { title: `screenshot-${iteration}` },
441
+ {
442
+ title: `screenshot-${iteration}`,
443
+ permission: [{ permission: "*", pattern: "*", action: "allow" }],
444
+ },
415
445
  async (s) => {
416
446
  const result = await s.client.session.prompt({
417
447
  sessionID: s.session.id,
@@ -450,7 +480,10 @@ export default defineWorkflow({
450
480
  description: `Apply refinements (iteration ${iteration})`,
451
481
  },
452
482
  {},
453
- { title: `apply-changes-${iteration}` },
483
+ {
484
+ title: `apply-changes-${iteration}`,
485
+ permission: [{ permission: "*", pattern: "*", action: "allow" }],
486
+ },
454
487
  async (s) => {
455
488
  const result = await s.client.session.prompt({
456
489
  sessionID: s.session.id,
@@ -495,7 +528,10 @@ export default defineWorkflow({
495
528
  description: "Remove banned anti-patterns before export",
496
529
  },
497
530
  {},
498
- { title: "forced-fix" },
531
+ {
532
+ title: "forced-fix",
533
+ permission: [{ permission: "*", pattern: "*", action: "allow" }],
534
+ },
499
535
  async (s) => {
500
536
  const result = await s.client.session.prompt({
501
537
  sessionID: s.session.id,
@@ -539,7 +575,10 @@ export default defineWorkflow({
539
575
  description: "Export design and create handoff bundle",
540
576
  },
541
577
  {},
542
- { title: "exporter" },
578
+ {
579
+ title: "exporter",
580
+ permission: [{ permission: "*", pattern: "*", action: "allow" }],
581
+ },
543
582
  async (s) => {
544
583
  const result = await s.client.session.prompt({
545
584
  sessionID: s.session.id,
@@ -28,6 +28,7 @@ import { defineWorkflow, extractAssistantText } from "../../../index.ts";
28
28
  import {
29
29
  buildPlannerPrompt,
30
30
  buildOrchestratorPrompt,
31
+ buildCodeSimplifierPrompt,
31
32
  buildInfraDiscoveryPrompts,
32
33
  buildReviewPrompt,
33
34
  filterActionable,
@@ -94,7 +95,7 @@ export default defineWorkflow({
94
95
 
95
96
  for (let iteration = 1; iteration <= maxLoops; iteration++) {
96
97
  // ── Plan ────────────────────────────────────────────────────────────
97
- await ctx.stage(
98
+ const planner = await ctx.stage(
98
99
  { name: `planner-${iteration}` },
99
100
  {
100
101
  chatFlags: [
@@ -106,13 +107,14 @@ export default defineWorkflow({
106
107
  },
107
108
  {},
108
109
  async (s) => {
109
- await s.session.query(
110
+ const result = await s.session.query(
110
111
  buildPlannerPrompt(prompt, {
111
112
  iteration,
112
113
  reviewReport: reviewReport || undefined,
113
114
  }),
114
115
  );
115
116
  s.save(s.sessionId);
117
+ return extractAssistantText(result, 0);
116
118
  },
117
119
  );
118
120
 
@@ -129,7 +131,33 @@ export default defineWorkflow({
129
131
  },
130
132
  {},
131
133
  async (s) => {
132
- await s.session.query(buildOrchestratorPrompt(prompt));
134
+ await s.session.query(
135
+ buildOrchestratorPrompt(prompt, {
136
+ plannerNotes: planner.result,
137
+ }),
138
+ );
139
+ s.save(s.sessionId);
140
+ },
141
+ );
142
+
143
+ // ── Code Simplifier ─────────────────────────────────────────────────
144
+ await ctx.stage(
145
+ { name: `code-simplifier-${iteration}` },
146
+ {
147
+ chatFlags: [
148
+ "--agent",
149
+ "code-simplifier",
150
+ "--allow-dangerously-skip-permissions",
151
+ "--dangerously-skip-permissions",
152
+ ],
153
+ },
154
+ {},
155
+ async (s) => {
156
+ await s.session.query(
157
+ buildCodeSimplifierPrompt(prompt, {
158
+ plannerNotes: planner.result,
159
+ }),
160
+ );
133
161
  s.save(s.sessionId);
134
162
  },
135
163
  );
@@ -27,6 +27,7 @@ import type { SessionEvent } from "@github/copilot-sdk";
27
27
  import {
28
28
  buildPlannerPrompt,
29
29
  buildOrchestratorPrompt,
30
+ buildCodeSimplifierPrompt,
30
31
  buildInfraDiscoveryPrompts,
31
32
  buildReviewPrompt,
32
33
  filterActionable,
@@ -140,6 +141,21 @@ export default defineWorkflow({
140
141
  },
141
142
  );
142
143
 
144
+ // ── Code Simplifier ───────────────────────────────────────────────
145
+ await ctx.stage(
146
+ { name: `code-simplifier-${iteration}` },
147
+ {},
148
+ { agent: "code-simplifier" },
149
+ async (s) => {
150
+ await s.session.send({
151
+ prompt: buildCodeSimplifierPrompt(userPromptText, {
152
+ plannerNotes: planner.result,
153
+ }),
154
+ });
155
+ s.save(await s.session.getMessages());
156
+ },
157
+ );
158
+
143
159
  // ── Infrastructure Discovery (three parallel sub-agent stages) ──
144
160
  const changeset = await captureBranchChangeset();
145
161
  const discoveryPrompts = buildInfraDiscoveryPrompts();
@@ -554,6 +554,60 @@ Do NOT compress the worker's task subject, description, or persisted task
554
554
  records — those must remain self-contained and unambiguous.`);
555
555
  }
556
556
 
557
+ // ============================================================================
558
+ // CODE SIMPLIFIER
559
+ // ============================================================================
560
+
561
+ export interface CodeSimplifierContext {
562
+ /** Optional planner output (RFC markdown or absolute path to spec). */
563
+ plannerNotes?: string;
564
+ }
565
+
566
+ /**
567
+ * Build the code-simplifier prompt. Run by the `code-simplifier` sub-agent
568
+ * to inspect only the orchestrator's changes on the current branch and
569
+ * refine them for clarity, consistency, and maintainability — without
570
+ * altering functionality or test behaviour.
571
+ *
572
+ * @param spec - The user's original specification, used as context/fallback
573
+ * when planner output is missing or ambiguous.
574
+ * @param context - Optional planner handoff (spec path or inline RFC markdown).
575
+ */
576
+ export function buildCodeSimplifierPrompt(
577
+ spec: string,
578
+ context: CodeSimplifierContext = {},
579
+ ): string {
580
+ const plannerNotes = context.plannerNotes?.trim() ?? "";
581
+ const plannerSection =
582
+ plannerNotes.length > 0
583
+ ? `<planner_output>
584
+ ${plannerNotes}
585
+ </planner_output>`
586
+ : `<planner_output>
587
+ (empty — fall back to the Original User Specification below)
588
+ </planner_output>`;
589
+
590
+ return withCaveman(`Inspect the orchestrator's changes on the current branch and simplify the implementation for clarity, consistency, and maintainability.
591
+
592
+ ## Design Input (authoritative)
593
+
594
+ ${plannerSection}
595
+
596
+ ## Original User Specification (context / fallback)
597
+
598
+ <specification>
599
+ ${spec}
600
+ </specification>
601
+
602
+ ## Instructions
603
+
604
+ 1. **Scope to branch changes only.** Run \`git diff\` and \`git status\` to identify every file the orchestrator touched. Do NOT modify files outside that set.
605
+ 2. **Simplify and refine.** Within the changed files, improve clarity, consistency, naming, and structure. Remove dead code, unnecessary comments, and redundant abstractions. Prefer simple, direct implementations.
606
+ 3. **Preserve all functionality and test behaviour.** No feature regressions, no removed tests, no altered public interfaces unless the change is strictly cosmetic (e.g. rename of an internal variable).
607
+ 4. **Keep changes minimal and focused.** No scope creep. Do not rewrite working code that is already clear. Touch only what genuinely benefits from simplification.
608
+ 5. **Verify after edits.** Run \`bun typecheck\` and \`bun lint\` from the repository root after all edits are complete. Fix any errors they surface before finishing.`);
609
+ }
610
+
557
611
  // ============================================================================
558
612
  // INFRASTRUCTURE DISCOVERY
559
613
  // ============================================================================
@@ -592,7 +646,7 @@ one-line description of each.
592
646
  - **Build config**: tsconfig.json, webpack.config.*, vite.config.*, esbuild.*, rollup.config.*, Makefile, etc.
593
647
  - **Test config**: jest.config.*, vitest.config.*, playwright.config.*, .mocharc.*, pytest.ini, etc.
594
648
  - **Lint / format config**: .eslintrc.*, eslint.config.*, biome.json, .prettierrc.*, oxlint.json, etc.
595
- - **CI/CD workflows**: .github/workflows/*.yml, .gitlab-ci.yml, Jenkinsfile, .circleci/config.yml, etc.
649
+ - **CI/CD workflows (REQUIRED)**: .github/workflows/*.yml, .gitlab-ci.yml, Jenkinsfile, .circleci/config.yml, azure-pipelines.yml, etc. List every workflow file separately — reviewers need full coverage.
596
650
  - **Agent config files**: CLAUDE.md, AGENTS.md, .claude/*, .github/copilot-instructions.md (these often document project commands)
597
651
 
598
652
  ## Output format
@@ -625,7 +679,12 @@ which commands to run to verify an implementation.
625
679
  executes" list.
626
680
  4. Read CLAUDE.md / AGENTS.md if present — they often document the
627
681
  canonical commands for contributors.
628
- 5. Identify the test framework(s) in use and how to invoke them.
682
+ 5. **Audit CI workflows.** When the \`gh\` CLI is available (check via \`command -v gh\`), run:
683
+ - \`gh workflow list\` to enumerate active workflows.
684
+ - \`gh run list --limit 5\` to see the most recent runs and their statuses.
685
+ - \`gh workflow view <name>\` for any workflow whose name suggests it gates merges.
686
+ When \`gh\` is unavailable or unauthenticated, fall back to reading the workflow YAML files directly. Capture: workflow names, triggers (push / pull_request / schedule / workflow_dispatch), job names, the exact \`run:\` commands per job, and recent run statuses.
687
+ 6. Identify the test framework(s) in use and how to invoke them.
629
688
 
630
689
  ## Output format
631
690
 
@@ -644,6 +703,10 @@ which commands to run to verify an implementation.
644
703
 
645
704
  ## CI Commands (from workflow files)
646
705
  - \`<command>\` — <source file and context>
706
+
707
+ ## CI / GitHub Actions
708
+ - Workflow: \`<name>\` — triggers: \`<push|pr|schedule|...>\` — jobs: \`<job names>\`
709
+ - Recent runs (when \`gh\` available): \`<conclusion>\` on \`<branch>\` (\`<run id>\`)
647
710
  \`\`\`
648
711
 
649
712
  Be specific — include the exact invocation string (e.g. \`bun test\`, not
@@ -670,6 +733,10 @@ but HOW they are used in practice.
670
733
  order CI runs them.
671
734
  5. **Dependency install pattern**: How are dependencies installed before
672
735
  build/test (e.g. \`bun install\`, \`npm ci\`)?
736
+ 6. **CI audit patterns**: Map out the CI structure so reviewers can audit it. Identify matrix builds, job dependencies (\`needs:\`), conditional runs (\`if:\`), required checks, and which jobs gate merges. When \`gh\` is available, surface example commands a reviewer could use:
737
+ - \`gh run view <id> --log-failed\` — inspect a failed run.
738
+ - \`gh pr checks\` — see check status on the current PR.
739
+ - \`gh workflow view <name> --yaml\` — view the canonical workflow definition.
673
740
 
674
741
  ## Output format
675
742
 
@@ -679,7 +746,7 @@ For each pattern found, report:
679
746
  - A brief explanation of when/how it's used
680
747
 
681
748
  End with a brief trailing summary of the overall build/test workflow order
682
- (e.g. "install → typecheck → lint → test → build").`),
749
+ (e.g. "install → typecheck → lint → test → build"). Also summarise CI workflow order: which workflows fire on what triggers, in what order jobs run within each.`),
683
750
  };
684
751
  }
685
752
 
@@ -24,6 +24,7 @@ import { defineWorkflow } from "../../../index.ts";
24
24
  import {
25
25
  buildPlannerPrompt,
26
26
  buildOrchestratorPrompt,
27
+ buildCodeSimplifierPrompt,
27
28
  buildInfraDiscoveryPrompts,
28
29
  buildReviewPrompt,
29
30
  filterActionable,
@@ -98,7 +99,10 @@ export default defineWorkflow({
98
99
  const planner = await ctx.stage(
99
100
  { name: `planner-${iteration}` },
100
101
  {},
101
- { title: `planner-${iteration}` },
102
+ {
103
+ title: `planner-${iteration}`,
104
+ permission: [{ permission: "*", pattern: "*", action: "allow" }],
105
+ },
102
106
  async (s) => {
103
107
  const result = await s.client.session.prompt({
104
108
  sessionID: s.session.id,
@@ -122,7 +126,10 @@ export default defineWorkflow({
122
126
  await ctx.stage(
123
127
  { name: `orchestrator-${iteration}` },
124
128
  {},
125
- { title: `orchestrator-${iteration}` },
129
+ {
130
+ title: `orchestrator-${iteration}`,
131
+ permission: [{ permission: "*", pattern: "*", action: "allow" }],
132
+ },
126
133
  async (s) => {
127
134
  const result = await s.client.session.prompt({
128
135
  sessionID: s.session.id,
@@ -140,6 +147,31 @@ export default defineWorkflow({
140
147
  },
141
148
  );
142
149
 
150
+ // ── Code Simplifier ───────────────────────────────────────────────
151
+ await ctx.stage(
152
+ { name: `code-simplifier-${iteration}` },
153
+ {},
154
+ {
155
+ title: `code-simplifier-${iteration}`,
156
+ permission: [{ permission: "*", pattern: "*", action: "allow" }],
157
+ },
158
+ async (s) => {
159
+ const result = await s.client.session.prompt({
160
+ sessionID: s.session.id,
161
+ parts: [
162
+ {
163
+ type: "text",
164
+ text: buildCodeSimplifierPrompt(prompt, {
165
+ plannerNotes: planner.result,
166
+ }),
167
+ },
168
+ ],
169
+ agent: "code-simplifier",
170
+ });
171
+ s.save(result.data!);
172
+ },
173
+ );
174
+
143
175
  // ── Infrastructure Discovery (three parallel sub-agent stages) ────
144
176
  const changeset = await captureBranchChangeset();
145
177
  const discoveryPrompts = buildInfraDiscoveryPrompts();
@@ -148,7 +180,10 @@ export default defineWorkflow({
148
180
  ctx.stage(
149
181
  { name: `infra-locate-${iteration}`, headless: true },
150
182
  {},
151
- { title: `infra-locate-${iteration}` },
183
+ {
184
+ title: `infra-locate-${iteration}`,
185
+ permission: [{ permission: "*", pattern: "*", action: "allow" }],
186
+ },
152
187
  async (s) => {
153
188
  const result = await s.client.session.prompt({
154
189
  sessionID: s.session.id,
@@ -162,7 +197,10 @@ export default defineWorkflow({
162
197
  ctx.stage(
163
198
  { name: `infra-analyze-${iteration}`, headless: true },
164
199
  {},
165
- { title: `infra-analyze-${iteration}` },
200
+ {
201
+ title: `infra-analyze-${iteration}`,
202
+ permission: [{ permission: "*", pattern: "*", action: "allow" }],
203
+ },
166
204
  async (s) => {
167
205
  const result = await s.client.session.prompt({
168
206
  sessionID: s.session.id,
@@ -176,7 +214,10 @@ export default defineWorkflow({
176
214
  ctx.stage(
177
215
  { name: `infra-patterns-${iteration}`, headless: true },
178
216
  {},
179
- { title: `infra-patterns-${iteration}` },
217
+ {
218
+ title: `infra-patterns-${iteration}`,
219
+ permission: [{ permission: "*", pattern: "*", action: "allow" }],
220
+ },
180
221
  async (s) => {
181
222
  const result = await s.client.session.prompt({
182
223
  sessionID: s.session.id,
@@ -206,7 +247,10 @@ export default defineWorkflow({
206
247
  ctx.stage(
207
248
  { name },
208
249
  {},
209
- { title: name },
250
+ {
251
+ title: name,
252
+ permission: [{ permission: "*", pattern: "*", action: "allow" }],
253
+ },
210
254
  async (s) => {
211
255
  const result = await s.client.session.prompt({
212
256
  sessionID: s.session.id,
@@ -38,7 +38,13 @@ let copilotGetAuthStatus = mock<() => Promise<CopilotAuthStatus>>(async () => ({
38
38
  login: "octocat",
39
39
  }));
40
40
 
41
+ // Captures the options passed to `new CopilotClient(...)` on each call.
42
+ let lastCopilotConstructorOptions: unknown = undefined;
43
+
41
44
  class FakeCopilotClient {
45
+ constructor(options: unknown) {
46
+ lastCopilotConstructorOptions = options;
47
+ }
42
48
  async start(): Promise<void> {
43
49
  await copilotStart();
44
50
  }
@@ -114,6 +120,7 @@ afterAll(() => {
114
120
  const { checkAgentAuth, printAuthError } = await import("./auth.ts");
115
121
 
116
122
  beforeEach(() => {
123
+ lastCopilotConstructorOptions = undefined;
117
124
  copilotStart.mockClear();
118
125
  copilotStart.mockImplementation(async () => {});
119
126
  copilotStop.mockClear();
@@ -173,6 +180,52 @@ describe("checkAgentAuth(copilot)", () => {
173
180
  // The stop failure must not shadow the probe result.
174
181
  expect(result.detail).not.toContain("stop crashed");
175
182
  });
183
+
184
+ test("constructs CopilotClient with COPILOT_CLI_PATH as cliPath and NODE_NO_WARNINGS=1 in env", async () => {
185
+ const origCliPath = process.env["COPILOT_CLI_PATH"];
186
+ process.env["COPILOT_CLI_PATH"] = "/explicit/bin/copilot";
187
+ try {
188
+ await checkAgentAuth("copilot");
189
+ const opts = lastCopilotConstructorOptions as {
190
+ cliPath?: string;
191
+ env?: Record<string, string | undefined>;
192
+ };
193
+ expect(opts).toBeDefined();
194
+ expect(opts.cliPath).toBe("/explicit/bin/copilot");
195
+ expect(opts.env?.["NODE_NO_WARNINGS"]).toBe("1");
196
+ } finally {
197
+ if (origCliPath === undefined) delete process.env["COPILOT_CLI_PATH"];
198
+ else process.env["COPILOT_CLI_PATH"] = origCliPath;
199
+ }
200
+ });
201
+
202
+ test("constructs CopilotClient via centralized launch options — env.NODE_NO_WARNINGS=1 present even when COPILOT_CLI_PATH is unset", async () => {
203
+ // When COPILOT_CLI_PATH is absent the auth probe delegates entirely to
204
+ // copilotSdkLaunchOptions(), which always injects NODE_NO_WARNINGS=1
205
+ // via copilotSubprocessEnv(). No cliPath should appear in the options
206
+ // because resolveCopilotCliPath() returns undefined when the env var is
207
+ // not set and no standalone binary is found on PATH.
208
+ const origCliPath = process.env["COPILOT_CLI_PATH"];
209
+ delete process.env["COPILOT_CLI_PATH"];
210
+ try {
211
+ await checkAgentAuth("copilot");
212
+ const opts = lastCopilotConstructorOptions as {
213
+ cliPath?: string;
214
+ env?: Record<string, string | undefined>;
215
+ };
216
+ expect(opts).toBeDefined();
217
+ // Centralized env must always include NODE_NO_WARNINGS regardless of cliPath.
218
+ expect(opts.env?.["NODE_NO_WARNINGS"]).toBe("1");
219
+ // cliPath must not be injected from a stale or undefined resolution.
220
+ // (It may be defined if a copilot binary happens to be on PATH in the
221
+ // test environment, but it must never be "/explicit/bin/copilot" which
222
+ // is only set by the sibling test above.)
223
+ expect(opts.cliPath).not.toBe("/explicit/bin/copilot");
224
+ } finally {
225
+ if (origCliPath === undefined) delete process.env["COPILOT_CLI_PATH"];
226
+ else process.env["COPILOT_CLI_PATH"] = origCliPath;
227
+ }
228
+ });
176
229
  });
177
230
 
178
231
  describe("checkAgentAuth(claude)", () => {
@@ -17,7 +17,8 @@
17
17
 
18
18
  import type { AgentKey } from "../config/index.ts";
19
19
  import { COLORS } from "../../theme/colors.ts";
20
- import { copilotSubprocessEnv } from "../../sdk/providers/copilot.ts";
20
+ import { copilotSdkLaunchOptions } from "../../sdk/providers/copilot.ts";
21
+ import { withAtomicTempEnv } from "../../lib/atomic-temp.ts";
21
22
 
22
23
  export interface AuthCheckResult {
23
24
  /** True when the SDK reports the user is authenticated. */
@@ -72,7 +73,7 @@ const AUTH_PROMPTS: Record<AgentKey, { name: string; loginHint: string }> = {
72
73
 
73
74
  async function checkCopilotAuth(): Promise<AuthCheckResult> {
74
75
  const { CopilotClient } = await import("@github/copilot-sdk");
75
- const client = new CopilotClient({ env: copilotSubprocessEnv() });
76
+ const client = new CopilotClient(copilotSdkLaunchOptions());
76
77
  try {
77
78
  await client.start();
78
79
  const status = await client.getAuthStatus();
@@ -105,33 +106,35 @@ async function checkClaudeAuth(): Promise<AuthCheckResult> {
105
106
  // actually delivered.
106
107
  async function* emptyStream(): AsyncGenerator<never, void, void> {}
107
108
 
108
- const q = query({
109
- prompt: emptyStream(),
110
- options: {
111
- pathToClaudeCodeExecutable: resolveHeadlessClaudeBin(),
112
- },
113
- });
109
+ return await withAtomicTempEnv(async () => {
110
+ const q = query({
111
+ prompt: emptyStream(),
112
+ options: {
113
+ pathToClaudeCodeExecutable: resolveHeadlessClaudeBin(),
114
+ },
115
+ });
114
116
 
115
- try {
116
- const init = await q.initializationResult();
117
- const account = init.account ?? {};
118
- const loggedIn = Boolean(
119
- account.email || account.tokenSource || account.apiKeySource,
120
- );
121
- return {
122
- loggedIn,
123
- identity: account.email,
124
- };
125
- } catch (err) {
126
- return {
127
- loggedIn: false,
128
- detail: err instanceof Error ? err.message : String(err),
129
- };
130
- } finally {
131
117
  try {
132
- q.close();
133
- } catch {
134
- // Best effort — the subprocess is torn down on process exit anyway.
118
+ const init = await q.initializationResult();
119
+ const account = init.account ?? {};
120
+ const loggedIn = Boolean(
121
+ account.email || account.tokenSource || account.apiKeySource,
122
+ );
123
+ return {
124
+ loggedIn,
125
+ identity: account.email,
126
+ };
127
+ } catch (err) {
128
+ return {
129
+ loggedIn: false,
130
+ detail: err instanceof Error ? err.message : String(err),
131
+ };
132
+ } finally {
133
+ try {
134
+ q.close();
135
+ } catch {
136
+ // Best effort — the subprocess is torn down on process exit anyway.
137
+ }
135
138
  }
136
- }
139
+ });
137
140
  }
@@ -24,7 +24,7 @@ export function isCommandInstalled(cmd: string): boolean {
24
24
  * @returns The absolute path to the command, or null if not found
25
25
  */
26
26
  export function getCommandPath(cmd: string): string | null {
27
- return Bun.which(cmd);
27
+ return Bun.which(cmd, { PATH: process.env["PATH"] ?? "" });
28
28
  }
29
29
 
30
30
  /**