gsd-lite 0.7.5 → 0.7.6

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.
@@ -13,7 +13,7 @@
13
13
  "name": "gsd",
14
14
  "source": "./",
15
15
  "description": "AI orchestration tool — GSD management shell + Superpowers quality core. 5 commands, 4 agents, 5 workflows, MCP server, context monitoring.",
16
- "version": "0.7.5",
16
+ "version": "0.7.6",
17
17
  "keywords": [
18
18
  "orchestration",
19
19
  "mcp",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gsd",
3
- "version": "0.7.5",
3
+ "version": "0.7.6",
4
4
  "description": "AI orchestration tool for Claude Code — GSD management shell + Superpowers quality core",
5
5
  "author": {
6
6
  "name": "sdsrss",
package/README.md CHANGED
@@ -291,7 +291,7 @@ gsd-lite/
291
291
  │ ├── gsd-session-stop.cjs # Graceful shutdown with crash markers
292
292
  │ ├── gsd-statusline.cjs # StatusLine display (composite-aware)
293
293
  │ └── lib/ # Shared hook utilities (gsd-finder, composite statusline, semver)
294
- ├── tests/ # 966 tests (unit + simulation + E2E integration)
294
+ ├── tests/ # 972 tests (unit + simulation + E2E integration)
295
295
  ├── cli.js # Install/uninstall CLI entry
296
296
  ├── install.js # Installation script (plugin-aware, idempotent)
297
297
  └── uninstall.js # Uninstall script
@@ -300,7 +300,7 @@ gsd-lite/
300
300
  ## Testing
301
301
 
302
302
  ```bash
303
- npm test # Run all 966 tests
303
+ npm test # Run all 972 tests
304
304
  npm run test:coverage # Tests + coverage report (94%+ lines, 83%+ branches)
305
305
  npm run lint # Biome lint
306
306
  node --test tests/file.js # Run a single test file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gsd-lite",
3
- "version": "0.7.5",
3
+ "version": "0.7.6",
4
4
  "description": "AI orchestration tool for Claude Code — GSD management shell + Superpowers quality core",
5
5
  "type": "module",
6
6
  "bin": {
package/src/server.js CHANGED
@@ -144,7 +144,7 @@ const TOOLS = [
144
144
  },
145
145
  run_verify: {
146
146
  type: 'boolean',
147
- description: 'When true, run lint/typecheck/test during handoff evaluation',
147
+ description: 'Assert that verification was run externally; if true without a verification object, returns INVALID_INPUT. The state layer does not execute external tools.',
148
148
  },
149
149
  direction_ok: {
150
150
  type: 'boolean',
@@ -1,4 +1,4 @@
1
- import { read, reclassifyReviewLevel } from '../state/index.js';
1
+ import { read, reclassifyReviewLevel, selectRunnableTask } from '../state/index.js';
2
2
  import { validateExecutorResult } from '../../schema.js';
3
3
  import {
4
4
  MAX_DEBUG_RETRY,
@@ -101,8 +101,20 @@ export async function handleExecutorResult({ result, basePath = process.cwd() }
101
101
 
102
102
  if (result.outcome === 'blocked') {
103
103
  const { blocked_reason, unblock_condition } = getBlockedReasonFromResult(result);
104
+ // Probe whether other tasks remain runnable after this one is blocked.
105
+ // Design (docs/gsd-lite-design.md §1399): awaiting_user fires only when
106
+ // 0 runnable tasks remain — blocked-with-others-runnable continues execution.
107
+ const probePhase = {
108
+ ...phase,
109
+ todo: phase.todo.map((t) => (t.id === task.id
110
+ ? { ...t, lifecycle: 'blocked', blocked_reason, unblock_condition }
111
+ : t)),
112
+ };
113
+ const probe = selectRunnableTask(probePhase, state);
114
+ const hasOtherRunnable = !!probe?.task;
115
+
104
116
  const persistError = await persist(basePath, {
105
- workflow_mode: 'awaiting_user',
117
+ workflow_mode: hasOtherRunnable ? 'executing_task' : 'awaiting_user',
106
118
  current_task: null,
107
119
  current_review: null,
108
120
  phases: [{
@@ -120,8 +132,8 @@ export async function handleExecutorResult({ result, basePath = process.cwd() }
120
132
 
121
133
  return {
122
134
  success: true,
123
- action: 'awaiting_user',
124
- workflow_mode: 'awaiting_user',
135
+ action: hasOtherRunnable ? 'continue_execution' : 'awaiting_user',
136
+ workflow_mode: hasOtherRunnable ? 'executing_task' : 'awaiting_user',
125
137
  task_id: task.id,
126
138
  blockers: getBlockedTasks({ todo: [{ id: task.id, lifecycle: 'blocked', blocked_reason, unblock_condition }] }),
127
139
  };
@@ -511,6 +511,13 @@ export async function phaseComplete({
511
511
  ? verificationPassed(verificationResult)
512
512
  : phase.phase_handoff.tests_passed === true;
513
513
  if (!testsPassed) {
514
+ if (!verificationResult) {
515
+ return {
516
+ error: true,
517
+ code: ERROR_CODES.HANDOFF_GATE,
518
+ message: 'Handoff gate not met: verification required. Run lint/typecheck/test externally, then call phase-complete with verification: { lint: { exit_code }, typecheck: { exit_code }, test: { exit_code } }',
519
+ };
520
+ }
514
521
  return {
515
522
  error: true,
516
523
  code: ERROR_CODES.HANDOFF_GATE,
@@ -163,21 +163,16 @@
163
163
  | `await_recovery_decision` | 工作流处于 failed 状态。向用户展示失败信息和恢复选项 (retry/skip/replan) |
164
164
 
165
165
  **`phase-complete` 参数:**
166
+
167
+ 编排器必须先用 Bash 外部执行 lint/typecheck/test (state 层不自动跑外部工具),然后把结果作为 `verification` 传入:
166
168
  ```
167
169
  phase-complete({
168
170
  phase_id: <当前 phase 编号>,
169
- run_verify: true, // 自动运行 lint/typecheck/test
170
- direction_ok: true // 方向校验通过 (如有偏差设为 false)
171
- })
172
- ```
173
- 如果没有 lint/typecheck/test 工具,可改用 `verification` 参数传入预计算结果:
174
- ```
175
- phase-complete({
176
- phase_id: <phase>,
177
171
  verification: { lint: {exit_code: 0}, typecheck: {exit_code: 0}, test: {exit_code: 0} },
178
- direction_ok: true
172
+ direction_ok: true // 方向校验通过 (如有偏差设为 false)
179
173
  })
180
174
  ```
175
+ `run_verify: true` 只是声明"已外部跑过",不提供 `verification` 时会返回 INVALID_INPUT,用于防止调用方忘记传结果。如果项目缺少某项脚本 (例如无 typecheck),跑对应工具时返回 0 视为通过即可 (约定: "命令不存在" = 不适用 = 通过)。
181
176
  </execution_loop>
182
177
 
183
178
  ## STEP 12 — 最终报告