@ai-content-space/loopx 0.1.7 → 0.1.9
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 +2 -1
- package/README.zh-CN.md +2 -1
- package/package.json +1 -1
- package/plugins/loopx/.codex-plugin/plugin.json +1 -1
- package/plugins/loopx/skills/archive/SKILL.md +1 -1
- package/plugins/loopx/skills/autopilot/SKILL.md +1 -1
- package/plugins/loopx/skills/build/SKILL.md +1 -1
- package/plugins/loopx/skills/clarify/SKILL.md +1 -1
- package/plugins/loopx/skills/debug/SKILL.md +1 -1
- package/plugins/loopx/skills/go-style/SKILL.md +1 -1
- package/plugins/loopx/skills/kratos/SKILL.md +1 -1
- package/plugins/loopx/skills/plan/SKILL.md +1 -1
- package/plugins/loopx/skills/review/SKILL.md +8 -5
- package/plugins/loopx/skills/tdd/SKILL.md +1 -1
- package/plugins/loopx/skills/verify/SKILL.md +1 -1
- package/scripts/codex-workflow-hook.mjs +7 -3
- package/skills/archive/SKILL.md +1 -1
- package/skills/autopilot/SKILL.md +1 -1
- package/skills/build/SKILL.md +1 -1
- package/skills/clarify/SKILL.md +1 -1
- package/skills/debug/SKILL.md +1 -1
- package/skills/go-style/SKILL.md +1 -1
- package/skills/kratos/SKILL.md +1 -1
- package/skills/plan/SKILL.md +1 -1
- package/skills/review/SKILL.md +8 -5
- package/skills/tdd/SKILL.md +1 -1
- package/skills/verify/SKILL.md +1 -1
- package/src/cli.mjs +9 -0
- package/src/html-views.mjs +55 -4
- package/src/next-skill.mjs +7 -0
- package/src/workflow.mjs +16 -14
package/README.md
CHANGED
|
@@ -498,6 +498,7 @@ node --test test/*.test.mjs
|
|
|
498
498
|
node scripts/install-skills.mjs --check
|
|
499
499
|
node --test plugins/loopx/scripts/plugin-install.test.mjs
|
|
500
500
|
node src/cli.mjs --help
|
|
501
|
+
node src/cli.mjs --version
|
|
501
502
|
node src/cli.mjs doctor
|
|
502
503
|
node src/cli.mjs status --json
|
|
503
504
|
```
|
|
@@ -521,4 +522,4 @@ node src/cli.mjs status --json
|
|
|
521
522
|
|
|
522
523
|
## Version
|
|
523
524
|
|
|
524
|
-
Current npm package version: `0.1.
|
|
525
|
+
Current npm package version: `0.1.9`.
|
package/README.zh-CN.md
CHANGED
|
@@ -509,6 +509,7 @@ node --test test/*.test.mjs
|
|
|
509
509
|
node scripts/install-skills.mjs --check
|
|
510
510
|
node --test plugins/loopx/scripts/plugin-install.test.mjs
|
|
511
511
|
node src/cli.mjs --help
|
|
512
|
+
node src/cli.mjs --version
|
|
512
513
|
node src/cli.mjs doctor
|
|
513
514
|
node src/cli.mjs status --json
|
|
514
515
|
```
|
|
@@ -532,4 +533,4 @@ node src/cli.mjs status --json
|
|
|
532
533
|
|
|
533
534
|
## 版本
|
|
534
535
|
|
|
535
|
-
当前 npm 包版本:`0.1.
|
|
536
|
+
当前 npm 包版本:`0.1.9`。
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@ name: archive
|
|
|
3
3
|
description: "Archives an approved loopx change delta into long-lived specs and writes an ADR candidate after done approval. Not for active builds or unapproved reviews."
|
|
4
4
|
when_to_use: "archive, done workflow, spec delta, long-lived specs, ADR candidate, review approved, 归档, 同步规格"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
argument-hint: "<workflow slug>"
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ name: autopilot
|
|
|
3
3
|
description: "Runs one bounded autonomous loopx orchestration over clarify, plan, build, and review while preserving canonical artifacts. Not for manual gate-by-gate control."
|
|
4
4
|
when_to_use: "autopilot, autonomous loopx run, end-to-end workflow, run all stages, bounded orchestration, 自动执行, 全流程"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
argument-hint: "<workflow slug>"
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ name: build
|
|
|
3
3
|
description: "Executes an approved loopx plan or review rework contract with evidence, verification, deslop, and regression gates. Not for unclear requirements or independent review."
|
|
4
4
|
when_to_use: "build, implement approved plan, execute PRD, --from-review, review rework, implementation fixes, 执行, 实现, 修改"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
argument-hint: "[--no-deslop] <approved PRD path or workflow slug> | --from-review <review artifact path>"
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ name: clarify
|
|
|
3
3
|
description: "Clarifies ambiguous loopx work into requirements, non-goals, decision boundaries, and design-ready specs before planning. Not for already-approved plans or concrete implementation tasks."
|
|
4
4
|
when_to_use: "clarify, requirements, ambiguous request, unclear scope, non-goals, decision boundaries, acceptance criteria, 需求澄清, 范围不清"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# loopx Clarify
|
|
@@ -3,7 +3,7 @@ name: debug
|
|
|
3
3
|
description: "Finds root cause for bugs, failing tests, build failures, regressions, and unexpected behavior before fixes. Not for new feature planning or routine code review."
|
|
4
4
|
when_to_use: "debug, bug, test failure, build failure, regression, unexpected behavior, root cause, 报错, 失败, 回归, 排查"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Systematic Debugging
|
|
@@ -3,7 +3,7 @@ name: go-style
|
|
|
3
3
|
description: "Applies loopx Go coding style for .go edits, tests, errors, context, naming, and interface boundaries. Not for non-Go code or Kratos-specific architecture by itself."
|
|
4
4
|
when_to_use: "go-style, Go, golang, .go files, go tests, gofmt, idiomatic Go, Go style, Go 代码"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Go Style
|
|
@@ -3,7 +3,7 @@ name: kratos
|
|
|
3
3
|
description: "Supports Go-Kratos microservices, proto/buf APIs, service/biz/data layers, middleware, auth, config, and troubleshooting. Not for generic Go style alone."
|
|
4
4
|
when_to_use: "kratos, Go-Kratos, proto, buf, service layer, biz layer, data layer, middleware, auth, config, Kratos 微服务"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Kratos
|
|
@@ -3,7 +3,7 @@ name: plan
|
|
|
3
3
|
description: "Creates a consensus-first loopx plan package with Planner, Architect, and Critic review from an approved spec. Not for unresolved requirements or direct implementation."
|
|
4
4
|
when_to_use: "plan, planning, consensus planning, PRD, architecture plan, test plan, approved clarify spec, 规划, 方案, 架构评审"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
argument-hint: "[--interactive] [--deliberate] [--direct <spec-path>] <clarified task or spec path>"
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ name: review
|
|
|
3
3
|
description: "Reviews a loopx build execution record for acceptance, code risks, evidence quality, and architecture smells. Not for doing implementation work or replanning."
|
|
4
4
|
when_to_use: "review, code review, acceptance, go no-go, execution-record, architecture smell, build complete, 审查, 验收"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
argument-hint: "<execution-record path or workflow slug>"
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -101,13 +101,16 @@ For approval:
|
|
|
101
101
|
|
|
102
102
|
```text
|
|
103
103
|
Next:
|
|
104
|
-
|
|
104
|
+
$archive <slug>
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
`$archive` consumes the pending `review -> done` completion transition before syncing specs. Do not ask the user to run a separate `loopx approve <slug> --from review --to done` command in the normal Codex-facing flow.
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
For CLI/runtime debugging only, the equivalent explicit sequence is:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
loopx approve <slug> --from review --to done
|
|
113
|
+
loopx archive <slug>
|
|
111
114
|
```
|
|
112
115
|
|
|
113
116
|
This syncs the approved `.loopx/changes/active/<change-id>/spec-delta.md` into long-lived `.loopx/specs/` files and moves the change folder under `.loopx/changes/archive/<change-id>/`.
|
|
@@ -3,7 +3,7 @@ name: tdd
|
|
|
3
3
|
description: "Guides feature and bugfix implementation through a failing test before production code and red-green-refactor discipline. Not for generated files or throwaway prototypes."
|
|
4
4
|
when_to_use: "tdd, failing test first, feature implementation, bugfix, regression test, red green refactor, 测试先行"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Test-Driven Development (TDD)
|
|
@@ -3,7 +3,7 @@ name: verify
|
|
|
3
3
|
description: "Requires fresh verification evidence before claiming work is complete, fixed, passing, review-ready, or ready to commit. Not for speculative confidence or stale results."
|
|
4
4
|
when_to_use: "verify, completion claim, fixed claim, tests pass, review-ready, commit, fresh evidence, 验证, 完成前检查"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Verification Before Completion
|
|
@@ -40,6 +40,13 @@ function nextSkill(state) {
|
|
|
40
40
|
&& state.archive_status !== 'archived') {
|
|
41
41
|
return `$archive ${state.slug}`;
|
|
42
42
|
}
|
|
43
|
+
if (state.current_stage === 'review'
|
|
44
|
+
&& state.review_verdict === 'approve'
|
|
45
|
+
&& state.pending_user_decision === 'review->done'
|
|
46
|
+
&& ['requested', 'approved'].includes(state.approval?.complete)
|
|
47
|
+
&& state.archive_status !== 'archived') {
|
|
48
|
+
return `$archive ${state.slug}`;
|
|
49
|
+
}
|
|
43
50
|
if (state.stage_status === 'awaiting-approval'
|
|
44
51
|
&& state.current_stage === 'plan'
|
|
45
52
|
&& Array.isArray(state.plan_blockers)
|
|
@@ -84,9 +91,6 @@ function nextSkill(state) {
|
|
|
84
91
|
&& state.approval?.rollback === 'approved') {
|
|
85
92
|
return `$clarify ${state.slug}`;
|
|
86
93
|
}
|
|
87
|
-
if (state.current_stage === 'review' && state.review_verdict === 'approve' && state.pending_user_decision === 'review->done') {
|
|
88
|
-
return `loopx approve ${state.slug} --from review --to done`;
|
|
89
|
-
}
|
|
90
94
|
return null;
|
|
91
95
|
}
|
|
92
96
|
|
package/skills/archive/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: archive
|
|
|
3
3
|
description: "Archives an approved loopx change delta into long-lived specs and writes an ADR candidate after done approval. Not for active builds or unapproved reviews."
|
|
4
4
|
when_to_use: "archive, done workflow, spec delta, long-lived specs, ADR candidate, review approved, 归档, 同步规格"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
argument-hint: "<workflow slug>"
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ name: autopilot
|
|
|
3
3
|
description: "Runs one bounded autonomous loopx orchestration over clarify, plan, build, and review while preserving canonical artifacts. Not for manual gate-by-gate control."
|
|
4
4
|
when_to_use: "autopilot, autonomous loopx run, end-to-end workflow, run all stages, bounded orchestration, 自动执行, 全流程"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
argument-hint: "<workflow slug>"
|
|
8
8
|
---
|
|
9
9
|
|
package/skills/build/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: build
|
|
|
3
3
|
description: "Executes an approved loopx plan or review rework contract with evidence, verification, deslop, and regression gates. Not for unclear requirements or independent review."
|
|
4
4
|
when_to_use: "build, implement approved plan, execute PRD, --from-review, review rework, implementation fixes, 执行, 实现, 修改"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
argument-hint: "[--no-deslop] <approved PRD path or workflow slug> | --from-review <review artifact path>"
|
|
8
8
|
---
|
|
9
9
|
|
package/skills/clarify/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: clarify
|
|
|
3
3
|
description: "Clarifies ambiguous loopx work into requirements, non-goals, decision boundaries, and design-ready specs before planning. Not for already-approved plans or concrete implementation tasks."
|
|
4
4
|
when_to_use: "clarify, requirements, ambiguous request, unclear scope, non-goals, decision boundaries, acceptance criteria, 需求澄清, 范围不清"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# loopx Clarify
|
package/skills/debug/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: debug
|
|
|
3
3
|
description: "Finds root cause for bugs, failing tests, build failures, regressions, and unexpected behavior before fixes. Not for new feature planning or routine code review."
|
|
4
4
|
when_to_use: "debug, bug, test failure, build failure, regression, unexpected behavior, root cause, 报错, 失败, 回归, 排查"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Systematic Debugging
|
package/skills/go-style/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: go-style
|
|
|
3
3
|
description: "Applies loopx Go coding style for .go edits, tests, errors, context, naming, and interface boundaries. Not for non-Go code or Kratos-specific architecture by itself."
|
|
4
4
|
when_to_use: "go-style, Go, golang, .go files, go tests, gofmt, idiomatic Go, Go style, Go 代码"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Go Style
|
package/skills/kratos/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: kratos
|
|
|
3
3
|
description: "Supports Go-Kratos microservices, proto/buf APIs, service/biz/data layers, middleware, auth, config, and troubleshooting. Not for generic Go style alone."
|
|
4
4
|
when_to_use: "kratos, Go-Kratos, proto, buf, service layer, biz layer, data layer, middleware, auth, config, Kratos 微服务"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Kratos
|
package/skills/plan/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: plan
|
|
|
3
3
|
description: "Creates a consensus-first loopx plan package with Planner, Architect, and Critic review from an approved spec. Not for unresolved requirements or direct implementation."
|
|
4
4
|
when_to_use: "plan, planning, consensus planning, PRD, architecture plan, test plan, approved clarify spec, 规划, 方案, 架构评审"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
argument-hint: "[--interactive] [--deliberate] [--direct <spec-path>] <clarified task or spec path>"
|
|
8
8
|
---
|
|
9
9
|
|
package/skills/review/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: review
|
|
|
3
3
|
description: "Reviews a loopx build execution record for acceptance, code risks, evidence quality, and architecture smells. Not for doing implementation work or replanning."
|
|
4
4
|
when_to_use: "review, code review, acceptance, go no-go, execution-record, architecture smell, build complete, 审查, 验收"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
argument-hint: "<execution-record path or workflow slug>"
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -101,13 +101,16 @@ For approval:
|
|
|
101
101
|
|
|
102
102
|
```text
|
|
103
103
|
Next:
|
|
104
|
-
|
|
104
|
+
$archive <slug>
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
`$archive` consumes the pending `review -> done` completion transition before syncing specs. Do not ask the user to run a separate `loopx approve <slug> --from review --to done` command in the normal Codex-facing flow.
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
For CLI/runtime debugging only, the equivalent explicit sequence is:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
loopx approve <slug> --from review --to done
|
|
113
|
+
loopx archive <slug>
|
|
111
114
|
```
|
|
112
115
|
|
|
113
116
|
This syncs the approved `.loopx/changes/active/<change-id>/spec-delta.md` into long-lived `.loopx/specs/` files and moves the change folder under `.loopx/changes/archive/<change-id>/`.
|
package/skills/tdd/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: tdd
|
|
|
3
3
|
description: "Guides feature and bugfix implementation through a failing test before production code and red-green-refactor discipline. Not for generated files or throwaway prototypes."
|
|
4
4
|
when_to_use: "tdd, failing test first, feature implementation, bugfix, regression test, red green refactor, 测试先行"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Test-Driven Development (TDD)
|
package/skills/verify/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: verify
|
|
|
3
3
|
description: "Requires fresh verification evidence before claiming work is complete, fixed, passing, review-ready, or ready to commit. Not for speculative confidence or stale results."
|
|
4
4
|
when_to_use: "verify, completion claim, fixed claim, tests pass, review-ready, commit, fresh evidence, 验证, 完成前检查"
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.9"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Verification Before Completion
|
package/src/cli.mjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
4
|
+
|
|
3
5
|
import { archiveStage, autopilotStage, approveStage, buildStage, clarifyStage, initWorkspace, planStage, reviewStage, statusSummary } from './workflow.mjs';
|
|
4
6
|
import { renderHtmlViews } from './html-views.mjs';
|
|
5
7
|
import { installBundledSkills } from './install-discovery.mjs';
|
|
@@ -7,9 +9,12 @@ import { nextSkillCommand, withNextSkill } from './next-skill.mjs';
|
|
|
7
9
|
import { doctorRuntime, migrateLegacyRuntime } from './runtime-maintenance.mjs';
|
|
8
10
|
import { setupWorkspaceContext } from './workspace-context.mjs';
|
|
9
11
|
|
|
12
|
+
const packageJson = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
|
|
13
|
+
|
|
10
14
|
function usage() {
|
|
11
15
|
return [
|
|
12
16
|
'Usage:',
|
|
17
|
+
' loopx --version',
|
|
13
18
|
' loopx init [--slug <slug>]',
|
|
14
19
|
' loopx clarify <slug> [--standard|--deep]',
|
|
15
20
|
' loopx approve <slug> --from <stage> --to <stage>',
|
|
@@ -139,6 +144,10 @@ function printHumanStatus(status) {
|
|
|
139
144
|
|
|
140
145
|
async function main() {
|
|
141
146
|
const { command, positionals, options } = parseArgs(process.argv.slice(2));
|
|
147
|
+
if (command === 'version' || command === '--version' || command === '-v') {
|
|
148
|
+
console.log(packageJson.version);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
142
151
|
if (!command || command === 'help' || command === '--help' || command === '-h') {
|
|
143
152
|
console.log(usage());
|
|
144
153
|
return;
|
package/src/html-views.mjs
CHANGED
|
@@ -11,13 +11,14 @@ const WORKFLOW_ARTIFACTS = [
|
|
|
11
11
|
{ name: 'architecture.md', label: '架构', page: 'plan.html' },
|
|
12
12
|
{ name: 'development-plan.md', label: '开发计划', page: 'plan.html' },
|
|
13
13
|
{ name: 'test-plan.md', label: '测试计划', page: 'plan.html' },
|
|
14
|
+
{ name: 'requirement-traceability.md', label: '需求覆盖矩阵', page: 'plan.html' },
|
|
14
15
|
{ name: 'execution-record.md', label: '执行记录', page: 'build.html' },
|
|
15
16
|
{ name: 'review-report.md', label: '评审报告', page: 'review.html' },
|
|
16
17
|
];
|
|
17
18
|
|
|
18
19
|
const PAGE_GROUPS = [
|
|
19
20
|
{ file: 'intake.html', title: '需求澄清', artifacts: ['spec.md'] },
|
|
20
|
-
{ file: 'plan.html', title: '计划与架构', artifacts: ['plan.md', 'architecture.md', 'development-plan.md', 'test-plan.md'] },
|
|
21
|
+
{ file: 'plan.html', title: '计划与架构', artifacts: ['plan.md', 'architecture.md', 'development-plan.md', 'test-plan.md', 'requirement-traceability.md'] },
|
|
21
22
|
{ file: 'build.html', title: '执行与验证', artifacts: ['execution-record.md'] },
|
|
22
23
|
{ file: 'review.html', title: '评审结论', artifacts: ['review-report.md'] },
|
|
23
24
|
];
|
|
@@ -84,15 +85,43 @@ function markdownToHtml(markdown) {
|
|
|
84
85
|
const html = [];
|
|
85
86
|
let inCode = false;
|
|
86
87
|
let listOpen = false;
|
|
88
|
+
let orderedListOpen = false;
|
|
87
89
|
|
|
88
90
|
const closeList = () => {
|
|
89
91
|
if (listOpen) {
|
|
90
92
|
html.push('</ul>');
|
|
91
93
|
listOpen = false;
|
|
92
94
|
}
|
|
95
|
+
if (orderedListOpen) {
|
|
96
|
+
html.push('</ol>');
|
|
97
|
+
orderedListOpen = false;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
const tableCells = (line) => line.split('|').slice(1, -1).map((cell) => cell.trim());
|
|
101
|
+
const isTableDelimiter = (line) => /^\s*\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)+\|?\s*$/.test(line);
|
|
102
|
+
const inlineMarkdown = (value) => escapeHtml(value)
|
|
103
|
+
.replace(/`([^`]+)`/g, '<code>$1</code>')
|
|
104
|
+
.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
|
|
105
|
+
const renderTable = (start) => {
|
|
106
|
+
const header = tableCells(lines[start]);
|
|
107
|
+
const rows = [];
|
|
108
|
+
let index = start + 2;
|
|
109
|
+
while (index < lines.length && lines[index].trim().startsWith('|')) {
|
|
110
|
+
rows.push(tableCells(lines[index]));
|
|
111
|
+
index += 1;
|
|
112
|
+
}
|
|
113
|
+
html.push('<table>');
|
|
114
|
+
html.push(`<thead><tr>${header.map((cell) => `<th>${inlineMarkdown(cell)}</th>`).join('')}</tr></thead>`);
|
|
115
|
+
html.push('<tbody>');
|
|
116
|
+
for (const row of rows) {
|
|
117
|
+
html.push(`<tr>${header.map((_, cellIndex) => `<td>${inlineMarkdown(row[cellIndex] || '')}</td>`).join('')}</tr>`);
|
|
118
|
+
}
|
|
119
|
+
html.push('</tbody></table>');
|
|
120
|
+
return index - 1;
|
|
93
121
|
};
|
|
94
122
|
|
|
95
|
-
for (
|
|
123
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
124
|
+
const line = lines[index];
|
|
96
125
|
if (line.startsWith('```')) {
|
|
97
126
|
if (inCode) {
|
|
98
127
|
html.push('</code></pre>');
|
|
@@ -114,12 +143,33 @@ function markdownToHtml(markdown) {
|
|
|
114
143
|
html.push(`<h${level}>${escapeHtml(line.replace(/^#{1,4}\s+/, ''))}</h${level}>`);
|
|
115
144
|
continue;
|
|
116
145
|
}
|
|
146
|
+
if (line.trim().startsWith('|') && lines[index + 1] && isTableDelimiter(lines[index + 1])) {
|
|
147
|
+
closeList();
|
|
148
|
+
index = renderTable(index);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
117
151
|
if (line.startsWith('- ')) {
|
|
152
|
+
if (orderedListOpen) {
|
|
153
|
+
html.push('</ol>');
|
|
154
|
+
orderedListOpen = false;
|
|
155
|
+
}
|
|
118
156
|
if (!listOpen) {
|
|
119
157
|
html.push('<ul>');
|
|
120
158
|
listOpen = true;
|
|
121
159
|
}
|
|
122
|
-
html.push(`<li>${
|
|
160
|
+
html.push(`<li>${inlineMarkdown(line.slice(2))}</li>`);
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (/^\d+[.)]\s+/.test(line)) {
|
|
164
|
+
if (listOpen) {
|
|
165
|
+
html.push('</ul>');
|
|
166
|
+
listOpen = false;
|
|
167
|
+
}
|
|
168
|
+
if (!orderedListOpen) {
|
|
169
|
+
html.push('<ol>');
|
|
170
|
+
orderedListOpen = true;
|
|
171
|
+
}
|
|
172
|
+
html.push(`<li>${inlineMarkdown(line.replace(/^\d+[.)]\s+/, ''))}</li>`);
|
|
123
173
|
continue;
|
|
124
174
|
}
|
|
125
175
|
if (!line.trim()) {
|
|
@@ -127,7 +177,7 @@ function markdownToHtml(markdown) {
|
|
|
127
177
|
continue;
|
|
128
178
|
}
|
|
129
179
|
closeList();
|
|
130
|
-
html.push(`<p>${
|
|
180
|
+
html.push(`<p>${inlineMarkdown(line)}</p>`);
|
|
131
181
|
}
|
|
132
182
|
closeList();
|
|
133
183
|
if (inCode) {
|
|
@@ -150,6 +200,7 @@ function statusPanels(status) {
|
|
|
150
200
|
'<section class="grid">',
|
|
151
201
|
`<div class="panel"><strong>阶段</strong><br>${escapeHtml(state.current_stage || '(none)')}</div>`,
|
|
152
202
|
`<div class="panel"><strong>状态</strong><br>${escapeHtml(state.stage_status || '(unknown)')}</div>`,
|
|
203
|
+
`<div class="panel"><strong>需求覆盖</strong><br>${escapeHtml(state.source_requirements_status || 'unknown')}</div>`,
|
|
153
204
|
`<div class="panel"><strong>下一步</strong><br><code>${escapeHtml(nextSkill || status.next_action || 'none')}</code></div>`,
|
|
154
205
|
`<div class="panel"><strong>归档</strong><br>${escapeHtml(state.archive_status || 'pending')}</div>`,
|
|
155
206
|
'</section>',
|
package/src/next-skill.mjs
CHANGED
|
@@ -19,6 +19,13 @@ export function nextSkillCommand(state) {
|
|
|
19
19
|
&& state.archive_status !== 'archived') {
|
|
20
20
|
return `$archive ${state.slug}`;
|
|
21
21
|
}
|
|
22
|
+
if (state.current_stage === 'review'
|
|
23
|
+
&& state.review_verdict === 'approve'
|
|
24
|
+
&& state.pending_user_decision === 'review->done'
|
|
25
|
+
&& ['requested', 'approved'].includes(state.approval?.complete)
|
|
26
|
+
&& state.archive_status !== 'archived') {
|
|
27
|
+
return `$archive ${state.slug}`;
|
|
28
|
+
}
|
|
22
29
|
if (state.stage_status !== 'awaiting-approval') {
|
|
23
30
|
return null;
|
|
24
31
|
}
|
package/src/workflow.mjs
CHANGED
|
@@ -720,21 +720,21 @@ async function writeRequirementTraceabilityArtifact({ root, sourceSpecPath, sour
|
|
|
720
720
|
const status = blockers.length > 0 ? 'partial' : 'complete';
|
|
721
721
|
|
|
722
722
|
await writeText(traceabilityPath, [
|
|
723
|
-
'#
|
|
723
|
+
'# 原始需求覆盖矩阵',
|
|
724
724
|
'',
|
|
725
|
-
`-
|
|
726
|
-
`-
|
|
727
|
-
`-
|
|
725
|
+
`- 来源:${sourceSpecPath}`,
|
|
726
|
+
`- 状态:${status}`,
|
|
727
|
+
`- 提取项数量:${rows.length}`,
|
|
728
728
|
'',
|
|
729
|
-
'##
|
|
729
|
+
'## 覆盖矩阵',
|
|
730
730
|
'',
|
|
731
|
-
'|
|
|
731
|
+
'| 原始需求项 | 覆盖状态 |',
|
|
732
732
|
'| --- | --- |',
|
|
733
733
|
...(rows.length > 0
|
|
734
734
|
? rows.map((row) => `| ${row.item.replace(/\|/g, '\\|')} | ${row.status} |`)
|
|
735
|
-
: ['|
|
|
735
|
+
: ['| 未检测到显式需求覆盖项 | covered |']),
|
|
736
736
|
'',
|
|
737
|
-
'##
|
|
737
|
+
'## 门禁',
|
|
738
738
|
'',
|
|
739
739
|
...(blockers.length > 0
|
|
740
740
|
? blockers.map((blocker) => `- ${blocker}`)
|
|
@@ -2248,7 +2248,7 @@ function buildCurrentEvidenceChain(state, readiness = buildReadiness(state), aut
|
|
|
2248
2248
|
evidence.push(evidenceEntry(
|
|
2249
2249
|
'review_approved',
|
|
2250
2250
|
'Review verdict is approve.',
|
|
2251
|
-
authorization.done.authorized ? '
|
|
2251
|
+
authorization.done.authorized ? 'Archive can consume the approved review -> done transition before syncing specs.' : 'Completion still requires explicit review -> done authorization.',
|
|
2252
2252
|
));
|
|
2253
2253
|
}
|
|
2254
2254
|
if (state.archive_status === 'archived' && state.spec_sync_status === 'synced') {
|
|
@@ -2371,9 +2371,7 @@ function recommendedAction(state, legacy = false) {
|
|
|
2371
2371
|
: 'Approve build -> review when execution-record.md is complete.';
|
|
2372
2372
|
case STAGES.REVIEW:
|
|
2373
2373
|
if (state.review_verdict === 'approve') {
|
|
2374
|
-
return
|
|
2375
|
-
? 'Run loopx review again to consume the approved review -> done transition.'
|
|
2376
|
-
: 'Approve review -> done to complete the workflow.';
|
|
2374
|
+
return 'Run loopx archive; archive consumes the pending review -> done completion transition before syncing specs.';
|
|
2377
2375
|
}
|
|
2378
2376
|
if (state.review_verdict === 'request-changes') {
|
|
2379
2377
|
if (state.requested_transition === TRANSITIONS.REVIEW_TO_BUILD && state.approval.build === APPROVAL_STATES.APPROVED) {
|
|
@@ -2574,7 +2572,11 @@ function nextCommandForRollbackTarget(slug, target) {
|
|
|
2574
2572
|
if (target === 'none') {
|
|
2575
2573
|
return [
|
|
2576
2574
|
'Next:',
|
|
2575
|
+
`$archive ${slug}`,
|
|
2576
|
+
'',
|
|
2577
|
+
'CLI-only equivalent:',
|
|
2577
2578
|
`loopx approve ${slug} --from review --to done`,
|
|
2579
|
+
`loopx archive ${slug}`,
|
|
2578
2580
|
].join('\n');
|
|
2579
2581
|
}
|
|
2580
2582
|
return [
|
|
@@ -2587,7 +2589,7 @@ function nextCommandForRollbackTarget(slug, target) {
|
|
|
2587
2589
|
function reviewUserMessageZh({ slug, verdict, rollbackTarget, findings }) {
|
|
2588
2590
|
const label = reviewVerdictLabel(verdict);
|
|
2589
2591
|
const next = verdict === 'APPROVE'
|
|
2590
|
-
?
|
|
2592
|
+
? `下一步:直接归档;archive 会先消费 pending 的 review -> done 完成态。\n${nextCommandForRollbackTarget(slug, 'none')}`
|
|
2591
2593
|
: `下一步:按审查发现处理,并${rollbackTargetLabel(rollbackTarget)}。\n${nextCommandForRollbackTarget(slug, rollbackTarget)}`;
|
|
2592
2594
|
const findingText = Array.isArray(findings) && findings.length > 0 ? findings.join(';') : '无额外发现。';
|
|
2593
2595
|
return `Review 结果:${slug} ${label}。审查发现:${findingText} ${next}`;
|
|
@@ -3929,7 +3931,7 @@ export async function reviewStage(cwd, slug, { reviewer = 'independent-reviewer'
|
|
|
3929
3931
|
verdict: reviewInput.verdict,
|
|
3930
3932
|
reviewMessageZh: reviewMessage,
|
|
3931
3933
|
evidenceManifest: reviewInput.evidenceManifest,
|
|
3932
|
-
followUps: ['
|
|
3934
|
+
followUps: ['执行 $archive;archive 会消费 pending 的 review -> done 完成态。'],
|
|
3933
3935
|
});
|
|
3934
3936
|
} catch (error) {
|
|
3935
3937
|
journalWarning = error instanceof Error ? error.message : String(error);
|