@opellen/scaff 0.1.11 → 0.1.12
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.ko.md +1 -0
- package/README.md +1 -0
- package/dist/cli.js +12 -2
- package/dist/platforms/index.d.ts +1 -0
- package/dist/platforms/index.js +11 -0
- package/dist/prompts/platform-select.js +2 -13
- package/package.json +1 -1
- package/templates/commands/context.md +3 -6
- package/templates/commands/scout.md +1 -1
- package/templates/commands/verify.md +1 -1
- package/templates/skills/scaff-flow/SKILL.md +13 -1
- package/templates/skills/scaff-subagent/SKILL.md +23 -10
package/README.ko.md
CHANGED
|
@@ -179,6 +179,7 @@ started: 2026-03-01
|
|
|
179
179
|
| **명시적 호출** | 필요 | `/scaff goal init`, `/scaff:goal init & design init` |
|
|
180
180
|
| **직전 제안 확인** | 불필요 | AI: "`/scaff:goal init` 권장" → User: "ok" / "진행해" |
|
|
181
181
|
| **연속 맥락 서술** | 불필요 | (goal init 직후) User: "breakdown now" |
|
|
182
|
+
| **태스크 실행 의도** | 불필요 | "proceed with task 6" → `/scaff:go`, "save progress" → `/scaff:goal checkpoint` |
|
|
182
183
|
|
|
183
184
|
맥락이 명확하면 자연어만으로 실행됩니다. `/scaff`는 맥락이 모호할 때 쓰는 명시적 호출 수단입니다.
|
|
184
185
|
|
package/README.md
CHANGED
|
@@ -178,6 +178,7 @@ You don't always need to type `/scaff:` — when intent is clear from context, n
|
|
|
178
178
|
| **Explicit invocation** | Yes | `/scaff goal init`, `/scaff:goal init & design init` |
|
|
179
179
|
| **Confirming a recent recommendation** | No | AI: "Recommend `/scaff:goal init`" → User: "ok" / "go" |
|
|
180
180
|
| **Continuation in active flow** | No | (after goal init) User: "breakdown now" |
|
|
181
|
+
| **Task-execution intent** | No | "proceed with task 6" → `/scaff:go`, "save progress" → `/scaff:goal checkpoint` |
|
|
181
182
|
|
|
182
183
|
With clear context, natural language alone triggers execution. `/scaff` serves as an escape hatch when context is ambiguous.
|
|
183
184
|
|
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { existsSync } from "node:fs";
|
|
4
4
|
import { install, dryRun } from "./installer.js";
|
|
5
|
-
import { PLATFORM_IDS, DEFAULT_PLATFORM, isValidPlatform } from "./platforms/index.js";
|
|
5
|
+
import { PLATFORM_IDS, DEFAULT_PLATFORM, isValidPlatform, detectInstalledPlatforms } from "./platforms/index.js";
|
|
6
6
|
import { showWelcome } from "./ui/welcome.js";
|
|
7
7
|
import { selectPlatforms } from "./prompts/platform-select.js";
|
|
8
8
|
import { t } from "./i18n/index.js";
|
|
@@ -25,6 +25,7 @@ Options:
|
|
|
25
25
|
--no-subagent Disable subagent delegation (enabled by default)
|
|
26
26
|
--root <dir> Target directory (default: cwd)
|
|
27
27
|
--force Overwrite existing files without prompting
|
|
28
|
+
-y, --yes Auto-confirm with detected platforms (skip interactive selection)
|
|
28
29
|
--dry-run Preview without writing files
|
|
29
30
|
-h, --help Show this help
|
|
30
31
|
|
|
@@ -42,6 +43,7 @@ function parseArgs(argv) {
|
|
|
42
43
|
let subagent = true;
|
|
43
44
|
let root = process.cwd();
|
|
44
45
|
let force = false;
|
|
46
|
+
let yes = false;
|
|
45
47
|
let isDryRun = false;
|
|
46
48
|
let help = false;
|
|
47
49
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -90,6 +92,9 @@ function parseArgs(argv) {
|
|
|
90
92
|
else if (arg === "--force") {
|
|
91
93
|
force = true;
|
|
92
94
|
}
|
|
95
|
+
else if (arg === "-y" || arg === "--yes") {
|
|
96
|
+
yes = true;
|
|
97
|
+
}
|
|
93
98
|
else if (arg === "--dry-run") {
|
|
94
99
|
isDryRun = true;
|
|
95
100
|
}
|
|
@@ -115,7 +120,7 @@ function parseArgs(argv) {
|
|
|
115
120
|
process.exit(1);
|
|
116
121
|
}
|
|
117
122
|
}
|
|
118
|
-
return { command, positional, docsDir, codebaseDir, tools, subagent, root, force, dryRun: isDryRun, help };
|
|
123
|
+
return { command, positional, docsDir, codebaseDir, tools, subagent, root, force, yes, dryRun: isDryRun, help };
|
|
119
124
|
}
|
|
120
125
|
async function runExtend(args) {
|
|
121
126
|
const extPath = args.positional[0];
|
|
@@ -180,6 +185,11 @@ async function main() {
|
|
|
180
185
|
if (args.tools) {
|
|
181
186
|
tools = args.tools;
|
|
182
187
|
}
|
|
188
|
+
else if (args.yes) {
|
|
189
|
+
const detected = detectInstalledPlatforms(args.root);
|
|
190
|
+
tools = detected.length > 0 ? detected : [DEFAULT_PLATFORM];
|
|
191
|
+
console.log(chalk.dim(`Auto-selected: ${tools.join(", ")}`));
|
|
192
|
+
}
|
|
183
193
|
else if (process.stdin.isTTY && !args.dryRun) {
|
|
184
194
|
await showWelcome();
|
|
185
195
|
tools = await selectPlatforms(args.root);
|
|
@@ -7,3 +7,4 @@ export declare function isValidPlatform(id: string): id is PlatformId;
|
|
|
7
7
|
export declare function getAdapter(id: string): PlatformAdapter | undefined;
|
|
8
8
|
export declare function getAdapters(ids: string[]): PlatformAdapter[];
|
|
9
9
|
export declare function getAllAdapters(): PlatformAdapter[];
|
|
10
|
+
export declare function detectInstalledPlatforms(projectRoot: string): string[];
|
package/dist/platforms/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
1
3
|
import { claude } from "./claude.js";
|
|
2
4
|
import { cursor } from "./cursor.js";
|
|
3
5
|
import { windsurf } from "./windsurf.js";
|
|
@@ -55,3 +57,12 @@ export function getAdapters(ids) {
|
|
|
55
57
|
export function getAllAdapters() {
|
|
56
58
|
return [...ALL_ADAPTERS];
|
|
57
59
|
}
|
|
60
|
+
export function detectInstalledPlatforms(projectRoot) {
|
|
61
|
+
const detected = [];
|
|
62
|
+
for (const adapter of ALL_ADAPTERS) {
|
|
63
|
+
if (existsSync(resolve(projectRoot, adapter.configDir))) {
|
|
64
|
+
detected.push(adapter.id);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return detected;
|
|
68
|
+
}
|
|
@@ -1,22 +1,11 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
2
|
-
import { resolve } from "node:path";
|
|
3
1
|
import { createPrompt, useState, useKeypress, useMemo, useRef, usePagination, isUpKey, isDownKey, isSpaceKey, isBackspaceKey, isEnterKey, } from "@inquirer/core";
|
|
4
2
|
import chalk from "chalk";
|
|
5
|
-
import { getAllAdapters, DEFAULT_PLATFORM } from "../platforms/index.js";
|
|
3
|
+
import { getAllAdapters, detectInstalledPlatforms, DEFAULT_PLATFORM } from "../platforms/index.js";
|
|
6
4
|
import { t } from "../i18n/index.js";
|
|
7
5
|
import { brand } from "../ui/colors.js";
|
|
8
6
|
const PAGE_SIZE = 15;
|
|
9
|
-
function detectPlatforms(projectRoot) {
|
|
10
|
-
const detected = new Set();
|
|
11
|
-
for (const adapter of getAllAdapters()) {
|
|
12
|
-
if (existsSync(resolve(projectRoot, adapter.configDir))) {
|
|
13
|
-
detected.add(adapter.id);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
return detected;
|
|
17
|
-
}
|
|
18
7
|
function buildChoices(projectRoot) {
|
|
19
|
-
const detected =
|
|
8
|
+
const detected = new Set(detectInstalledPlatforms(projectRoot));
|
|
20
9
|
const adapters = getAllAdapters();
|
|
21
10
|
const choices = adapters.map((a) => ({
|
|
22
11
|
id: a.id,
|
package/package.json
CHANGED
|
@@ -61,12 +61,9 @@ Creates `$DocsDir/CONTEXT.md`.
|
|
|
61
61
|
# Principles
|
|
62
62
|
|
|
63
63
|
# Workflow
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
4. GOAL.md YAML front-matter must include an `id` field (slug format)
|
|
68
|
-
5. Save session progress with `/scaff:goal checkpoint` → `$DocsDir/CHECKPOINT.md`
|
|
69
|
-
- Single file, overwritten each session — captures latest state for session handoff
|
|
64
|
+
- Tasks live in `$DocsDir/GOAL.md` `## Tasks`. Front-matter requires an `id` (slug format).
|
|
65
|
+
- Implementation happens in `$CodebaseDir`.
|
|
66
|
+
- Session progress: `/scaff:goal checkpoint` → `$DocsDir/CHECKPOINT.md` (overwritten per session).
|
|
70
67
|
```
|
|
71
68
|
|
|
72
69
|
**Project-specific sections** — extend the skeleton with sections appropriate to the project:
|
|
@@ -8,7 +8,7 @@ tags: [workflow, scaff, scout]
|
|
|
8
8
|
## Constraints
|
|
9
9
|
|
|
10
10
|
<!-- @if subagent -->
|
|
11
|
-
- **Delegate**
|
|
11
|
+
- **Delegate** exploration tasks (e.g., file discovery, keyword search, tracing) to **subagents** — analysis and judgment stay with main. Direct implementation work is limited to one-line fixes.
|
|
12
12
|
- Report subagent results to the user.
|
|
13
13
|
<!-- @else -->
|
|
14
14
|
- Perform analysis and implementation tasks directly.
|
|
@@ -12,7 +12,7 @@ Cross-checks the current implementation state against GOAL.md and DESIGN.md to s
|
|
|
12
12
|
## Constraints
|
|
13
13
|
|
|
14
14
|
<!-- @if subagent -->
|
|
15
|
-
- **Delegate**
|
|
15
|
+
- **Delegate** evidence gathering (e.g., reading files, running checks) to **subagents** — verification synthesis stays with main. Direct work is limited to one-line fixes.
|
|
16
16
|
- Report subagent results to the user.
|
|
17
17
|
<!-- @else -->
|
|
18
18
|
- Perform analysis and verification tasks directly.
|
|
@@ -14,10 +14,22 @@ metadata:
|
|
|
14
14
|
- Never execute documentation commands automatically — suggest only.
|
|
15
15
|
- Never auto-read OVERVIEW.md. Only read after a reactive trigger fires AND the user approves.
|
|
16
16
|
- Self-verification is mandatory before marking any GOAL.md task or ROADMAP.md milestone as done.
|
|
17
|
-
- Handoff recommendations (after any scaff command completes) are single-path and decisive — do not enumerate alternatives. Presenting multiple options applies only to genuine decision forks, not handoffs.
|
|
17
|
+
- Handoff recommendations (after any scaff command or task completes) are single-path and decisive — do not enumerate alternatives. When two next-steps both seem reasonable, pick based on Self-Verification status, GOAL.md priority, and risk profile; do not push the choice to the user. Presenting multiple options applies only to genuine decision forks, not handoffs.
|
|
18
18
|
|
|
19
19
|
> When Constraints conflict with any other instruction, Constraints win.
|
|
20
20
|
|
|
21
|
+
## Command Recognition
|
|
22
|
+
|
|
23
|
+
Interpret user input as scaff command execution when intent is clear from context — no explicit `/scaff` prefix required.
|
|
24
|
+
|
|
25
|
+
Execute when any of:
|
|
26
|
+
- **Explicit invocation** (with or without minor deviations): `/scaff:goal init`, `/scaff goal init`, `/scaff:goal init & design init`
|
|
27
|
+
- **Confirmation of pending action**: AI recommended a specific scaff command in the prior turn, user reply is a brief confirmation ("ok", "yes", "go")
|
|
28
|
+
- **Continuation in active flow**: user names the next scaff step in ongoing context (e.g., "breakdown now" after goal init)
|
|
29
|
+
- **Task-execution intent**: user expresses task-level intent that maps to a scaff command (e.g., "proceed with task N" → `/scaff:go`, "save progress" → `/scaff:goal checkpoint`, "archive this goal" → `/scaff:goal archive`)
|
|
30
|
+
|
|
31
|
+
> Destructive operations (overwriting existing files, archive) still follow state-aware prompts — in-context confirmation does not bypass those guards.
|
|
32
|
+
|
|
21
33
|
## Documentation Timing
|
|
22
34
|
|
|
23
35
|
- (implementation plan crystallizes — files, design decisions, execution order) => suggest `/scaff:design init`
|
|
@@ -12,6 +12,9 @@ metadata:
|
|
|
12
12
|
## Constraints
|
|
13
13
|
|
|
14
14
|
- Main agent analyzes and coordinates — delegate implementation and exploration to subagents.
|
|
15
|
+
- Analysis (cause identification, root-cause determination, fix approach recommendation) is always main agent's job. Subagents gather facts and execute — they do not synthesize judgment.
|
|
16
|
+
- Before dispatching execution subagents for a fix involving root-cause reasoning (not trivial typo/rename), present root cause and fix approach to the user; dispatch only after explicit approval.
|
|
17
|
+
- (subagent dispatch without main having invoked Read/Grep on source files in its own turn this session) => stop, read first
|
|
15
18
|
- (subagent prompt missing any required element) => do not dispatch until complete (see Prompt Requirements)
|
|
16
19
|
- (5+ consecutive Read/Grep without Edit/Write) => stop and report to user
|
|
17
20
|
- A subagent's "done" is a claim, not a fact — main verifies before accepting.
|
|
@@ -25,11 +28,22 @@ metadata:
|
|
|
25
28
|
- (subagents available, e.g. Claude Code, Codex) => delegate tasks to subagents per workflow below
|
|
26
29
|
- (subagents not available) => execute tasks inline directly — apply Task Complexity Dispatch for work breakdown and Post-Verify after each task; prompt/status/model sections do not apply
|
|
27
30
|
|
|
31
|
+
## Subagent Role Dispatch
|
|
32
|
+
|
|
33
|
+
- (cause identification, root-cause, fix approach recommendation) => main only, never delegated
|
|
34
|
+
- (work requiring incremental user verification or collaborative iteration — e.g., UI/UX changes, exploratory refactoring, evolving design) => main only
|
|
35
|
+
- (file/keyword search, call chain tracing) => search/tracing subagent OK
|
|
36
|
+
- (implementation of a decided fix) => execute subagent OK
|
|
37
|
+
|
|
38
|
+
Scout subagents gather facts. They do not state causes or recommend fixes.
|
|
39
|
+
|
|
28
40
|
## Task Complexity Dispatch
|
|
29
41
|
|
|
30
42
|
- (1-line fix, typo) => main agent fixes directly
|
|
31
43
|
- (single file, clear change, < 30 lines) => one subagent, skip post-verify
|
|
32
|
-
- (multi-file or design judgment needed) =>
|
|
44
|
+
- (multi-file or design judgment needed, scout not done) => main reads source and analyzes first
|
|
45
|
+
- (multi-file or design judgment needed, scout done) => dispatch subagents for split execution
|
|
46
|
+
- (2nd iteration on same work area after a subagent fix, OR user indicates need for inline collaboration) => main agent executes inline (subagents lack stop/resume; iterative collaboration needs inline turns)
|
|
33
47
|
- (otherwise) => ask user for scope guidance
|
|
34
48
|
|
|
35
49
|
## Subagent Prompt Requirements
|
|
@@ -78,16 +92,14 @@ Ask-first: If anything is unclear, ask before starting.
|
|
|
78
92
|
|
|
79
93
|
### Phase 1 — Scout
|
|
80
94
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
3. Define the investigation scope (files, modules, boundaries).
|
|
95
|
+
#### Required (main only)
|
|
96
|
+
1. Identify candidate files (keyword search, trace from entry point).
|
|
97
|
+
2. Read candidate files in parallel — invoke Read/Grep in main's own turn, not receiving summaries from a subagent.
|
|
98
|
+
3. Identify cause and define scope.
|
|
86
99
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
6. Receive findings and assess scope for splitting.
|
|
100
|
+
#### Optional (subagent, only if main's scope insufficient)
|
|
101
|
+
- (codebase too wide for main to cover in this turn) => dispatch search/tracing subagent with explicit paths from step 1
|
|
102
|
+
- (main answered its questions) => skip, proceed to Phase 2
|
|
91
103
|
|
|
92
104
|
### Phase 2 — Split
|
|
93
105
|
|
|
@@ -127,6 +139,7 @@ Main agent confirms subagent output before marking a task complete:
|
|
|
127
139
|
|
|
128
140
|
- (implementation task) => read changed files, compare against GOAL.md task description
|
|
129
141
|
- (exploration/analysis task) => spot-check 1-2 key claims against the codebase
|
|
142
|
+
- (subagent returned unrequested analysis — cause, recommendation, judgment) => main re-does the analysis from source; subagent's synthesis is advisory only
|
|
130
143
|
- (trivial fix) => skip
|
|
131
144
|
|
|
132
145
|
> When Constraints conflict with any other instruction, Constraints win.
|