@aipper/aiws-spec 0.0.46 → 0.0.48
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/docs/opencode-omo-adapter.md +52 -0
- package/docs/workflow-router-rules.md +4 -1
- package/docs/ws-goal-contract.md +68 -0
- package/package.json +1 -1
- package/templates/workspace/.opencode/command/ws-goal.md +51 -44
- package/templates/workspace/.opencode/commands/ws-goal.md +278 -0
- package/templates/workspace/.opencode/lib/aiws-context.js +211 -0
- package/templates/workspace/.opencode/skills/using-aiws/SKILL.md +40 -49
- package/templates/workspace/.opencode/skills/ws-delegate/SKILL.md +24 -48
- package/templates/workspace/.opencode/skills/ws-dev/SKILL.md +22 -39
- package/templates/workspace/.opencode/skills/ws-frontend-design/SKILL.md +14 -32
- package/templates/workspace/.opencode/skills/ws-goal/SKILL.md +55 -22
- package/templates/workspace/.opencode/skills/ws-plan/SKILL.md +12 -26
- package/templates/workspace/.opencode/skills/ws-quality-review/SKILL.md +1 -0
- package/templates/workspace/.opencode/skills/ws-spec-review/SKILL.md +1 -0
|
@@ -386,6 +386,209 @@ export class AiwsContext {
|
|
|
386
386
|
)
|
|
387
387
|
}
|
|
388
388
|
|
|
389
|
+
// -- Goal FSM (TOOLING-003D L1 inject) -------------------------------
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Scan `.aiws/goals/*.state.json` for active/paused goals.
|
|
393
|
+
* Preference: status=active first, then paused.
|
|
394
|
+
* Within a status tier, most recently updated wins (updated_at ISO or file mtime).
|
|
395
|
+
*
|
|
396
|
+
* Returns array of goal summary objects (may be empty). Never throws.
|
|
397
|
+
* Each entry:
|
|
398
|
+
* { goal_id, status, current_phase, checkpoint_summary, md_path, state_path,
|
|
399
|
+
* next_action, updated_at, mtime_ms, others_note? }
|
|
400
|
+
*/
|
|
401
|
+
getActiveGoals() {
|
|
402
|
+
const goalsDir = join(this.directory, ".aiws", "goals")
|
|
403
|
+
if (!existsSync(goalsDir)) return []
|
|
404
|
+
|
|
405
|
+
let files
|
|
406
|
+
try {
|
|
407
|
+
files = readdirSync(goalsDir).filter(f => f.endsWith(".state.json"))
|
|
408
|
+
} catch {
|
|
409
|
+
return []
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
const active = []
|
|
413
|
+
const paused = []
|
|
414
|
+
|
|
415
|
+
for (const file of files) {
|
|
416
|
+
const statePath = join(goalsDir, file)
|
|
417
|
+
let raw
|
|
418
|
+
try {
|
|
419
|
+
raw = readFileSync(statePath, "utf-8")
|
|
420
|
+
} catch {
|
|
421
|
+
continue
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
let state
|
|
425
|
+
try {
|
|
426
|
+
state = JSON.parse(raw)
|
|
427
|
+
} catch {
|
|
428
|
+
// malformed JSON — skip without crashing
|
|
429
|
+
continue
|
|
430
|
+
}
|
|
431
|
+
if (!state || typeof state !== "object") continue
|
|
432
|
+
|
|
433
|
+
const status = str(state.status)
|
|
434
|
+
if (status !== "active" && status !== "paused") continue
|
|
435
|
+
|
|
436
|
+
const goalId =
|
|
437
|
+
str(state.goal_id) ||
|
|
438
|
+
str(state.goalId) ||
|
|
439
|
+
file.replace(/\.state\.json$/, "")
|
|
440
|
+
|
|
441
|
+
let mtimeMs = 0
|
|
442
|
+
try {
|
|
443
|
+
mtimeMs = statSync(statePath).mtimeMs
|
|
444
|
+
} catch {
|
|
445
|
+
mtimeMs = 0
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const updatedAt = str(state.updated_at) || str(state.updatedAt) || null
|
|
449
|
+
let sortKey = mtimeMs
|
|
450
|
+
if (updatedAt) {
|
|
451
|
+
const t = Date.parse(updatedAt)
|
|
452
|
+
if (!Number.isNaN(t)) sortKey = t
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
const currentPhase =
|
|
456
|
+
state.current_phase == null
|
|
457
|
+
? null
|
|
458
|
+
: (str(state.current_phase) || String(state.current_phase))
|
|
459
|
+
|
|
460
|
+
const checkpointSummary = this._summarizeGoalCheckpoints(state.checkpoints)
|
|
461
|
+
const mdPath = join(".aiws", "goals", `${goalId}.md`)
|
|
462
|
+
const nextAction = this._suggestGoalNextAction({
|
|
463
|
+
goal_id: goalId,
|
|
464
|
+
status,
|
|
465
|
+
current_phase: currentPhase,
|
|
466
|
+
checkpoints: state.checkpoints,
|
|
467
|
+
})
|
|
468
|
+
|
|
469
|
+
const entry = {
|
|
470
|
+
goal_id: goalId,
|
|
471
|
+
status,
|
|
472
|
+
current_phase: currentPhase,
|
|
473
|
+
checkpoint_summary: checkpointSummary,
|
|
474
|
+
md_path: mdPath,
|
|
475
|
+
state_path: join(".aiws", "goals", file),
|
|
476
|
+
next_action: nextAction,
|
|
477
|
+
updated_at: updatedAt,
|
|
478
|
+
mtime_ms: mtimeMs,
|
|
479
|
+
_sort: sortKey,
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
if (status === "active") active.push(entry)
|
|
483
|
+
else paused.push(entry)
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
const byRecency = (a, b) => b._sort - a._sort
|
|
487
|
+
active.sort(byRecency)
|
|
488
|
+
paused.sort(byRecency)
|
|
489
|
+
|
|
490
|
+
const ordered = [...active, ...paused]
|
|
491
|
+
return ordered.map(({ _sort, ...rest }) => rest)
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Primary goal for session inject: first of getActiveGoals() (active preferred).
|
|
496
|
+
* When multiple actives exist, the most recently updated is primary; callers can
|
|
497
|
+
* list others via getActiveGoals().
|
|
498
|
+
*/
|
|
499
|
+
getActiveGoal() {
|
|
500
|
+
const goals = this.getActiveGoals()
|
|
501
|
+
return goals.length > 0 ? goals[0] : null
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
_summarizeGoalCheckpoints(checkpoints) {
|
|
505
|
+
if (!checkpoints || typeof checkpoints !== "object") return "(no checkpoints)"
|
|
506
|
+
const pending = []
|
|
507
|
+
const complete = []
|
|
508
|
+
for (const [name, cp] of Object.entries(checkpoints)) {
|
|
509
|
+
const st =
|
|
510
|
+
cp && typeof cp === "object"
|
|
511
|
+
? str(cp.status) || "unknown"
|
|
512
|
+
: "unknown"
|
|
513
|
+
if (st === "complete" || st === "done") complete.push(name)
|
|
514
|
+
else pending.push(`${name}:${st}`)
|
|
515
|
+
}
|
|
516
|
+
const parts = []
|
|
517
|
+
if (pending.length) parts.push(`pending=[${pending.join(", ")}]`)
|
|
518
|
+
if (complete.length) parts.push(`complete=${complete.length}`)
|
|
519
|
+
return parts.join(" ") || "(empty checkpoints)"
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* Suggest next_action text for L1 inject (READ-ONLY; no skill execution).
|
|
524
|
+
* Frozen Q3=A: plugins only inject text; model/user runs /ws-goal.
|
|
525
|
+
*/
|
|
526
|
+
_suggestGoalNextAction({ goal_id, status, current_phase, checkpoints }) {
|
|
527
|
+
const id = goal_id || "?"
|
|
528
|
+
if (status === "paused") {
|
|
529
|
+
return `/ws-goal resume ${id}`
|
|
530
|
+
}
|
|
531
|
+
// active
|
|
532
|
+
if (!current_phase || current_phase === "null") {
|
|
533
|
+
return `/ws-goal continue ${id} (establish current_phase via advance if needed)`
|
|
534
|
+
}
|
|
535
|
+
// Find first incomplete checkpoint name if useful
|
|
536
|
+
let nextCp = null
|
|
537
|
+
if (checkpoints && typeof checkpoints === "object") {
|
|
538
|
+
for (const [name, cp] of Object.entries(checkpoints)) {
|
|
539
|
+
const st =
|
|
540
|
+
cp && typeof cp === "object" ? str(cp.status) : null
|
|
541
|
+
if (st && st !== "complete" && st !== "done") {
|
|
542
|
+
nextCp = name
|
|
543
|
+
break
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
if (nextCp && nextCp !== current_phase) {
|
|
548
|
+
return `/ws-goal continue ${id} — phase=${current_phase}, next checkpoint=${nextCp}`
|
|
549
|
+
}
|
|
550
|
+
return `/ws-goal continue ${id} — phase=${current_phase}`
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Compact <goal-context> block for session-start inject.
|
|
555
|
+
* Empty string when no active/paused goal.
|
|
556
|
+
*/
|
|
557
|
+
buildGoalContextBlock() {
|
|
558
|
+
const goals = this.getActiveGoals()
|
|
559
|
+
if (!goals.length) return ""
|
|
560
|
+
|
|
561
|
+
const primary = goals[0]
|
|
562
|
+
const others = goals.slice(1)
|
|
563
|
+
const lines = [
|
|
564
|
+
"<goal-context>",
|
|
565
|
+
"## Active / Paused Goal (FSM L1 inject — advisory routing only)",
|
|
566
|
+
`goal_id: ${primary.goal_id}`,
|
|
567
|
+
`status: ${primary.status}`,
|
|
568
|
+
`current_phase: ${primary.current_phase ?? "null"}`,
|
|
569
|
+
`checkpoints: ${primary.checkpoint_summary}`,
|
|
570
|
+
`goal_md: ${primary.md_path}`,
|
|
571
|
+
`state: ${primary.state_path}`,
|
|
572
|
+
`next_action: ${primary.next_action}`,
|
|
573
|
+
]
|
|
574
|
+
if (others.length) {
|
|
575
|
+
const brief = others
|
|
576
|
+
.map(g => `${g.goal_id}(${g.status}, phase=${g.current_phase ?? "null"})`)
|
|
577
|
+
.join("; ")
|
|
578
|
+
lines.push(`other_goals: ${brief}`)
|
|
579
|
+
lines.push(
|
|
580
|
+
"note: multiple active/paused — primary is most recently updated; " +
|
|
581
|
+
"resolve conflict before parallel goal work"
|
|
582
|
+
)
|
|
583
|
+
}
|
|
584
|
+
lines.push(
|
|
585
|
+
"authority: phase writes via `aiws goal advance` only; " +
|
|
586
|
+
"this block does not execute skills (L1 text inject)."
|
|
587
|
+
)
|
|
588
|
+
lines.push("</goal-context>")
|
|
589
|
+
return lines.join("\n")
|
|
590
|
+
}
|
|
591
|
+
|
|
389
592
|
// -- Spec index ------------------------------------------------
|
|
390
593
|
|
|
391
594
|
/**
|
|
@@ -824,6 +1027,14 @@ You are starting a new session in an aiws-managed project.
|
|
|
824
1027
|
Read and follow the context below.
|
|
825
1028
|
</aiws-context>`)
|
|
826
1029
|
|
|
1030
|
+
// TOOLING-003D L1: active/paused goal FSM inject (READ-ONLY text)
|
|
1031
|
+
try {
|
|
1032
|
+
const goalBlock = ctx.buildGoalContextBlock()
|
|
1033
|
+
if (goalBlock) parts.push(goalBlock)
|
|
1034
|
+
} catch {
|
|
1035
|
+
// Non-blocking: goal inject must never crash session-start
|
|
1036
|
+
}
|
|
1037
|
+
|
|
827
1038
|
const specIndex = ctx.getSpecIndex()
|
|
828
1039
|
if (specIndex) {
|
|
829
1040
|
parts.push("<spec-index>")
|
|
@@ -5,21 +5,21 @@ description: 使用时机:新会话开始、不确定下一步做什么时。
|
|
|
5
5
|
|
|
6
6
|
用中文输出(命令/路径/代码标识符保持原样不翻译)。
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
目标:默认入口,先读真值,判定 workflow,再进入 `ws-*`。意图不明则先澄清,不直接实现。阶段:bootstrap/router,只分流。
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
路由 SSOT:`packages/spec/docs/workflow-router-rules.json`(`goal_driven` / `plan_first` / `direct_implementation` / `escape_hatch`)。本 skill 是人工投影,冲突以 JSON 为准。
|
|
11
11
|
|
|
12
12
|
## 编排约束
|
|
13
13
|
|
|
14
|
-
- **不直接实现**:只判 workflow
|
|
15
|
-
-
|
|
16
|
-
- **意图不明先澄清**:`routeTo=clarify`
|
|
14
|
+
- **不直接实现**:只判 workflow、读真值、路由到 `ws-*`。主 session 不写代码。
|
|
15
|
+
- **上下文先于判决**:`direct_implementation` 前收集 `git status --porcelain`、`git diff --stat`、`AI_WORKSPACE.md` 验证入口;仅 ≤3 文件、≤100 行、验证明确才可 direct。
|
|
16
|
+
- **意图不明先澄清**:`routeTo=clarify` 时停并问 1-3 个关键问题。
|
|
17
|
+
- **L3 纪律(goal resume)**:有 `active`/`paused` goal 时,冷启动 medium+ 勿 bare 跳 `$ws-dev`/`$ws-plan`;优先 `$ws-goal` resume。例外:显式 escape-hatch 或用户点名阶段 skill。
|
|
17
18
|
|
|
18
19
|
## 必需输入
|
|
19
20
|
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
- 若已存在:`change/<change-id>` 上下文、`plan/...`、`.aiws/changes/<change-id>/...`
|
|
21
|
+
- 任务描述;`AI_PROJECT.md` / `REQUIREMENTS.md` / `AI_WORKSPACE.md`
|
|
22
|
+
- 若已存在:`change/<id>`、`plan/...`、`.aiws/changes/<id>/...`、`.aiws/goals/`、`ws-goal` skill
|
|
23
23
|
|
|
24
24
|
## 必需输出
|
|
25
25
|
|
|
@@ -27,83 +27,74 @@ description: 使用时机:新会话开始、不确定下一步做什么时。
|
|
|
27
27
|
|
|
28
28
|
## 阻断条件
|
|
29
29
|
|
|
30
|
-
-
|
|
30
|
+
- 无法确定项目根、缺失真值、意图不明、无法归因且不能安全推断
|
|
31
31
|
|
|
32
32
|
## 执行步骤
|
|
33
33
|
|
|
34
34
|
### 1. Preflight
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
读三真值。有 `.opencode/oh-my-opencode.json` → `oMo-enabled`,否则 `standard-opencode`。缺真值 → `$ws-preflight`,建议 `aiws init .`。
|
|
37
37
|
|
|
38
38
|
### 1.5 Per-turn Breadcrumb(必做)
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
每轮开始读 change 状态,输出 `[workflow-state:PHASE_NAME/N]`。
|
|
41
41
|
|
|
42
42
|
### 2. 路由判定
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
按 `workflow-router-rules.json` 判定。direct 前先收集 git 上下文。
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
**复杂度启发(结合上下文):** ≤2 文件、已知路径、≤100 行、验证明确 → 可 direct;≥3 文件 / 跨模块 / 多步 / 未知路径 → medium+(优先 goal/plan)。
|
|
47
|
+
|
|
48
|
+
**ws-goal 可用**:存在 `.aiws/goals/`,或可加载 `ws-goal` skill。
|
|
48
49
|
|
|
49
50
|
| 意图 | Route |
|
|
50
51
|
|------|-------|
|
|
51
52
|
| 需求/验收/合同变更 | `$ws-req-review` |
|
|
52
|
-
|
|
|
53
|
+
| 评审/审计/风险 | `$ws-review` |
|
|
53
54
|
| finish/merge/push/cleanup | `$ws-finish` |
|
|
54
55
|
| handoff/archive | `$ws-handoff` |
|
|
55
|
-
| 先出设计方案 | `$ws-plan
|
|
56
|
-
|
|
|
57
|
-
|
|
|
56
|
+
| 先出设计方案 | `$ws-plan`(已走 goal → `$ws-goal` 管道) |
|
|
57
|
+
| 更新规范/验收 | `$ws-req-change`(先 review) |
|
|
58
|
+
| 中大型实现(goal 可用) | `$ws-goal`(`goal_driven`) |
|
|
59
|
+
| 中大型实现(goal 不可用) | `$ws-plan`(`plan_first`) |
|
|
58
60
|
| 小步明确实现/修复 | `$ws-dev` |
|
|
59
|
-
| 极简修复 | `$ws-dev-lite` |
|
|
60
|
-
| Subagent 不可用 |
|
|
61
|
-
|
|
62
|
-
注:`$ws-dev` 默认走 subagent-first 策略。主 session 应优先通过 `$ws-delegate` 派发 `aiws-worker`,除非用户明确说"直接改"。
|
|
61
|
+
| 极简修复 / 显式跳过流程 | `$ws-dev-lite`(后者 `escape_hatch`) |
|
|
62
|
+
| Subagent 不可用 | 单 agent + 工件模式 |
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
注:`$ws-dev` 默认 subagent-first;主 session 优先 `$ws-delegate` → `aiws-worker`,除非用户说「直接改」。
|
|
65
65
|
|
|
66
|
+
**Escape Hatch**:用户明确「跳过流程」/「直接改」/「do it inline」→ `$ws-dev-lite`,须 `[escape-hatch]`、Req_ID、可复现验证、evidence 注明原因。小修入口保留,不得全灌 `$ws-goal`。
|
|
66
67
|
### 3. 意图不明确
|
|
67
68
|
|
|
68
69
|
只问 1-3 个关键问题(意图、Req_ID/Problem_ID、verify、change),然后停止。
|
|
69
70
|
|
|
70
71
|
### 4. Continuation Routing(新 session 恢复)
|
|
71
72
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
| Phase | Next Action |
|
|
75
|
-
|-------|-------------|
|
|
76
|
-
| none(无 change) | ws-intake 或 ws-plan |
|
|
77
|
-
| intake | ws-intake 继续,或 ws-plan |
|
|
78
|
-
| planning | plan 存在→ws-plan-verify;否则 ws-plan |
|
|
79
|
-
| ready-for-dev | 派发 aiws-worker |
|
|
80
|
-
| in-progress | patches 存在→review;was DONE_WITH_CONCERNS→ws-quality-review;否则继续 |
|
|
81
|
-
| review | evidence 齐→ws-finish/ws-commit;否则补 evidence |
|
|
82
|
-
| finished | ws-finish 收尾归档 |
|
|
83
|
-
| unknown | ws-preflight |
|
|
73
|
+
change 相位 + goal 叠加;goal 优先于冷启动 plan/dev 跳过:
|
|
84
74
|
|
|
85
|
-
|
|
75
|
+
| Phase / Goal | Next |
|
|
76
|
+
|--------------|------|
|
|
77
|
+
| active goal | `$ws-goal` resume(按 state next_action) |
|
|
78
|
+
| paused goal | `$ws-goal` resume(继续 / 改目标 / 放弃后冷启动) |
|
|
79
|
+
| none | intake;或 medium+ 且 goal 可用 → `$ws-goal`;否则 `$ws-plan` |
|
|
80
|
+
| intake | 继续 intake,或 plan/goal(按可用性与冻结) |
|
|
81
|
+
| planning | 有 plan→plan-verify;否则 plan(goal 内则 `$ws-goal`) |
|
|
82
|
+
| ready-for-dev | 派发 aiws-worker(goal 绑定经 `$ws-goal`) |
|
|
83
|
+
| in-progress | 有 patches→review;DONE_WITH_CONCERNS→quality-review;否则继续 |
|
|
84
|
+
| review | evidence 齐→finish/commit;否则补 evidence |
|
|
85
|
+
| finished / unknown | `$ws-finish` 归档 / `$ws-preflight` |
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
Subagent 降级:无 subagent 时本 agent 执行,evidence 记 `mode: single-agent`。`BLOCKED` 解 blocker;`NEEDS_CONTEXT` 补 JSONL 后重试。
|
|
88
88
|
|
|
89
89
|
### 5. 输出路由
|
|
90
90
|
|
|
91
91
|
```
|
|
92
|
-
Root:
|
|
93
|
-
Found: <files>
|
|
94
|
-
OpenCode mode: <oMo-enabled / standard-opencode>
|
|
95
|
-
Task intent: <分类>
|
|
96
|
-
Binding: <清晰 / 缺失项>
|
|
97
|
-
Route: <$ws-... 或 clarify>
|
|
98
|
-
Why: <一句到三句>
|
|
99
|
-
Next: <继续执行对应 skill,或提出澄清问题>
|
|
92
|
+
Root: / Found: / OpenCode mode: / Task intent: / Binding: / Route: / Why: / Next:
|
|
100
93
|
```
|
|
101
94
|
|
|
102
95
|
## 约束
|
|
103
96
|
|
|
104
|
-
- Router
|
|
105
|
-
-
|
|
106
|
-
- 复杂度升高:`$ws-dev` 回退 `$ws-plan`;`$ws-finish` 回退前置门禁
|
|
107
|
-
- subagent 不可用:单 agent 执行,但须维护等价工件结构
|
|
97
|
+
- Router 不实现;不给 route 前不改代码;一次一个主 route;复杂度升高时 `$ws-dev` → `$ws-plan`/`$ws-goal`,`$ws-finish` 回退前置门禁
|
|
98
|
+
- subagent 不可用:单 agent,维护等价工件;不用 L4 程序化 skill invoke(agent 读规则后进入 skill)
|
|
108
99
|
|
|
109
100
|
> 运行时行为约束:`packages/spec/docs/run-behavior-guidelines.md`
|
|
@@ -5,67 +5,46 @@ description: 使用时机:需要拆分子任务、委托给子 agent 时。触
|
|
|
5
5
|
|
|
6
6
|
用中文输出(命令/路径/代码标识符保持原样不翻译)。
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
目标:优先 oMo agent 拆分任务;不可用则回退 OpenCode delegation / 单 agent。
|
|
9
9
|
|
|
10
10
|
## 核心约束
|
|
11
11
|
|
|
12
|
-
- **Subagent-First**:主 session
|
|
13
|
-
- **Handoff 证据**:worker 必须产出 `.aiws/changes/<id>/handoff-evidence.md
|
|
12
|
+
- **Subagent-First**:主 session 只编排收敛,不写代码;产出由 subagent 完成并可追溯。
|
|
13
|
+
- **Handoff 证据**:worker 必须产出 `.aiws/changes/<id>/handoff-evidence.md`(完成/未完成/残余风险)。缺失=委托未完成。
|
|
14
14
|
|
|
15
|
-
## 必需输入
|
|
15
|
+
## 必需输入 / 输出
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
- 当前任务已绑定 `Req_ID` / change / Verify
|
|
17
|
+
**输入:** 真值 + delegation contract 上下文(`workflow-delegation-contracts.md`、`opencode-omo-adapter.md`、`opencode-subagent-first.md`);任务已绑定 `Req_ID` / change / Verify。
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
**输出:** `Delegation Plan:` role / preferred agent / readScope / writeScope / artifactTargets / fallback;`Context Curation:` / `Execution Mode:` / `Evidence:` / `Next:`。
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
- `Context Curation:` 策展详情 / `Execution Mode:` / `Evidence:` / `Next:`
|
|
21
|
+
**执行:** 主 session 不改代码;产物由 subagent 可追溯产出;handoff 含 delegate round number、产出路径、未关闭项。
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
- 主 session 不直接改代码;所有产物由 subagent 产出且可追溯
|
|
28
|
-
- handoff 含 delegate round number、产出文件路径、已知未关闭项
|
|
29
|
-
|
|
30
|
-
## 阻断条件
|
|
31
|
-
|
|
32
|
-
任务未绑定 / 委托边界不清 / 上下文策展未执行 / 无法判断 oMo 可用性 / handoff 文件缺失
|
|
23
|
+
**阻断:** 任务未绑定 / 边界不清 / 未策展上下文 / 无法判断 oMo 可用性 / handoff 缺失。
|
|
33
24
|
|
|
34
25
|
## 角色映射
|
|
35
26
|
|
|
36
|
-
| aiws
|
|
37
|
-
|
|
38
|
-
| planner | planner-sisyphus |
|
|
39
|
-
| explorer | @explore / @librarian |
|
|
40
|
-
| reviewer | @oracle |
|
|
41
|
-
| integrator | 当前主 agent |
|
|
42
|
-
|
|
43
|
-
推荐标准角色:
|
|
44
|
-
|
|
45
|
-
| 角色 | 职责 | 读取 | 写入 |
|
|
46
|
-
|------|------|------|------|
|
|
47
|
-
| implementer | 代码+测试实现 | 真值+change上下文 | 代码+测试+evidence/ |
|
|
48
|
-
| reviewer | 独立审查 | 真值+diff+evidence | review/*.md |
|
|
49
|
-
| researcher | 分析探索 | 真值+外部文档 | analysis/*.md |
|
|
27
|
+
| aiws | oMo | 标准角色 | 职责 | 读 | 写 |
|
|
28
|
+
|------|-----|----------|------|----|----|
|
|
29
|
+
| planner | planner-sisyphus | implementer | 代码+测试 | 真值+change | 代码+测试+evidence/ |
|
|
30
|
+
| explorer | @explore / @librarian | reviewer | 独立审查 | 真值+diff+evidence | review/*.md |
|
|
31
|
+
| reviewer | @oracle | researcher | 分析探索 | 真值+外部文档 | analysis/*.md |
|
|
32
|
+
| integrator | 当前主 agent | | | | |
|
|
50
33
|
|
|
51
34
|
## 连续执行循环
|
|
52
35
|
|
|
53
|
-
1. 主 session
|
|
54
|
-
2.
|
|
55
|
-
3. DONE → dispatch `aiws-reviewer`;pass→收敛 evidence;fail→worker 修复(≤3
|
|
36
|
+
1. 主 session 策展 JSONL → dispatch `aiws-worker`
|
|
37
|
+
2. 检查 Status:DONE / DONE_WITH_CONCERNS / NEEDS_CONTEXT / BLOCKED
|
|
38
|
+
3. DONE → dispatch `aiws-reviewer`;pass→收敛 evidence;fail→worker 修复(≤3)
|
|
56
39
|
4. DONE_WITH_CONCERNS → 先 `ws-quality-review`
|
|
57
|
-
5. NEEDS_CONTEXT → 补上下文重试(≤2
|
|
58
|
-
6. BLOCKED → 输出 blocker
|
|
40
|
+
5. NEEDS_CONTEXT → 补上下文重试(≤2);仍失败→回退单 agent
|
|
41
|
+
6. BLOCKED → 输出 blocker,不继续
|
|
59
42
|
|
|
60
43
|
## 上下文策展
|
|
61
44
|
|
|
62
|
-
1.
|
|
63
|
-
2. 展开 glob(替换 `<id>`)
|
|
64
|
-
3. 委托者调整(添加/删除/调整 priority/sections)
|
|
65
|
-
4. 预算检查:high+medium ≤5 文件,总行数 ≤4000
|
|
66
|
-
5. 写入 `.aiws/changes/<id>/analysis/<role>-context.jsonl`
|
|
45
|
+
1. 读合同 `contextFiles` → 2. 展开 glob(`<id>`)→ 3. 委托者调整(增删/priority/sections)→ 4. 预算 high+medium ≤5 文件、总行 ≤4000 → 5. 写 `.aiws/changes/<id>/analysis/<role>-context.jsonl`
|
|
67
46
|
|
|
68
|
-
插件 `aiws-inject-context`
|
|
47
|
+
插件 `aiws-inject-context` 自动注入;`task()` 指定 `role: <role>` 即可。
|
|
69
48
|
|
|
70
49
|
## 子 agent 返回协议
|
|
71
50
|
|
|
@@ -91,13 +70,10 @@ Context Curation: .aiws/changes/<id>/analysis/worker-context.jsonl
|
|
|
91
70
|
|
|
92
71
|
## 委托者检查清单
|
|
93
72
|
|
|
94
|
-
|
|
73
|
+
**派遣前:** `[ ] prompt 含上下文引用` `[ ] JSONL 已写` `[ ] 预算通过` `[ ] readScope/writeScope/artifactTargets 已声明`
|
|
95
74
|
|
|
96
|
-
|
|
75
|
+
**返回后:** `[ ] 解析 Status` `[ ] 非 DONE→按规则处理` `[ ] 非 DONE→记入 delegation-decisions.md` `[ ] handoff 存在且非空`
|
|
97
76
|
|
|
98
|
-
|
|
99
|
-
- 不让 `ws-delegate` 变成第二套 orchestrator
|
|
100
|
-
- 不让 delegated agent 越权写未授权文件
|
|
101
|
-
- 不跳过 submodule drift check(若 `.gitmodules` 存在)
|
|
77
|
+
**安全:** 不把 `ws-delegate` 做成第二套 orchestrator;delegated agent 不越权写未授权文件;有 `.gitmodules` 时不跳过 submodule drift check。
|
|
102
78
|
|
|
103
79
|
> 运行时行为约束:`packages/spec/docs/run-behavior-guidelines.md`
|
|
@@ -5,23 +5,18 @@ description: 使用时机:需要修改代码、配置、测试时。触发词
|
|
|
5
5
|
|
|
6
6
|
用中文输出(命令/路径/代码标识符保持原样不翻译)。
|
|
7
7
|
|
|
8
|
-
目标:在 AIWS
|
|
9
|
-
|
|
10
|
-
阶段定位:implementation 阶段。
|
|
8
|
+
目标:在 AIWS 约束下完成可回放、可验证的小步交付。阶段:implementation。
|
|
11
9
|
|
|
12
10
|
## 必需输入
|
|
13
11
|
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
- 当前 `change/<change-id>` 上下文或等价变更归因
|
|
12
|
+
- 真值:`AI_PROJECT.md` / `REQUIREMENTS.md` / `AI_WORKSPACE.md`
|
|
13
|
+
- 归因:`Req_ID` 或 `Problem_ID`;`change/<change-id>` 上下文
|
|
14
|
+
- medium/complex:已通过 `$ws-plan` / `$ws-plan-verify` 的计划
|
|
18
15
|
|
|
19
16
|
## 必需输出
|
|
20
17
|
|
|
21
|
-
- `变更文件(Changed):`
|
|
22
|
-
-
|
|
23
|
-
- `证据(Evidence):` `plan/...`、`.aiws/changes/<change-id>/...` 等证据路径
|
|
24
|
-
- `Next:` 若准备提交,建议 `$ws-review` 或 `$ws-commit`
|
|
18
|
+
- `变更文件(Changed):` / `验证(Verify):` / `证据(Evidence):` 路径
|
|
19
|
+
- `Next:` 准备提交时建议 `$ws-review` 或 `$ws-commit`
|
|
25
20
|
|
|
26
21
|
## 前置条件(硬阻断 — 必须最先检查)
|
|
27
22
|
|
|
@@ -33,58 +28,46 @@ description: 使用时机:需要修改代码、配置、测试时。触发词
|
|
|
33
28
|
|
|
34
29
|
## TDD 约束(强制)
|
|
35
30
|
|
|
36
|
-
|
|
37
|
-
1. **RED
|
|
38
|
-
|
|
39
|
-
3. **REFACTOR**:重构,保持测试通过
|
|
40
|
-
禁止:先写实现再补测试 / 跳过测试直接提交。
|
|
41
|
-
修改后自检:`lint → typecheck → test`(项目无对应脚本则跳过)。
|
|
31
|
+
新代码/业务逻辑改动必须 RED-GREEN-REFACTOR:
|
|
32
|
+
1. **RED**:先写测试并确认失败 → 2. **GREEN**:最小实现通过 → 3. **REFACTOR**:保持绿
|
|
33
|
+
禁止先实现后补测 / 跳过测试提交。改后自检:`lint → typecheck → test`(无脚本则跳过)。
|
|
42
34
|
|
|
43
35
|
## 完成判定
|
|
44
36
|
|
|
45
|
-
|
|
37
|
+
改动已落盘、验证已执行或已说明未执行原因、证据可回放 → 可进 review/commit。
|
|
46
38
|
|
|
47
39
|
## 建议流程
|
|
48
40
|
|
|
49
41
|
### 1. Preflight
|
|
50
42
|
|
|
51
|
-
|
|
52
|
-
- 中大型任务:先用 `$ws-plan` 生成 `plan/` 工件,并默认执行 3.1 自我修正循环
|
|
53
|
-
- 已有计划:先 `$ws-plan-verify`,通过后进入实现
|
|
54
|
-
- `$ws-plan` 已创建 worktree:直接在其中继续
|
|
43
|
+
定位项目根,读真值,输出约束摘要。中大型先 `$ws-plan`(默认走 3.1);已有计划先 `$ws-plan-verify`;已有 worktree 则直接继续。
|
|
55
44
|
|
|
56
45
|
### 1.5 Spec Refresh(进入实现前必做)
|
|
57
46
|
|
|
58
|
-
重读 `AI_PROJECT.md`
|
|
47
|
+
重读 `AI_PROJECT.md` 安全边界与 `REQUIREMENTS.md` 相关条目,输出 2-3 段摘要。
|
|
59
48
|
|
|
60
49
|
### 2. 建立变更归因
|
|
61
50
|
|
|
62
|
-
- `git status --porcelain`
|
|
63
|
-
-
|
|
64
|
-
-
|
|
65
|
-
- 有 submodule:准备好 `submodules.targets`(`aiws change start` 自动检测 `.gitmodules`)
|
|
51
|
+
- `git status --porcelain` 仅有计划/工件 → 继续
|
|
52
|
+
- 新建:`aiws change start <change-id> --hooks --no-switch`;切换前确认无未提交改动再 `git switch change/<change-id>`
|
|
53
|
+
- submodule:准备 `submodules.targets`(`aiws change start` 自动检测 `.gitmodules`)
|
|
66
54
|
|
|
67
55
|
### 3. 实现策略:默认 dispatch aiws-worker(Subagent-First)
|
|
68
56
|
|
|
69
57
|
详见 `packages/spec/docs/opencode-subagent-first.md`。
|
|
70
|
-
- 主 session
|
|
71
|
-
- worker 返回后派发 `aiws-reviewer`
|
|
72
|
-
- **Inline escape hatch**:用户说"直接改"
|
|
73
|
-
-
|
|
58
|
+
- 主 session **默认不直接写代码**;`$ws-delegate` 派发 `aiws-worker`(`task()` 加 `role: worker`)
|
|
59
|
+
- worker 返回后派发 `aiws-reviewer` 独立审查,再 fix 或收敛 evidence
|
|
60
|
+
- **Inline escape hatch**:用户说"直接改"/`do it inline` 时可直写,须落盘记录理由
|
|
61
|
+
- 验证先行:确认 `AI_WORKSPACE.md` 验证命令;不明确则先补入口再实现
|
|
74
62
|
|
|
75
63
|
### 3.1 自我修正循环(evaluate-optimize)——必经步骤
|
|
76
64
|
|
|
77
|
-
dispatch 前最多 **2
|
|
78
|
-
适用:所有非 trivial 改动。注意:不替代 `$ws-review` 正式 gate。
|
|
65
|
+
dispatch 前最多 **2 轮**:产出 → 主 session 检查(lint/typecheck/模式)→ 有问题则修正;2 轮后仍有问题升级 `$ws-review`。适用非 trivial;不替代 `$ws-review` 正式 gate。
|
|
79
66
|
|
|
80
67
|
### 4. 其他规则
|
|
81
68
|
|
|
82
|
-
- 需求调整:`$ws-req-review` →
|
|
83
|
-
-
|
|
84
|
-
- 验证:运行 `AI_WORKSPACE.md` 命令;未运行不声称已运行
|
|
85
|
-
- 多步任务用 `update_plan` 跟踪
|
|
86
|
-
- 提交前门禁:`aiws validate .`
|
|
87
|
-
- 交付收尾:`$ws-finish`
|
|
69
|
+
- 需求调整:`$ws-req-review` → `$ws-req-change`;最小改动归因到 `REQUIREMENTS.md` 或 `issues/problem-issues.csv`
|
|
70
|
+
- 验证跑 `AI_WORKSPACE.md` 命令(未运行不声称已运行);多步用 `update_plan`;提交前 `aiws validate .`;收尾 `$ws-finish`
|
|
88
71
|
|
|
89
72
|
## 输出要求
|
|
90
73
|
|
|
@@ -23,34 +23,21 @@ description: 使用时机:需要前端设计、UI/UX 实现时。触发词:
|
|
|
23
23
|
- `Interaction thesis:` 2-3 个动效想法及其如何改善层级/氛围/可感知性
|
|
24
24
|
|
|
25
25
|
## 设计默认值
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
- 默认最多两套字体、一种强调色;已有品牌系统则优先跟随
|
|
31
|
-
- 优先靠留白、尺度、裁切、对比、对齐建立层级,再考虑装饰
|
|
26
|
+
- 构图优先于组件库;第一屏偏海报感,非文档感
|
|
27
|
+
- 强视觉锚点:大图 / 主视觉平面 / 产品画面 / 主数据工作区
|
|
28
|
+
- 避免卡片墙;用 section / column / divider / media / list / plain layout
|
|
29
|
+
- ≤两套字体、一种强调色(有品牌系统则跟随);靠留白、尺度、裁切、对比、对齐建层级
|
|
32
30
|
|
|
33
31
|
## Landing 规则
|
|
34
|
-
|
|
35
|
-
-
|
|
36
|
-
|
|
37
|
-
-
|
|
38
|
-
- Final CTA:开始、注册、联系、访问
|
|
39
|
-
Hero 强约束:
|
|
40
|
-
- 一个 section 只承载一个 dominant idea
|
|
41
|
-
- 默认 full-bleed hero;仅内层文字列约束宽度
|
|
42
|
-
- 品牌名 > headline > body > CTA
|
|
43
|
-
- 不要 hero cards / stat strips / logo clouds / pill soup / floating dashboards
|
|
44
|
-
- headline desktop 约 2-3 行;mobile 一眼读完
|
|
45
|
-
- 有固定 header 时占用首屏预算;header + hero 不超出 viewport
|
|
46
|
-
- 若去掉主视觉后首屏仍几乎成立,说明图像太弱
|
|
32
|
+
结构:Hero(名/承诺/CTA/主视觉)→ Support(能力/证明)→ Detail(氛围/流程/故事)→ Final CTA
|
|
33
|
+
Hero:每 section 一个 dominant idea;默认 full-bleed(仅文字区限宽);品牌名 > headline > body > CTA
|
|
34
|
+
禁止:hero cards / stat strips / logo clouds / pill soup / floating dashboards
|
|
35
|
+
headline desktop 约 2-3 行、mobile 一眼读完;header+hero 不超 viewport;主视觉去掉后首屏仍成立=图像太弱
|
|
47
36
|
|
|
48
37
|
## App-UI 规则
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
- 不要把常规产品 UI 做成营销落地页
|
|
53
|
-
- 文案优先 orientation / status / action;不要首页口号 / 情绪隐喻 / 执行摘要横幅
|
|
38
|
+
- 克制:少色、少 chrome、清晰栅格、可扫读;primary workspace → nav → secondary context → action
|
|
39
|
+
- card 仅作交互容器,否则 plain layout;勿把产品 UI 做成营销页
|
|
40
|
+
- 文案偏 orientation / status / action;忌口号 / 情绪隐喻 / 摘要横幅
|
|
54
41
|
|
|
55
42
|
## 图像与媒体
|
|
56
43
|
- 图像必须承担叙事任务,不能只是补背景
|
|
@@ -78,14 +65,9 @@ Hero 强约束:
|
|
|
78
65
|
- 图像上的文字必须保证对比度与点击区域可用
|
|
79
66
|
- 必须同时考虑 desktop / mobile;验证命令优先引用 `AI_WORKSPACE.md`
|
|
80
67
|
|
|
81
|
-
##
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
## 实现检查(交付前自检)
|
|
85
|
-
- 第一屏能否一眼看出品牌/产品;是否有明确视觉锚点
|
|
86
|
-
- 只扫标题能否理解页面;每个 section 是否只有一个职责
|
|
87
|
-
- card 是否真有必要;动效是否真正提升层级/氛围
|
|
88
|
-
- 去掉装饰阴影后页面是否仍成立
|
|
68
|
+
## 实现检查(交付前)
|
|
69
|
+
- 首屏品牌/锚点明确;扫标题即可懂页;每 section 单一职责
|
|
70
|
+
- card 有必要;动效真提升层级;去装饰阴影后页面仍成立
|
|
89
71
|
|
|
90
72
|
## 输出要求
|
|
91
73
|
- `Mode:` `landing | app-ui | polish-only`
|