@leing2021/super-pi 0.19.2 → 0.19.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/README.md
CHANGED
|
@@ -35,7 +35,7 @@ Super Pi's answers:
|
|
|
35
35
|
|
|
36
36
|
Each step has a dedicated skill + tool pair. Not just prompts — structured toolchains.
|
|
37
37
|
|
|
38
|
-
### New: Stage model routing
|
|
38
|
+
### New: Stage model routing
|
|
39
39
|
|
|
40
40
|
Configure once in `.pi/settings.json`:
|
|
41
41
|
|
|
@@ -48,24 +48,22 @@ Configure once in `.pi/settings.json`:
|
|
|
48
48
|
"04-review": "claude-sonnet-4-20250514",
|
|
49
49
|
"05-learn": "claude-haiku-4-20250414",
|
|
50
50
|
"default": "claude-sonnet-4-20250514"
|
|
51
|
-
},
|
|
52
|
-
"pipeline": {
|
|
53
|
-
"autoContinue": false
|
|
54
51
|
}
|
|
55
52
|
}
|
|
56
53
|
```
|
|
57
54
|
|
|
58
55
|
How it works:
|
|
59
|
-
-
|
|
56
|
+
- Model switching is handled automatically by the ce-core extension `input` hook — no manual `/model` needed.
|
|
57
|
+
- When you type `/skill:01-brainstorm` through `/skill:05-learn`, the extension reads `modelStrategy[stage]` (or `modelStrategy.default`) and switches before the skill runs.
|
|
58
|
+
- Supported formats: full reference (`"anthropic/claude-opus-4-1"`) or bare model id (`"claude-opus-4-1"`, reuses current provider).
|
|
60
59
|
- Every stage prints a `📊 Pipeline Status` block with `Current / Output / Next`.
|
|
61
|
-
-
|
|
62
|
-
- Auto-continue is gate-aware: it will NOT skip required approvals (brainstorm approval, plan/review A/B/C choices).
|
|
60
|
+
- A `Switched model for <stage>: <provider>/<model>` notification appears when the model changes.
|
|
63
61
|
|
|
64
62
|
Quick example:
|
|
65
|
-
1. Run `/skill:01-brainstorm`
|
|
63
|
+
1. Run `/skill:01-brainstorm` — model auto-switches to the configured brainstorm model
|
|
66
64
|
2. Approve the design
|
|
67
|
-
3.
|
|
68
|
-
4.
|
|
65
|
+
3. Run `/skill:02-plan` — model auto-switches to the configured plan model
|
|
66
|
+
4. Continue through each stage — model switches automatically at each step
|
|
69
67
|
|
|
70
68
|
---
|
|
71
69
|
|
|
@@ -180,7 +178,7 @@ Single `npm install` output filtered once pays for the entire overhead. Full eva
|
|
|
180
178
|
|
|
181
179
|
## Code Scale
|
|
182
180
|
|
|
183
|
-
~2800 lines of TypeScript implementing 16 tools, 22 Markdown reference files + 78 rule files driving 10 skills,
|
|
181
|
+
~2800 lines of TypeScript implementing 16 tools, 22 Markdown reference files + 78 rule files driving 10 skills, 175 tests covering all tool logic.
|
|
184
182
|
|
|
185
183
|
Not a heavy framework. Each tool has a single responsibility, each skill works independently, and together they form a complete workflow.
|
|
186
184
|
|
|
@@ -383,6 +381,20 @@ Not a fork. Not a wrapper. Methodologies extracted and rebuilt with Pi's native
|
|
|
383
381
|
|
|
384
382
|
## Changelog
|
|
385
383
|
|
|
384
|
+
### 0.19.4 — Read output filter markdown truncation fix
|
|
385
|
+
- Fixed `read-output-filter` over-truncating markdown files: raised markdown threshold from 2KB → 8KB.
|
|
386
|
+
- Improved `filterMarkdown()` to fully preserve list items (`-`, `*`, numbered) and keep first 3 lines of paragraphs (was 1).
|
|
387
|
+
- Filter notice now includes actual file path in actionable guidance (`bash cat <path>`).
|
|
388
|
+
- Added 5 new tests covering list preservation, markdown threshold gate, and path-in-notice.
|
|
389
|
+
- 175 tests passing.
|
|
390
|
+
|
|
391
|
+
### 0.19.3 — Terminate fix + runtime model routing + autoContinue removal
|
|
392
|
+
- Fixed 6 ce-core tools (`brainstorm_dialog`, `workflow_state`, `review_router`, `session_checkpoint`, `session_history`, `pattern_extractor`) incorrectly returning `terminate: true`, which caused agent turns to end prematurely (brainstorm questions not shown, "type continue to proceed" interruptions).
|
|
393
|
+
- Implemented runtime stage model routing via ce-core extension `input` hook: reads `.pi/settings.json` `modelStrategy`, auto-switches model before skill execution. Supports full reference (`anthropic/claude-opus-4-1`) and bare model id (`claude-opus-4-1`).
|
|
394
|
+
- Removed `pipeline.autoContinue` configuration (never had runtime implementation; Pi lacks `skill_end` event for auto-continue).
|
|
395
|
+
- Updated `skills/references/pipeline-config.md`, `README.md`, `README_CN.md` to reflect runtime model routing behavior.
|
|
396
|
+
- Added 4 new tests covering terminate regression, input hook model routing, and bare model id parsing.
|
|
397
|
+
|
|
386
398
|
### 0.19.2 — Evidence-first handoff-lite + docs tracking rule
|
|
387
399
|
- Added `context_handoff` with evidence-first default handoff-lite generation when markdown is omitted.
|
|
388
400
|
- Standardized the shared handoff-lite template across 01-05 workflow handoffs via `skills/references/pipeline-config.md`.
|
|
@@ -391,8 +403,7 @@ Not a fork. Not a wrapper. Methodologies extracted and rebuilt with Pi's native
|
|
|
391
403
|
|
|
392
404
|
### 0.19.1 — Pipeline config + typecheck baseline fix
|
|
393
405
|
- Added shared pipeline config (`skills/references/pipeline-config.md`) for stage model routing via `.pi/settings.json`.
|
|
394
|
-
- Added
|
|
395
|
-
- Added explicit README usage examples for `modelStrategy` and `pipeline.autoContinue`.
|
|
406
|
+
- Added runtime stage model routing via ce-core extension `input` hook (reads `modelStrategy` from `.pi/settings.json`, auto-switches model before skill execution).
|
|
396
407
|
- Fixed TypeScript baseline issues so `bunx tsc --noEmit` passes.
|
|
397
408
|
|
|
398
409
|
### 0.19.0 — 0.69.0 alignment + learn rename
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises"
|
|
2
|
+
import path from "node:path"
|
|
1
3
|
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent"
|
|
2
4
|
import { Type } from "typebox"
|
|
3
5
|
import { createArtifactHelperTool, type ArtifactType } from "./tools/artifact-helper"
|
|
@@ -20,6 +22,65 @@ import { AsyncMutex } from "./tools/async-mutex"
|
|
|
20
22
|
import type { SubagentExecOptions, SubagentRunner } from "./tools/subagent"
|
|
21
23
|
|
|
22
24
|
const _subagentEnvMutex = new AsyncMutex()
|
|
25
|
+
const PIPELINE_STAGE_KEYS = new Set([
|
|
26
|
+
"01-brainstorm",
|
|
27
|
+
"02-plan",
|
|
28
|
+
"03-work",
|
|
29
|
+
"04-review",
|
|
30
|
+
"05-learn",
|
|
31
|
+
])
|
|
32
|
+
|
|
33
|
+
interface ModelStrategySettings {
|
|
34
|
+
modelStrategy?: Record<string, string>
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function readProjectSettings(cwd: string): Promise<ModelStrategySettings | null> {
|
|
38
|
+
const settingsPath = path.join(cwd, ".pi", "settings.json")
|
|
39
|
+
try {
|
|
40
|
+
const content = await readFile(settingsPath, "utf8")
|
|
41
|
+
return JSON.parse(content) as ModelStrategySettings
|
|
42
|
+
} catch {
|
|
43
|
+
return null
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function parseStageSkillName(text: string): string | null {
|
|
48
|
+
const trimmed = text.trim()
|
|
49
|
+
const match = trimmed.match(/^\/skill:([^\s]+)/)
|
|
50
|
+
if (!match) {
|
|
51
|
+
return null
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const skillName = match[1]
|
|
55
|
+
return PIPELINE_STAGE_KEYS.has(skillName) ? skillName : null
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function parseModelRef(
|
|
59
|
+
modelRef: string,
|
|
60
|
+
currentProvider?: string,
|
|
61
|
+
): { provider: string, id: string } | null {
|
|
62
|
+
const trimmed = modelRef.trim()
|
|
63
|
+
if (!trimmed) {
|
|
64
|
+
return null
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const slashIndex = trimmed.indexOf("/")
|
|
68
|
+
if (slashIndex > 0 && slashIndex < trimmed.length - 1) {
|
|
69
|
+
return {
|
|
70
|
+
provider: trimmed.slice(0, slashIndex),
|
|
71
|
+
id: trimmed.slice(slashIndex + 1),
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (!currentProvider) {
|
|
76
|
+
return null
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
provider: currentProvider,
|
|
81
|
+
id: trimmed,
|
|
82
|
+
}
|
|
83
|
+
}
|
|
23
84
|
|
|
24
85
|
/**
|
|
25
86
|
* Create a subagent runner that handles env injection with mutex protection
|
|
@@ -223,6 +284,62 @@ const patternExtractorParams = Type.Object({
|
|
|
223
284
|
})
|
|
224
285
|
|
|
225
286
|
export default function ceCoreExtension(pi: ExtensionAPI) {
|
|
287
|
+
pi.on("input", async (event, ctx) => {
|
|
288
|
+
if (event.source === "extension") {
|
|
289
|
+
return { action: "continue" as const }
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const stageKey = parseStageSkillName(event.text)
|
|
293
|
+
if (!stageKey) {
|
|
294
|
+
return { action: "continue" as const }
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const settings = await readProjectSettings(ctx.cwd)
|
|
298
|
+
const modelStrategy = settings?.modelStrategy
|
|
299
|
+
if (!modelStrategy) {
|
|
300
|
+
return { action: "continue" as const }
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const targetModelRef = modelStrategy[stageKey] ?? modelStrategy.default
|
|
304
|
+
if (!targetModelRef) {
|
|
305
|
+
return { action: "continue" as const }
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const parsed = parseModelRef(targetModelRef, ctx.model?.provider)
|
|
309
|
+
if (!parsed) {
|
|
310
|
+
if (ctx.hasUI) {
|
|
311
|
+
ctx.ui.notify(`Invalid modelStrategy entry for ${stageKey}: ${targetModelRef}`, "warning")
|
|
312
|
+
}
|
|
313
|
+
return { action: "continue" as const }
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (ctx.model?.provider === parsed.provider && ctx.model?.id === parsed.id) {
|
|
317
|
+
return { action: "continue" as const }
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const model = ctx.modelRegistry.find(parsed.provider, parsed.id)
|
|
321
|
+
if (!model) {
|
|
322
|
+
if (ctx.hasUI) {
|
|
323
|
+
ctx.ui.notify(`Configured model not found for ${stageKey}: ${targetModelRef}`, "warning")
|
|
324
|
+
}
|
|
325
|
+
return { action: "continue" as const }
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const switched = await pi.setModel(model)
|
|
329
|
+
if (switched) {
|
|
330
|
+
if (ctx.hasUI) {
|
|
331
|
+
ctx.ui.notify(`Switched model for ${stageKey}: ${model.provider}/${model.id}`, "info")
|
|
332
|
+
}
|
|
333
|
+
return { action: "continue" as const }
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (ctx.hasUI) {
|
|
337
|
+
ctx.ui.notify(`No API key available for configured model: ${model.provider}/${model.id}`, "warning")
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return { action: "continue" as const }
|
|
341
|
+
})
|
|
342
|
+
|
|
226
343
|
const artifactHelper = createArtifactHelperTool()
|
|
227
344
|
const askUserQuestion = createAskUserQuestionTool()
|
|
228
345
|
const subagent = createSubagentTool()
|
|
@@ -338,7 +455,6 @@ export default function ceCoreExtension(pi: ExtensionAPI) {
|
|
|
338
455
|
return {
|
|
339
456
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
340
457
|
details: result,
|
|
341
|
-
terminate: true,
|
|
342
458
|
}
|
|
343
459
|
},
|
|
344
460
|
})
|
|
@@ -393,7 +509,6 @@ export default function ceCoreExtension(pi: ExtensionAPI) {
|
|
|
393
509
|
return {
|
|
394
510
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
395
511
|
details: result,
|
|
396
|
-
terminate: true,
|
|
397
512
|
}
|
|
398
513
|
},
|
|
399
514
|
})
|
|
@@ -449,7 +564,6 @@ export default function ceCoreExtension(pi: ExtensionAPI) {
|
|
|
449
564
|
return {
|
|
450
565
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
451
566
|
details: result,
|
|
452
|
-
terminate: true,
|
|
453
567
|
}
|
|
454
568
|
},
|
|
455
569
|
})
|
|
@@ -489,7 +603,6 @@ export default function ceCoreExtension(pi: ExtensionAPI) {
|
|
|
489
603
|
return {
|
|
490
604
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
491
605
|
details: result,
|
|
492
|
-
terminate: true,
|
|
493
606
|
}
|
|
494
607
|
},
|
|
495
608
|
})
|
|
@@ -531,7 +644,6 @@ export default function ceCoreExtension(pi: ExtensionAPI) {
|
|
|
531
644
|
return {
|
|
532
645
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
533
646
|
details: result,
|
|
534
|
-
terminate: true,
|
|
535
647
|
}
|
|
536
648
|
},
|
|
537
649
|
})
|
|
@@ -553,7 +665,6 @@ export default function ceCoreExtension(pi: ExtensionAPI) {
|
|
|
553
665
|
return {
|
|
554
666
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
555
667
|
details: result,
|
|
556
|
-
terminate: true,
|
|
557
668
|
}
|
|
558
669
|
},
|
|
559
670
|
})
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// 1. Lock / generated files → extreme compression (summary only)
|
|
10
10
|
// 2. package.json → keep scripts + dep summary, drop full version lists
|
|
11
11
|
// 3. Large code files → keep signatures/structure, collapse bodies
|
|
12
|
-
// 4. Large markdown → keep headings +
|
|
12
|
+
// 4. Large markdown → keep headings + code blocks + lists + expanded paragraphs per section
|
|
13
13
|
// 5. Generic → head/tail truncation for very large files
|
|
14
14
|
|
|
15
15
|
// ============================================================================
|
|
@@ -93,6 +93,9 @@ function classifyFile(path: string): FileCategory {
|
|
|
93
93
|
/** Minimum output size (bytes) to trigger any filtering */
|
|
94
94
|
const MIN_FILTER_THRESHOLD = 2048 // 2KB
|
|
95
95
|
|
|
96
|
+
/** Minimum output size (bytes) to trigger markdown filtering */
|
|
97
|
+
const MARKDOWN_FILTER_THRESHOLD = 8192 // 8KB — markdown docs are dense, don't filter small ones
|
|
98
|
+
|
|
96
99
|
/** Maximum size for structural code compression trigger */
|
|
97
100
|
const CODE_COMPRESS_THRESHOLD = 8192 // 8KB
|
|
98
101
|
|
|
@@ -308,6 +311,9 @@ function filterMarkdown(output: string): string {
|
|
|
308
311
|
let inParagraph = false
|
|
309
312
|
let paragraphLineCount = 0
|
|
310
313
|
let inCodeBlock = false
|
|
314
|
+
let omitMarkerPlaced = false
|
|
315
|
+
|
|
316
|
+
const MAX_PARAGRAPH_LINES = 3 // Keep first N lines of each paragraph (vs 1 before)
|
|
311
317
|
|
|
312
318
|
for (const line of lines) {
|
|
313
319
|
const trimmed = line.trim()
|
|
@@ -322,6 +328,7 @@ function filterMarkdown(output: string): string {
|
|
|
322
328
|
// Keep all lines inside code blocks
|
|
323
329
|
if (inCodeBlock) {
|
|
324
330
|
kept.push(line)
|
|
331
|
+
omitMarkerPlaced = false
|
|
325
332
|
continue
|
|
326
333
|
}
|
|
327
334
|
|
|
@@ -330,27 +337,43 @@ function filterMarkdown(output: string): string {
|
|
|
330
337
|
kept.push(line)
|
|
331
338
|
inParagraph = false
|
|
332
339
|
paragraphLineCount = 0
|
|
340
|
+
omitMarkerPlaced = false
|
|
333
341
|
continue
|
|
334
342
|
}
|
|
335
343
|
|
|
336
|
-
// Empty lines
|
|
344
|
+
// Empty lines — reset paragraph state
|
|
337
345
|
if (trimmed === "") {
|
|
338
346
|
kept.push(line)
|
|
339
347
|
inParagraph = false
|
|
340
348
|
paragraphLineCount = 0
|
|
349
|
+
omitMarkerPlaced = false
|
|
350
|
+
continue
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Always keep list items (-, *, numbered) — they often contain key definitions
|
|
354
|
+
if (/^[-*+]\s/.test(trimmed) || /^\d+\.\s/.test(trimmed)) {
|
|
355
|
+
kept.push(line)
|
|
356
|
+
omitMarkerPlaced = false
|
|
357
|
+
// List items don't count as paragraph continuation
|
|
341
358
|
continue
|
|
342
359
|
}
|
|
343
360
|
|
|
344
|
-
// Keep first
|
|
361
|
+
// Keep first N lines of each paragraph
|
|
345
362
|
if (!inParagraph) {
|
|
346
363
|
kept.push(line)
|
|
347
364
|
inParagraph = true
|
|
348
365
|
paragraphLineCount = 1
|
|
366
|
+
omitMarkerPlaced = false
|
|
349
367
|
} else {
|
|
350
368
|
paragraphLineCount++
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
369
|
+
if (paragraphLineCount <= MAX_PARAGRAPH_LINES) {
|
|
370
|
+
kept.push(line)
|
|
371
|
+
} else {
|
|
372
|
+
// Place omit marker once per paragraph
|
|
373
|
+
if (!omitMarkerPlaced) {
|
|
374
|
+
kept.push(` [... additional paragraph content omitted]`)
|
|
375
|
+
omitMarkerPlaced = true
|
|
376
|
+
}
|
|
354
377
|
}
|
|
355
378
|
}
|
|
356
379
|
}
|
|
@@ -400,9 +423,11 @@ function appendFilterNotice(
|
|
|
400
423
|
originalBytes: number,
|
|
401
424
|
filteredBytes: number,
|
|
402
425
|
strategy: string,
|
|
426
|
+
path?: string,
|
|
403
427
|
): string {
|
|
404
428
|
const saved = formatBytes(originalBytes - filteredBytes)
|
|
405
|
-
|
|
429
|
+
const pathHint = path ? `: bash cat ${path}` : ": bash cat <path>"
|
|
430
|
+
return `${output}\n\n[Read output filtered: ${formatBytes(originalBytes)} → ${formatBytes(filteredBytes)} (${saved} saved, strategy: ${strategy}). If you need the full content, use${pathHint}]`
|
|
406
431
|
}
|
|
407
432
|
|
|
408
433
|
// ============================================================================
|
|
@@ -464,8 +489,12 @@ export function filterReadOutput(input: ReadOutputFilterInput): ReadOutputFilter
|
|
|
464
489
|
break
|
|
465
490
|
|
|
466
491
|
case "markdown":
|
|
467
|
-
|
|
468
|
-
|
|
492
|
+
if (originalBytes >= MARKDOWN_FILTER_THRESHOLD) {
|
|
493
|
+
filtered = filterMarkdown(output)
|
|
494
|
+
strategyName = "markdown (headings + code + lists + expanded paragraphs)"
|
|
495
|
+
} else {
|
|
496
|
+
return { output, filtered: false, originalBytes, filteredBytes: originalBytes, strategy: "none (markdown below 8KB threshold)" }
|
|
497
|
+
}
|
|
469
498
|
break
|
|
470
499
|
|
|
471
500
|
case "config":
|
|
@@ -497,7 +526,7 @@ export function filterReadOutput(input: ReadOutputFilterInput): ReadOutputFilter
|
|
|
497
526
|
}
|
|
498
527
|
|
|
499
528
|
return {
|
|
500
|
-
output: appendFilterNotice(filtered, originalBytes, filteredBytes, strategyName),
|
|
529
|
+
output: appendFilterNotice(filtered, originalBytes, filteredBytes, strategyName, path),
|
|
501
530
|
filtered: true,
|
|
502
531
|
originalBytes,
|
|
503
532
|
filteredBytes,
|
package/package.json
CHANGED
|
@@ -4,21 +4,21 @@ Use these rules in all Phase 1 skills: `01-brainstorm` → `02-plan` → `03-wor
|
|
|
4
4
|
|
|
5
5
|
## Start of skill: model routing
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
## End of skill: status + context
|
|
7
|
+
Model routing is handled automatically by the ce-core extension's `input` hook.
|
|
8
|
+
When a user types `/skill:01-brainstorm` through `/skill:05-learn`, the extension:
|
|
9
|
+
|
|
10
|
+
1. Reads `.pi/settings.json` from the project root.
|
|
11
|
+
2. Parses `modelStrategy[stageKey]` or falls back to `modelStrategy.default`.
|
|
12
|
+
3. If the target model differs from the current model, calls `pi.setModel()`.
|
|
13
|
+
4. If switching fails, notifies the user and continues with the current model.
|
|
14
|
+
|
|
15
|
+
No manual `/model` command is needed. The skill itself does not need to handle model switching.
|
|
16
|
+
|
|
17
|
+
Supported `modelStrategy` formats in `.pi/settings.json`:
|
|
18
|
+
- Full reference: `"02-plan": "anthropic/claude-opus-4-1"`
|
|
19
|
+
- Bare model id (reuses current provider): `"02-plan": "claude-opus-4-1"`
|
|
20
|
+
|
|
21
|
+
## End of skill: status + context
|
|
22
22
|
|
|
23
23
|
Before final completion, always output these blocks (replace placeholders with real values, never output angle-bracket placeholders literally):
|
|
24
24
|
|
|
@@ -45,16 +45,6 @@ Next step mapping:
|
|
|
45
45
|
- `04-review` → `/skill:05-learn`
|
|
46
46
|
- `05-learn` → `Completed`
|
|
47
47
|
|
|
48
|
-
Then read `.pi/settings.json` → `pipeline.autoContinue`:
|
|
49
|
-
- If `false` or missing, stop after the status block and wait for user input.
|
|
50
|
-
- If current stage is `05-learn`, stop after status block.
|
|
51
|
-
- If `true` and current stage is not `05-learn`, auto-continue is allowed only after stage-specific gates are satisfied:
|
|
52
|
-
- `01-brainstorm`: user has explicitly approved the design handoff.
|
|
53
|
-
- `02-plan`: review choice is resolved (A/B/C flow completed) and user confirmed to proceed.
|
|
54
|
-
- `04-review`: optional QA choice is resolved (A/B/C flow completed) and user confirmed to proceed.
|
|
55
|
-
- Any unclear/ambiguous state: do not auto-continue; stop and ask.
|
|
56
|
-
- When gates are satisfied, automatically trigger the mapped next skill command.
|
|
57
|
-
|
|
58
48
|
### Handoff-lite template
|
|
59
49
|
|
|
60
50
|
When a stage produces or updates handoff-lite, use this evidence-first structure and keep it concise (target <= 1500 tokens):
|