@ai-content-space/loopx 0.1.4 → 0.1.5
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 +39 -0
- package/README.zh-CN.md +40 -0
- package/package.json +3 -2
- package/plugins/loopx/.codex-plugin/plugin.json +1 -1
- package/plugins/loopx/skills/archive/SKILL.md +4 -1
- package/plugins/loopx/skills/autopilot/SKILL.md +4 -1
- package/plugins/loopx/skills/build/SKILL.md +7 -1
- package/plugins/loopx/skills/clarify/SKILL.md +4 -1
- package/plugins/loopx/skills/debug/SKILL.md +4 -1
- package/plugins/loopx/skills/go-style/SKILL.md +4 -1
- package/plugins/loopx/skills/kratos/SKILL.md +4 -1
- package/plugins/loopx/skills/plan/SKILL.md +4 -1
- package/plugins/loopx/skills/review/SKILL.md +7 -1
- package/plugins/loopx/skills/tdd/SKILL.md +4 -1
- package/plugins/loopx/skills/verify/SKILL.md +4 -1
- package/scripts/verify-skills.mjs +166 -0
- package/skills/RESOLVER.md +45 -0
- package/skills/archive/SKILL.md +4 -1
- package/skills/autopilot/SKILL.md +4 -1
- package/skills/build/SKILL.md +7 -1
- package/skills/clarify/SKILL.md +4 -1
- package/skills/debug/SKILL.md +4 -1
- package/skills/go-style/SKILL.md +4 -1
- package/skills/kratos/SKILL.md +4 -1
- package/skills/plan/SKILL.md +4 -1
- package/skills/review/SKILL.md +7 -1
- package/skills/tdd/SKILL.md +4 -1
- package/skills/verify/SKILL.md +4 -1
- package/src/context-manifest.mjs +2 -0
- package/src/project-discovery.mjs +163 -0
- package/src/workflow.mjs +8 -0
package/README.md
CHANGED
|
@@ -25,10 +25,12 @@ clarify -> plan -> build -> review -> approve review->done -> archive
|
|
|
25
25
|
## Features
|
|
26
26
|
|
|
27
27
|
- Installs and exposes eleven bundled loopx Codex skills: workflow skills `clarify`, `plan`, `build`, `review`, `archive`, and `autopilot`; quality support skills `debug`, `tdd`, and `verify`; and Go support skills `go-style` and `kratos`.
|
|
28
|
+
- Keeps bundled skill routing explicit in `skills/RESOLVER.md`, with deterministic governance checks for frontmatter, plugin mirrors, resolver coverage, local references, package inclusion, and version alignment.
|
|
28
29
|
- Supports npm global install and Codex plugin install through the same install/discovery core.
|
|
29
30
|
- Installs a managed Codex workflow hook that surfaces loopx workflow state and safe next-action hints inside Codex.
|
|
30
31
|
- Stores runtime state and stage artifacts locally under `.loopx/` for auditability, recovery, and migration.
|
|
31
32
|
- Stores clarify intake snapshots under `.loopx/intake/` so `.loopx/specs/` stays reserved for long-lived domain specs.
|
|
33
|
+
- Records existing project AI rule files, existing spec sources, and detected verification commands in `.loopx/config.json` during init so loopx can preserve local sources of truth while still running the full workflow.
|
|
32
34
|
- Runs `plan` with a Planner -> Architect -> Critic consensus loop by default.
|
|
33
35
|
- Writes OpenSpec-inspired change artifacts during `plan`: proposal, spec delta, design, vertical slices, tasks, and an artifact dependency graph.
|
|
34
36
|
- Provides per-repo agent context under `.loopx/agents/` and `.loopx/context/domain.md`, consumed by build/review context manifests.
|
|
@@ -174,6 +176,24 @@ The CLI is primarily for runtime, debugging, status inspection, and maintenance.
|
|
|
174
176
|
|
|
175
177
|
`loopx status` remains a CLI/runtime diagnostic command rather than a Codex skill. `loopx render` generates human-readable HTML views from existing runtime artifacts; without a slug it renders every non-legacy workflow plus the workspace index. Markdown and JSON remain the canonical machine-readable and editable sources.
|
|
176
178
|
|
|
179
|
+
## Skill Routing and Governance
|
|
180
|
+
|
|
181
|
+
The bundled skill resolver lives at:
|
|
182
|
+
|
|
183
|
+
```text
|
|
184
|
+
skills/RESOLVER.md
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
It is the human-readable routing map for the eleven bundled skills. Keep it aligned with each `skills/<name>/SKILL.md` and mirrored `plugins/loopx/skills/<name>/SKILL.md`.
|
|
188
|
+
|
|
189
|
+
Skill governance is enforced by:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
node scripts/verify-skills.mjs
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
The verifier checks that bundled skill frontmatter is triggerable and bounded, `metadata.version` matches `package.json`, plugin skill mirrors match the canonical skills, `skills/RESOLVER.md` covers every bundled skill without stale bundled-skill references, local skill references exist, the plugin manifest version matches the package version, and the verifier itself is included in the npm package.
|
|
196
|
+
|
|
177
197
|
## Skills
|
|
178
198
|
|
|
179
199
|
### clarify
|
|
@@ -337,11 +357,14 @@ loopx writes runtime state under `.loopx/` in the current project:
|
|
|
337
357
|
review.html
|
|
338
358
|
plan-reviews/
|
|
339
359
|
build-support/
|
|
360
|
+
review-support/
|
|
340
361
|
autopilot/
|
|
341
362
|
<slug>/
|
|
342
363
|
run.json
|
|
343
364
|
```
|
|
344
365
|
|
|
366
|
+
`config.json` records the loopx product contract plus init-time project discovery: existing AI rules such as `AGENTS.md` / `CLAUDE.md` / Cursor / Copilot files, existing spec sources such as `docs/changes` or ADR/RFC folders, and detected install/test/lint/typecheck/build/E2E commands. This does not create a lighter loopx mode; it keeps project facts available to `plan`, `build`, and `review` while preserving loopx's full closed workflow.
|
|
367
|
+
|
|
345
368
|
`intake` contains immutable clarify snapshots for a specific request. `workflows` contains the active runtime working set. `changes` contains the proposed change delta for the current request. `specs` contains accepted long-lived behavior after archive.
|
|
346
369
|
|
|
347
370
|
`views/` and `workflows/<slug>/view/` are derived HTML reading views generated by `loopx render`. They are for human review only and are safe to regenerate; agents and tooling should continue to read and update the Markdown and JSON artifacts.
|
|
@@ -359,6 +382,7 @@ Documents users normally need to watch:
|
|
|
359
382
|
Documents users may read and modify as workflow fact sources:
|
|
360
383
|
|
|
361
384
|
- `.loopx/workflows/<slug>/*.md`: editable working-copy artifacts for the active workflow; changes still need to pass the relevant stage gates.
|
|
385
|
+
- `.loopx/config.json`: workspace configuration, project-rule/spec-source discovery, and default verification commands; update it if the repository's canonical commands or project-rule files change.
|
|
362
386
|
- `.loopx/context/domain.md` and `.loopx/agents/*.md`: project context, domain vocabulary, and agent collaboration guidance.
|
|
363
387
|
- `.loopx/changes/active/<change-id>/*.md`: plan-generated change proposal, design, tasks, and spec delta; edits should be followed by plan/build/review validation.
|
|
364
388
|
- `.loopx/specs/<domain>/spec.md`: long-lived archived behavior specs; normally synced by `archive`, and manual edits should stay consistent with later change deltas.
|
|
@@ -392,6 +416,12 @@ Check skill discovery state only:
|
|
|
392
416
|
node scripts/install-skills.mjs --check
|
|
393
417
|
```
|
|
394
418
|
|
|
419
|
+
Verify bundled skill governance:
|
|
420
|
+
|
|
421
|
+
```bash
|
|
422
|
+
node scripts/verify-skills.mjs
|
|
423
|
+
```
|
|
424
|
+
|
|
395
425
|
## Codex Workflow Hook
|
|
396
426
|
|
|
397
427
|
`install-skills.mjs` and the Codex plugin installer automatically install `scripts/codex-workflow-hook.mjs` to:
|
|
@@ -443,9 +473,17 @@ Run tests:
|
|
|
443
473
|
npm test
|
|
444
474
|
```
|
|
445
475
|
|
|
476
|
+
`npm test` runs bundled skill governance first, then the Node test suites:
|
|
477
|
+
|
|
478
|
+
```bash
|
|
479
|
+
node scripts/verify-skills.mjs
|
|
480
|
+
node --test test/*.test.mjs
|
|
481
|
+
```
|
|
482
|
+
|
|
446
483
|
Useful verification commands:
|
|
447
484
|
|
|
448
485
|
```bash
|
|
486
|
+
node scripts/verify-skills.mjs
|
|
449
487
|
node --test test/*.test.mjs
|
|
450
488
|
node scripts/install-skills.mjs --check
|
|
451
489
|
node --test plugins/loopx/scripts/plugin-install.test.mjs
|
|
@@ -462,6 +500,7 @@ node src/cli.mjs status --json
|
|
|
462
500
|
- `README.zh-CN.md`
|
|
463
501
|
- `package.json`
|
|
464
502
|
- `scripts/install-skills.mjs`
|
|
503
|
+
- `scripts/verify-skills.mjs`
|
|
465
504
|
- `scripts/codex-stop-hook.mjs`
|
|
466
505
|
- `scripts/codex-workflow-hook.mjs`
|
|
467
506
|
- `assets/logo.svg`
|
package/README.zh-CN.md
CHANGED
|
@@ -27,10 +27,12 @@ clarify -> plan -> build -> review -> approve review->done -> archive
|
|
|
27
27
|
## 特性
|
|
28
28
|
|
|
29
29
|
- 安装并公开 11 个 loopx Codex skills:工作流 skills `clarify`、`plan`、`build`、`review`、`archive`、`autopilot`,质量辅助 skills `debug`、`tdd`、`verify`,以及 Go 支持 skills `go-style`、`kratos`。
|
|
30
|
+
- 通过 `skills/RESOLVER.md` 明确 bundled skill 路由,并用确定性治理脚本检查 frontmatter、plugin 镜像、resolver 覆盖、本地引用、发布包包含项和版本一致性。
|
|
30
31
|
- 支持 npm 全局安装和 Codex plugin 安装,两种安装方式共享同一套 install/discovery 逻辑。
|
|
31
32
|
- 自动安装 loopx 管理的 Codex workflow hook,在 Codex 中提示当前 workflow 状态和安全下一步。
|
|
32
33
|
- 所有运行时状态和阶段产物都写入项目本地 `.loopx/`,便于审计、恢复和迁移。
|
|
33
34
|
- clarify 需求快照写入 `.loopx/intake/`,让 `.loopx/specs/` 只承载长期领域规格。
|
|
35
|
+
- init 时会把已有项目 AI 规则、既有 spec 来源和自动发现的验证命令记录到 `.loopx/config.json`,让 loopx 保留项目原有事实源,同时继续执行完整闭环。
|
|
34
36
|
- `plan` 默认采用 Planner -> Architect -> Critic 的共识规划循环。
|
|
35
37
|
- `plan` 会写入借鉴 OpenSpec 的 change artifacts:proposal、spec delta、design、tasks 和 artifact dependency graph。
|
|
36
38
|
- 提供项目级 agent context:`.loopx/agents/` 和 `.loopx/context/domain.md`,供 build/review 的 context manifest 消费。
|
|
@@ -176,6 +178,24 @@ CLI 主要用于运行时、调试、状态观察和维护。日常面向 Codex
|
|
|
176
178
|
|
|
177
179
|
`loopx status` 仍然是 CLI/runtime 诊断命令,不作为单独 Codex skill 暴露。`loopx render` 会基于现有运行时产物生成给人阅读的 HTML 视图;不传 slug 时会渲染所有非 legacy workflow 和工作区首页。Markdown 和 JSON 仍然是机器可读、可编辑的事实源。
|
|
178
180
|
|
|
181
|
+
## Skill 路由与治理
|
|
182
|
+
|
|
183
|
+
bundled skill resolver 位于:
|
|
184
|
+
|
|
185
|
+
```text
|
|
186
|
+
skills/RESOLVER.md
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
它是 11 个 bundled skills 的可读路由表。修改任一 `skills/<name>/SKILL.md` 或镜像的 `plugins/loopx/skills/<name>/SKILL.md` 时,都要保持 resolver 同步。
|
|
190
|
+
|
|
191
|
+
skill 治理由下面的确定性脚本执行:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
node scripts/verify-skills.mjs
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
该脚本会检查 bundled skill frontmatter 是否可触发且有排除边界、`metadata.version` 是否匹配 `package.json`、plugin skill 镜像是否与 canonical skills 一致、`skills/RESOLVER.md` 是否覆盖所有 bundled skills 且没有陈旧 bundled-skill 引用、本地 skill 引用是否存在、plugin manifest 版本是否匹配 package 版本,以及 verifier 本身是否进入 npm 发布包。
|
|
198
|
+
|
|
179
199
|
## Skill 说明
|
|
180
200
|
|
|
181
201
|
### clarify
|
|
@@ -199,6 +219,7 @@ CLI 主要用于运行时、调试、状态观察和维护。日常面向 Codex
|
|
|
199
219
|
- `.loopx/changes/active/<change-id>/spec-delta.md`
|
|
200
220
|
- `.loopx/changes/active/<change-id>/design.md`
|
|
201
221
|
- `.loopx/changes/active/<change-id>/tasks.md`
|
|
222
|
+
- `.loopx/changes/active/<change-id>/slices.json`
|
|
202
223
|
- `.loopx/changes/active/<change-id>/artifact-graph.json`
|
|
203
224
|
- `.loopx/workflows/<slug>/plan.md`
|
|
204
225
|
- `.loopx/workflows/<slug>/architecture.md`
|
|
@@ -347,11 +368,14 @@ loopx 在当前项目下写入 `.loopx/`:
|
|
|
347
368
|
review.html
|
|
348
369
|
plan-reviews/
|
|
349
370
|
build-support/
|
|
371
|
+
review-support/
|
|
350
372
|
autopilot/
|
|
351
373
|
<slug>/
|
|
352
374
|
run.json
|
|
353
375
|
```
|
|
354
376
|
|
|
377
|
+
`config.json` 记录 loopx 产品契约和 init 时的项目发现结果:已有 AI 规则文件,例如 `AGENTS.md`、`CLAUDE.md`、Cursor / Copilot 规则;已有 spec 来源,例如 `docs/changes`、ADR/RFC 目录;以及自动发现的 install/test/lint/typecheck/build/E2E 命令。这不会引入轻量版 loopx;它只是让 `plan`、`build`、`review` 能看到项目事实,同时保持完整闭环。
|
|
378
|
+
|
|
355
379
|
`intake` 保存一次需求的 clarify 快照;`workflows` 保存当前任务的运行时工作副本;`changes` 保存本次需求对长期行为的 change delta;`specs` 只保存 archive 后的长期领域行为契约。
|
|
356
380
|
|
|
357
381
|
`views/` 和 `workflows/<slug>/view/` 是 `loopx render` 生成的派生 HTML 阅读视图,只服务于人的浏览和评审,可以随时重新生成;agent 和工具仍应读取、修改 Markdown 与 JSON 产物。
|
|
@@ -369,6 +393,7 @@ loopx 在当前项目下写入 `.loopx/`:
|
|
|
369
393
|
用户可以阅读和按流程修改的事实源文档:
|
|
370
394
|
|
|
371
395
|
- `.loopx/workflows/<slug>/*.md`:当前 workflow 的可编辑工作副本;修改后仍需通过对应阶段门禁。
|
|
396
|
+
- `.loopx/config.json`:workspace 配置、项目规则/spec 来源发现结果和默认验证命令;当仓库的 canonical 命令或规则文件变化时可以更新。
|
|
372
397
|
- `.loopx/context/domain.md` 和 `.loopx/agents/*.md`:项目级背景、术语和 agent 协作约定。
|
|
373
398
|
- `.loopx/changes/active/<change-id>/*.md`:plan 生成的 change proposal、design、tasks 和 spec delta;修改后应重新过 plan/build/review。
|
|
374
399
|
- `.loopx/specs/<domain>/spec.md`:archive 后的长期行为规格;通常由 `archive` 同步,人工改动需要保持和后续 change delta 一致。
|
|
@@ -402,6 +427,12 @@ loopx repair-install
|
|
|
402
427
|
node scripts/install-skills.mjs --check
|
|
403
428
|
```
|
|
404
429
|
|
|
430
|
+
检查 bundled skill 治理状态:
|
|
431
|
+
|
|
432
|
+
```bash
|
|
433
|
+
node scripts/verify-skills.mjs
|
|
434
|
+
```
|
|
435
|
+
|
|
405
436
|
## Codex Workflow Hook
|
|
406
437
|
|
|
407
438
|
`install-skills.mjs` 和 Codex plugin 安装脚本会自动把 `scripts/codex-workflow-hook.mjs` 安装到:
|
|
@@ -453,9 +484,17 @@ node scripts/codex-stop-hook.mjs
|
|
|
453
484
|
npm test
|
|
454
485
|
```
|
|
455
486
|
|
|
487
|
+
`npm test` 会先运行 bundled skill 治理检查,再运行 Node 测试套件:
|
|
488
|
+
|
|
489
|
+
```bash
|
|
490
|
+
node scripts/verify-skills.mjs
|
|
491
|
+
node --test test/*.test.mjs
|
|
492
|
+
```
|
|
493
|
+
|
|
456
494
|
也可以直接执行项目内的验证命令:
|
|
457
495
|
|
|
458
496
|
```bash
|
|
497
|
+
node scripts/verify-skills.mjs
|
|
459
498
|
node --test test/*.test.mjs
|
|
460
499
|
node scripts/install-skills.mjs --check
|
|
461
500
|
node --test plugins/loopx/scripts/plugin-install.test.mjs
|
|
@@ -472,6 +511,7 @@ node src/cli.mjs status --json
|
|
|
472
511
|
- `README.zh-CN.md`
|
|
473
512
|
- `package.json`
|
|
474
513
|
- `scripts/install-skills.mjs`
|
|
514
|
+
- `scripts/verify-skills.mjs`
|
|
475
515
|
- `scripts/codex-stop-hook.mjs`
|
|
476
516
|
- `scripts/codex-workflow-hook.mjs`
|
|
477
517
|
- `assets/logo.svg`
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-content-space/loopx",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.5",
|
|
5
5
|
"description": "Skill-first loopx workflow product for Codex",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"README.zh-CN.md",
|
|
23
23
|
"package.json",
|
|
24
24
|
"scripts/install-skills.mjs",
|
|
25
|
+
"scripts/verify-skills.mjs",
|
|
25
26
|
"scripts/codex-stop-hook.mjs",
|
|
26
27
|
"scripts/codex-workflow-hook.mjs",
|
|
27
28
|
"assets/logo.svg",
|
|
@@ -35,6 +36,6 @@
|
|
|
35
36
|
},
|
|
36
37
|
"scripts": {
|
|
37
38
|
"postinstall": "node scripts/install-skills.mjs",
|
|
38
|
-
"test": "node --test test/*.test.mjs"
|
|
39
|
+
"test": "node scripts/verify-skills.mjs && node --test test/*.test.mjs"
|
|
39
40
|
}
|
|
40
41
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: archive
|
|
3
|
-
description:
|
|
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
|
+
when_to_use: "archive, done workflow, spec delta, long-lived specs, ADR candidate, review approved, 归档, 同步规格"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
argument-hint: "<workflow slug>"
|
|
5
8
|
---
|
|
6
9
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: autopilot
|
|
3
|
-
description:
|
|
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
|
+
when_to_use: "autopilot, autonomous loopx run, end-to-end workflow, run all stages, bounded orchestration, 自动执行, 全流程"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
argument-hint: "<workflow slug>"
|
|
5
8
|
---
|
|
6
9
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: build
|
|
3
|
-
description:
|
|
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
|
+
when_to_use: "build, implement approved plan, execute PRD, --from-review, review rework, implementation fixes, 执行, 实现, 修改"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
argument-hint: "[--no-deslop] <approved PRD path or workflow slug> | --from-review <review artifact path>"
|
|
5
8
|
---
|
|
6
9
|
|
|
@@ -30,6 +33,7 @@ By default, `build` is not a one-shot draft writer. It is a persistence loop wit
|
|
|
30
33
|
- Execution may parallelize internally without exposing a public `team` stage.
|
|
31
34
|
- `build` does not replace `review`.
|
|
32
35
|
- `execution-record.md` remains the sole canonical execution and verification artifact.
|
|
36
|
+
- `.loopx/config.json` is supporting context for existing project AI rules, existing spec sources, and discovered verification commands; use it to preserve local sources of truth, not to skip loopx stages.
|
|
33
37
|
- Feature work and bug fixes should use `tdd`: write a failing test, confirm it fails for the intended reason, then implement the smallest passing change.
|
|
34
38
|
- Bug, test-failure, build-failure, and unexpected-behavior work should use `debug` before proposing fixes.
|
|
35
39
|
- Completion and review-ready claims should use `verify` before they are stated.
|
|
@@ -72,6 +76,8 @@ Compatible skill / CLI input:
|
|
|
72
76
|
When invoked with a PRD path, derive `<slug>` from `prd-<slug>.md` and still use the matching workflow-local plan package and test spec.
|
|
73
77
|
|
|
74
78
|
When invoked with `--from-review`, derive `<slug>` from the workflow directory, treat the review artifact as the implementation-fix contract, and load the matching PRD, test spec, previous `execution-record.md`, and workflow-local plan package as supporting context. This Codex skill invocation consumes the `review -> build` rework intent; users should not need a separate bash `loopx approve ... --from review --to build` step for the normal Codex-facing flow.
|
|
79
|
+
|
|
80
|
+
Also load `.loopx/config.json` when present. Its `project_conventions` entries identify existing project rule/spec files that should be preserved, and its `verification_commands` entries are the first project-native commands to consider for fresh evidence.
|
|
75
81
|
</Inputs>
|
|
76
82
|
|
|
77
83
|
<Execution_Model>
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: clarify
|
|
3
|
-
description:
|
|
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
|
+
when_to_use: "clarify, requirements, ambiguous request, unclear scope, non-goals, decision boundaries, acceptance criteria, 需求澄清, 范围不清"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
---
|
|
5
8
|
|
|
6
9
|
# loopx Clarify
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: debug
|
|
3
|
-
description:
|
|
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
|
+
when_to_use: "debug, bug, test failure, build failure, regression, unexpected behavior, root cause, 报错, 失败, 回归, 排查"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
---
|
|
5
8
|
|
|
6
9
|
# Systematic Debugging
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: go-style
|
|
3
|
-
description: Go
|
|
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
|
+
when_to_use: "go-style, Go, golang, .go files, go tests, gofmt, idiomatic Go, Go style, Go 代码"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
---
|
|
5
8
|
|
|
6
9
|
# Go Style
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: kratos
|
|
3
|
-
description: Go-Kratos
|
|
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
|
+
when_to_use: "kratos, Go-Kratos, proto, buf, service layer, biz layer, data layer, middleware, auth, config, Kratos 微服务"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
---
|
|
5
8
|
|
|
6
9
|
# Kratos
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: plan
|
|
3
|
-
description:
|
|
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
|
+
when_to_use: "plan, planning, consensus planning, PRD, architecture plan, test plan, approved clarify spec, 规划, 方案, 架构评审"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
argument-hint: "[--interactive] [--deliberate] [--direct <spec-path>] <clarified task or spec path>"
|
|
5
8
|
---
|
|
6
9
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: review
|
|
3
|
-
description:
|
|
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
|
+
when_to_use: "review, code review, acceptance, go no-go, execution-record, architecture smell, build complete, 审查, 验收"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
argument-hint: "<execution-record path or workflow slug>"
|
|
5
8
|
---
|
|
6
9
|
|
|
@@ -22,6 +25,8 @@ Compatible skill / CLI input:
|
|
|
22
25
|
|
|
23
26
|
When invoked with an execution record path, derive `<slug>` from the workflow directory and evaluate the matching active run.
|
|
24
27
|
|
|
28
|
+
When present, use `.loopx/config.json` as supporting context for project-native verification commands, existing AI rule files, and existing spec sources. Do not treat those external or pre-existing sources as replacements for the loopx execution record and review artifact.
|
|
29
|
+
|
|
25
30
|
## Expected Outputs
|
|
26
31
|
|
|
27
32
|
- a review artifact tied to the run being evaluated
|
|
@@ -42,6 +47,7 @@ Use stable machine values only where they are commands, file paths, JSON/state f
|
|
|
42
47
|
- Use this only after build has produced execution and verification evidence for a specific run.
|
|
43
48
|
- Stop here if review evidence is incomplete. `review` remains an independent gate and does not auto-complete the workflow.
|
|
44
49
|
- Review must include code review of the build-owned implementation diff. Do not limit review to artifact/schema checks.
|
|
50
|
+
- Review should compare verification evidence against project-native commands recorded in `.loopx/config.json` when available, while still accepting stronger task-specific verification from the approved plan.
|
|
45
51
|
- Review must include the architecture-smell lane as part of review evidence. This is not a new workflow stage and must not create extra user steps.
|
|
46
52
|
- Review must compare the execution scope against the approved workflow scope. If `execution-record.md` declares non-empty `remaining_scope`, `completion_claim` other than `full`, or a mismatch between `planned_scope` and `implemented_scope`, review must return no-go and route to build or plan. A partial slice may be accepted as useful work, but it must not be approved as full workflow completion.
|
|
47
53
|
- Code review findings should focus on real bugs, regressions, missing tests, broken contracts, security/data-integrity risks, and user-visible behavior gaps.
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: tdd
|
|
3
|
-
description:
|
|
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
|
+
when_to_use: "tdd, failing test first, feature implementation, bugfix, regression test, red green refactor, 测试先行"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
---
|
|
5
8
|
|
|
6
9
|
# Test-Driven Development (TDD)
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: verify
|
|
3
|
-
description:
|
|
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
|
+
when_to_use: "verify, completion claim, fixed claim, tests pass, review-ready, commit, fresh evidence, 验证, 完成前检查"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
---
|
|
5
8
|
|
|
6
9
|
# Verification Before Completion
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import assert from 'node:assert/strict';
|
|
4
|
+
import { existsSync } from 'node:fs';
|
|
5
|
+
import { readdir, readFile } from 'node:fs/promises';
|
|
6
|
+
import { dirname, join, resolve } from 'node:path';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
|
|
9
|
+
import { LOOPX_BUNDLED_SKILLS } from '../src/install-discovery.mjs';
|
|
10
|
+
|
|
11
|
+
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
12
|
+
const packageJson = JSON.parse(await readFile(join(repoRoot, 'package.json'), 'utf8'));
|
|
13
|
+
const pluginManifest = JSON.parse(await readFile(join(repoRoot, 'plugins', 'loopx', '.codex-plugin', 'plugin.json'), 'utf8'));
|
|
14
|
+
const resolverPath = join(repoRoot, 'skills', 'RESOLVER.md');
|
|
15
|
+
const markdownPaths = [
|
|
16
|
+
'README.md',
|
|
17
|
+
'README.zh-CN.md',
|
|
18
|
+
'AGENTS.md',
|
|
19
|
+
'skills/RESOLVER.md',
|
|
20
|
+
];
|
|
21
|
+
const personalPathPattern = /\/(?:Users|home)\/[A-Za-z0-9._-]+\//;
|
|
22
|
+
const localRefPattern = /(?<![/.])\b(?:references|agents|scripts)\/[\w/.-]+\b/g;
|
|
23
|
+
|
|
24
|
+
function parseFrontmatter(path, text) {
|
|
25
|
+
assert.equal(text.startsWith('---\n'), true, `${path} must start with YAML frontmatter`);
|
|
26
|
+
const end = text.indexOf('\n---\n', 4);
|
|
27
|
+
assert.notEqual(end, -1, `${path} frontmatter must close with ---`);
|
|
28
|
+
|
|
29
|
+
const fields = {};
|
|
30
|
+
let inMetadata = false;
|
|
31
|
+
for (const line of text.slice(4, end).split('\n')) {
|
|
32
|
+
if (line === 'metadata:') {
|
|
33
|
+
inMetadata = true;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (inMetadata && line.startsWith(' version:')) {
|
|
37
|
+
fields.version = line.split(':', 2)[1].trim().replace(/^"|"$/g, '');
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (!line || line.startsWith(' ')) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
inMetadata = false;
|
|
44
|
+
const separator = line.indexOf(':');
|
|
45
|
+
assert.notEqual(separator, -1, `${path} has invalid frontmatter line: ${line}`);
|
|
46
|
+
const key = line.slice(0, separator).trim();
|
|
47
|
+
const raw = line.slice(separator + 1).trim();
|
|
48
|
+
fields[key] = raw.replace(/^"|"$/g, '');
|
|
49
|
+
}
|
|
50
|
+
return fields;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function assertSkillDescription(skillName, description) {
|
|
54
|
+
assert.ok(description, `${skillName} missing description`);
|
|
55
|
+
assert.ok(description.length >= 40, `${skillName} description is too short`);
|
|
56
|
+
assert.ok(description.length <= 500, `${skillName} description is too long`);
|
|
57
|
+
assert.match(description, /not for/i, `${skillName} description must include a Not for exclusion`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function assertMarkdownStructure(relativePath) {
|
|
61
|
+
const path = join(repoRoot, relativePath);
|
|
62
|
+
assert.equal(existsSync(path), true, `${relativePath} missing`);
|
|
63
|
+
const text = await readFile(path, 'utf8');
|
|
64
|
+
assert.equal(text.endsWith('\n'), true, `${relativePath} missing final newline`);
|
|
65
|
+
|
|
66
|
+
const fenceStack = [];
|
|
67
|
+
text.split('\n').forEach((line, index) => {
|
|
68
|
+
assert.equal(/^(<<<<<<<|=======|>>>>>>>)($| )/.test(line), false, `${relativePath}:${index + 1}: merge conflict marker`);
|
|
69
|
+
const match = line.match(/^(`{3,}|~{3,})/);
|
|
70
|
+
if (!match) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const marker = match[1];
|
|
74
|
+
if (fenceStack.length > 0 && marker[0] === fenceStack.at(-1).char && marker.length >= fenceStack.at(-1).length) {
|
|
75
|
+
fenceStack.pop();
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
fenceStack.push({ char: marker[0], length: marker.length, line: index + 1 });
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
assert.deepEqual(fenceStack, [], `${relativePath} has unclosed fenced block`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function assertContains(text, value, label) {
|
|
85
|
+
assert.match(text, new RegExp(value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')), `${label} missing ${value}`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function assertPublicDocsAligned() {
|
|
89
|
+
const readme = await readFile(join(repoRoot, 'README.md'), 'utf8');
|
|
90
|
+
const readmeZh = await readFile(join(repoRoot, 'README.zh-CN.md'), 'utf8');
|
|
91
|
+
const commands = [
|
|
92
|
+
'loopx init',
|
|
93
|
+
'loopx clarify',
|
|
94
|
+
'loopx approve',
|
|
95
|
+
'loopx plan',
|
|
96
|
+
'loopx build',
|
|
97
|
+
'loopx review',
|
|
98
|
+
'loopx archive',
|
|
99
|
+
'loopx autopilot',
|
|
100
|
+
'loopx render',
|
|
101
|
+
'loopx status',
|
|
102
|
+
'loopx setup-context',
|
|
103
|
+
'loopx doctor',
|
|
104
|
+
'loopx migrate',
|
|
105
|
+
'loopx repair-install',
|
|
106
|
+
'node scripts/verify-skills.mjs',
|
|
107
|
+
];
|
|
108
|
+
for (const command of commands) {
|
|
109
|
+
assertContains(readme, command, 'README.md');
|
|
110
|
+
assertContains(readmeZh, command, 'README.zh-CN.md');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const releaseNotesRoot = join(repoRoot, 'docs', 'release-notes');
|
|
114
|
+
const releaseNotes = existsSync(releaseNotesRoot)
|
|
115
|
+
? (await readdir(releaseNotesRoot)).filter((name) => name.endsWith('.md'))
|
|
116
|
+
: [];
|
|
117
|
+
assert.ok(releaseNotes.includes(`${packageJson.version}.md`), `docs/release-notes/${packageJson.version}.md missing`);
|
|
118
|
+
for (const name of releaseNotes) {
|
|
119
|
+
await assertMarkdownStructure(`docs/release-notes/${name}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async function assertSkill(skillName, resolverText) {
|
|
124
|
+
const rootPath = join(repoRoot, 'skills', skillName, 'SKILL.md');
|
|
125
|
+
const pluginPath = join(repoRoot, 'plugins', 'loopx', 'skills', skillName, 'SKILL.md');
|
|
126
|
+
assert.equal(existsSync(rootPath), true, `${skillName} root SKILL.md missing`);
|
|
127
|
+
assert.equal(existsSync(pluginPath), true, `${skillName} plugin SKILL.md missing`);
|
|
128
|
+
|
|
129
|
+
const rootText = await readFile(rootPath, 'utf8');
|
|
130
|
+
const pluginText = await readFile(pluginPath, 'utf8');
|
|
131
|
+
assert.equal(pluginText, rootText, `${skillName} plugin mirror drifted`);
|
|
132
|
+
assert.equal(personalPathPattern.test(rootText), false, `${skillName} contains a personal absolute path`);
|
|
133
|
+
|
|
134
|
+
const fields = parseFrontmatter(rootPath, rootText);
|
|
135
|
+
assert.equal(fields.name, skillName, `${skillName} frontmatter name mismatch`);
|
|
136
|
+
assert.equal(fields.version, packageJson.version, `${skillName} metadata.version must match package.json`);
|
|
137
|
+
assert.ok(fields.when_to_use && fields.when_to_use.length >= 20, `${skillName} missing useful when_to_use metadata`);
|
|
138
|
+
assertSkillDescription(skillName, fields.description);
|
|
139
|
+
assert.match(resolverText, new RegExp(`skills/${skillName}/SKILL\\.md`), `${skillName} missing from skills/RESOLVER.md`);
|
|
140
|
+
|
|
141
|
+
const refs = [...rootText.matchAll(localRefPattern)].map((match) => match[0]);
|
|
142
|
+
for (const ref of refs) {
|
|
143
|
+
const target = join(repoRoot, 'skills', skillName, ref);
|
|
144
|
+
assert.equal(existsSync(target), true, `${skillName} references missing local file: ${ref}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
assert.equal(pluginManifest.version, packageJson.version, 'plugin manifest version must match package.json');
|
|
149
|
+
assert.equal(existsSync(resolverPath), true, 'skills/RESOLVER.md missing');
|
|
150
|
+
|
|
151
|
+
for (const relativePath of markdownPaths) {
|
|
152
|
+
await assertMarkdownStructure(relativePath);
|
|
153
|
+
}
|
|
154
|
+
await assertPublicDocsAligned();
|
|
155
|
+
|
|
156
|
+
const resolverText = await readFile(resolverPath, 'utf8');
|
|
157
|
+
for (const skillName of LOOPX_BUNDLED_SKILLS) {
|
|
158
|
+
await assertSkill(skillName, resolverText);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const staleRefs = [...resolverText.matchAll(/skills\/([a-z][a-z0-9-]*)\/SKILL\.md/g)]
|
|
162
|
+
.map((match) => match[1])
|
|
163
|
+
.filter((skillName) => !LOOPX_BUNDLED_SKILLS.includes(skillName));
|
|
164
|
+
assert.deepEqual([...new Set(staleRefs)], [], 'skills/RESOLVER.md contains stale bundled-skill refs');
|
|
165
|
+
|
|
166
|
+
console.log(`ok: verified ${LOOPX_BUNDLED_SKILLS.length} loopx bundled skills`);
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# loopx Skill Resolver
|
|
2
|
+
|
|
3
|
+
Central routing map for loopx bundled skills. Keep this file in sync with every bundled `skills/<name>/SKILL.md` and `plugins/loopx/skills/<name>/SKILL.md`.
|
|
4
|
+
|
|
5
|
+
Read the selected skill file before acting. If multiple skills match, read every likely candidate and use the disambiguation rules below.
|
|
6
|
+
|
|
7
|
+
## Public Workflow Skills
|
|
8
|
+
|
|
9
|
+
| Trigger | Skill |
|
|
10
|
+
|---|---|
|
|
11
|
+
| Ambiguous request, unclear scope, non-goals, decision boundaries, requirements interview | `skills/clarify/SKILL.md` |
|
|
12
|
+
| Approved clarify spec, direct requirements artifact, PRD/test/architecture planning, consensus planning | `skills/plan/SKILL.md` |
|
|
13
|
+
| Approved plan execution, implementation persistence, review-requested implementation fixes | `skills/build/SKILL.md` |
|
|
14
|
+
| Independent acceptance, code review, architecture-smell review, go/no-go after build | `skills/review/SKILL.md` |
|
|
15
|
+
| Completed workflow needs long-lived spec sync and ADR candidate | `skills/archive/SKILL.md` |
|
|
16
|
+
| User wants one bounded end-to-end loopx run over clarify/plan/build/review | `skills/autopilot/SKILL.md` |
|
|
17
|
+
|
|
18
|
+
## Support Skills
|
|
19
|
+
|
|
20
|
+
| Trigger | Skill |
|
|
21
|
+
|---|---|
|
|
22
|
+
| Bug, test failure, build failure, regression, unexpected behavior, root-cause investigation | `skills/debug/SKILL.md` |
|
|
23
|
+
| Feature or bugfix implementation where behavior should be covered by a failing test first | `skills/tdd/SKILL.md` |
|
|
24
|
+
| Completion, fixed, passing, review-ready, commit, or handoff claims need fresh evidence | `skills/verify/SKILL.md` |
|
|
25
|
+
| Editing `.go` files or reviewing Go style inside build/review | `skills/go-style/SKILL.md` |
|
|
26
|
+
| Go-Kratos proto, service, biz, data, middleware, auth, config, or Kratos troubleshooting | `skills/kratos/SKILL.md` |
|
|
27
|
+
|
|
28
|
+
## Disambiguation
|
|
29
|
+
|
|
30
|
+
1. If intent, scope, non-goals, or decision boundaries are unresolved, use `clarify` before `plan`.
|
|
31
|
+
2. If requirements are approved but execution has not started, use `plan` before `build`.
|
|
32
|
+
3. If implementation is broken or tests fail during build, use `debug` as the diagnostic lens before patching.
|
|
33
|
+
4. If code is already implemented and needs acceptance, use `review`; do not run new build work from review.
|
|
34
|
+
5. If review requests implementation-only fixes, route to `build --from-review`; route to `plan` only when the plan itself is wrong.
|
|
35
|
+
6. If the user asks for autonomous execution, use `autopilot` only when requirements are bounded enough to run without new human decisions.
|
|
36
|
+
7. Treat `tdd`, `verify`, `go-style`, and `kratos` as support lenses unless the user explicitly invokes them directly.
|
|
37
|
+
8. `archive` is only valid after `review -> done`.
|
|
38
|
+
|
|
39
|
+
## Deterministic Guard
|
|
40
|
+
|
|
41
|
+
Run this before release or when changing bundled skills:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
node scripts/verify-skills.mjs
|
|
45
|
+
```
|
package/skills/archive/SKILL.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: archive
|
|
3
|
-
description:
|
|
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
|
+
when_to_use: "archive, done workflow, spec delta, long-lived specs, ADR candidate, review approved, 归档, 同步规格"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
argument-hint: "<workflow slug>"
|
|
5
8
|
---
|
|
6
9
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: autopilot
|
|
3
|
-
description:
|
|
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
|
+
when_to_use: "autopilot, autonomous loopx run, end-to-end workflow, run all stages, bounded orchestration, 自动执行, 全流程"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
argument-hint: "<workflow slug>"
|
|
5
8
|
---
|
|
6
9
|
|
package/skills/build/SKILL.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: build
|
|
3
|
-
description:
|
|
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
|
+
when_to_use: "build, implement approved plan, execute PRD, --from-review, review rework, implementation fixes, 执行, 实现, 修改"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
argument-hint: "[--no-deslop] <approved PRD path or workflow slug> | --from-review <review artifact path>"
|
|
5
8
|
---
|
|
6
9
|
|
|
@@ -30,6 +33,7 @@ By default, `build` is not a one-shot draft writer. It is a persistence loop wit
|
|
|
30
33
|
- Execution may parallelize internally without exposing a public `team` stage.
|
|
31
34
|
- `build` does not replace `review`.
|
|
32
35
|
- `execution-record.md` remains the sole canonical execution and verification artifact.
|
|
36
|
+
- `.loopx/config.json` is supporting context for existing project AI rules, existing spec sources, and discovered verification commands; use it to preserve local sources of truth, not to skip loopx stages.
|
|
33
37
|
- Feature work and bug fixes should use `tdd`: write a failing test, confirm it fails for the intended reason, then implement the smallest passing change.
|
|
34
38
|
- Bug, test-failure, build-failure, and unexpected-behavior work should use `debug` before proposing fixes.
|
|
35
39
|
- Completion and review-ready claims should use `verify` before they are stated.
|
|
@@ -72,6 +76,8 @@ Compatible skill / CLI input:
|
|
|
72
76
|
When invoked with a PRD path, derive `<slug>` from `prd-<slug>.md` and still use the matching workflow-local plan package and test spec.
|
|
73
77
|
|
|
74
78
|
When invoked with `--from-review`, derive `<slug>` from the workflow directory, treat the review artifact as the implementation-fix contract, and load the matching PRD, test spec, previous `execution-record.md`, and workflow-local plan package as supporting context. This Codex skill invocation consumes the `review -> build` rework intent; users should not need a separate bash `loopx approve ... --from review --to build` step for the normal Codex-facing flow.
|
|
79
|
+
|
|
80
|
+
Also load `.loopx/config.json` when present. Its `project_conventions` entries identify existing project rule/spec files that should be preserved, and its `verification_commands` entries are the first project-native commands to consider for fresh evidence.
|
|
75
81
|
</Inputs>
|
|
76
82
|
|
|
77
83
|
<Execution_Model>
|
package/skills/clarify/SKILL.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: clarify
|
|
3
|
-
description:
|
|
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
|
+
when_to_use: "clarify, requirements, ambiguous request, unclear scope, non-goals, decision boundaries, acceptance criteria, 需求澄清, 范围不清"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
---
|
|
5
8
|
|
|
6
9
|
# loopx Clarify
|
package/skills/debug/SKILL.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: debug
|
|
3
|
-
description:
|
|
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
|
+
when_to_use: "debug, bug, test failure, build failure, regression, unexpected behavior, root cause, 报错, 失败, 回归, 排查"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
---
|
|
5
8
|
|
|
6
9
|
# Systematic Debugging
|
package/skills/go-style/SKILL.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: go-style
|
|
3
|
-
description: Go
|
|
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
|
+
when_to_use: "go-style, Go, golang, .go files, go tests, gofmt, idiomatic Go, Go style, Go 代码"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
---
|
|
5
8
|
|
|
6
9
|
# Go Style
|
package/skills/kratos/SKILL.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: kratos
|
|
3
|
-
description: Go-Kratos
|
|
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
|
+
when_to_use: "kratos, Go-Kratos, proto, buf, service layer, biz layer, data layer, middleware, auth, config, Kratos 微服务"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
---
|
|
5
8
|
|
|
6
9
|
# Kratos
|
package/skills/plan/SKILL.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: plan
|
|
3
|
-
description:
|
|
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
|
+
when_to_use: "plan, planning, consensus planning, PRD, architecture plan, test plan, approved clarify spec, 规划, 方案, 架构评审"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
argument-hint: "[--interactive] [--deliberate] [--direct <spec-path>] <clarified task or spec path>"
|
|
5
8
|
---
|
|
6
9
|
|
package/skills/review/SKILL.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: review
|
|
3
|
-
description:
|
|
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
|
+
when_to_use: "review, code review, acceptance, go no-go, execution-record, architecture smell, build complete, 审查, 验收"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
argument-hint: "<execution-record path or workflow slug>"
|
|
5
8
|
---
|
|
6
9
|
|
|
@@ -22,6 +25,8 @@ Compatible skill / CLI input:
|
|
|
22
25
|
|
|
23
26
|
When invoked with an execution record path, derive `<slug>` from the workflow directory and evaluate the matching active run.
|
|
24
27
|
|
|
28
|
+
When present, use `.loopx/config.json` as supporting context for project-native verification commands, existing AI rule files, and existing spec sources. Do not treat those external or pre-existing sources as replacements for the loopx execution record and review artifact.
|
|
29
|
+
|
|
25
30
|
## Expected Outputs
|
|
26
31
|
|
|
27
32
|
- a review artifact tied to the run being evaluated
|
|
@@ -42,6 +47,7 @@ Use stable machine values only where they are commands, file paths, JSON/state f
|
|
|
42
47
|
- Use this only after build has produced execution and verification evidence for a specific run.
|
|
43
48
|
- Stop here if review evidence is incomplete. `review` remains an independent gate and does not auto-complete the workflow.
|
|
44
49
|
- Review must include code review of the build-owned implementation diff. Do not limit review to artifact/schema checks.
|
|
50
|
+
- Review should compare verification evidence against project-native commands recorded in `.loopx/config.json` when available, while still accepting stronger task-specific verification from the approved plan.
|
|
45
51
|
- Review must include the architecture-smell lane as part of review evidence. This is not a new workflow stage and must not create extra user steps.
|
|
46
52
|
- Review must compare the execution scope against the approved workflow scope. If `execution-record.md` declares non-empty `remaining_scope`, `completion_claim` other than `full`, or a mismatch between `planned_scope` and `implemented_scope`, review must return no-go and route to build or plan. A partial slice may be accepted as useful work, but it must not be approved as full workflow completion.
|
|
47
53
|
- Code review findings should focus on real bugs, regressions, missing tests, broken contracts, security/data-integrity risks, and user-visible behavior gaps.
|
package/skills/tdd/SKILL.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: tdd
|
|
3
|
-
description:
|
|
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
|
+
when_to_use: "tdd, failing test first, feature implementation, bugfix, regression test, red green refactor, 测试先行"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
---
|
|
5
8
|
|
|
6
9
|
# Test-Driven Development (TDD)
|
package/skills/verify/SKILL.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: verify
|
|
3
|
-
description:
|
|
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
|
+
when_to_use: "verify, completion claim, fixed claim, tests pass, review-ready, commit, fresh evidence, 验证, 完成前检查"
|
|
5
|
+
metadata:
|
|
6
|
+
version: "0.1.5"
|
|
4
7
|
---
|
|
5
8
|
|
|
6
9
|
# Verification Before Completion
|
package/src/context-manifest.mjs
CHANGED
|
@@ -138,6 +138,7 @@ export async function generateBuildContextManifest({ cwd, root, state, slug }) {
|
|
|
138
138
|
row(cwd, { stage: 'build', kind: 'review-rework', path: reviewReworkPath, reason: 'review_requested_implementation_fixes', priority: 33, required: requiresReviewRework }),
|
|
139
139
|
row(cwd, { stage: 'build', kind: 'domain-context', path: contextPaths.domainGlossary, reason: 'domain_vocabulary', priority: 34, required: contextSetup.status !== 'missing' }),
|
|
140
140
|
row(cwd, { stage: 'build', kind: 'agent-domain', path: contextPaths.agentDomain, reason: 'agent_context_rules', priority: 35, required: false }),
|
|
141
|
+
row(cwd, { stage: 'build', kind: 'workspace-config', path: join(cwd, '.loopx', 'config.json'), reason: 'project_rules_spec_sources_and_verification_commands', priority: 36, required: false }),
|
|
141
142
|
];
|
|
142
143
|
const manifestPath = buildContextManifestPath(root);
|
|
143
144
|
await writeContextManifest(manifestPath, rows);
|
|
@@ -157,6 +158,7 @@ export async function generateReviewContextManifest({ cwd, root, state, slug })
|
|
|
157
158
|
row(cwd, { stage: 'review', kind: 'residual-risks', path: join(root, 'execution-record.md'), reason: 'residual_risk_reference', priority: 26, required: false }),
|
|
158
159
|
row(cwd, { stage: 'review', kind: 'build-support', path: join(root, 'build-support'), reason: 'build_gate_evidence', priority: 30, required: false }),
|
|
159
160
|
row(cwd, { stage: 'review', kind: 'agent-domain', path: contextPaths.agentDomain, reason: 'agent_context_rules', priority: 31, required: false }),
|
|
161
|
+
row(cwd, { stage: 'review', kind: 'workspace-config', path: join(cwd, '.loopx', 'config.json'), reason: 'project_rules_spec_sources_and_verification_commands', priority: 32, required: false }),
|
|
160
162
|
row(cwd, { stage: 'review', kind: 'state', path: join(root, 'state.json'), reason: 'workflow_state', priority: 40 }),
|
|
161
163
|
];
|
|
162
164
|
const manifestPath = reviewContextManifestPath(root);
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { readdir, readFile, stat } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
|
|
5
|
+
async function readJsonIfExists(path) {
|
|
6
|
+
if (!existsSync(path)) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
try {
|
|
10
|
+
return JSON.parse(await readFile(path, 'utf8'));
|
|
11
|
+
} catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async function pathKind(path) {
|
|
17
|
+
if (!existsSync(path)) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const info = await stat(path);
|
|
21
|
+
return info.isDirectory() ? 'directory' : 'file';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function candidate(path, label) {
|
|
25
|
+
const kind = await pathKind(path);
|
|
26
|
+
if (!kind) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
return { path: label, kind };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function directoryChildren(root, label) {
|
|
33
|
+
if (!existsSync(root)) {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
const info = await stat(root);
|
|
37
|
+
if (!info.isDirectory()) {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
const entries = await readdir(root);
|
|
41
|
+
return entries
|
|
42
|
+
.filter((entry) => /\.(md|mdc|txt)$/i.test(entry))
|
|
43
|
+
.sort()
|
|
44
|
+
.map((entry) => ({ path: `${label}/${entry}`, kind: 'file' }));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function discoverAiRules(cwd) {
|
|
48
|
+
const direct = await Promise.all([
|
|
49
|
+
candidate(join(cwd, 'AGENTS.md'), 'AGENTS.md'),
|
|
50
|
+
candidate(join(cwd, 'CLAUDE.md'), 'CLAUDE.md'),
|
|
51
|
+
candidate(join(cwd, '.cursor', 'rules'), '.cursor/rules'),
|
|
52
|
+
candidate(join(cwd, '.github', 'copilot-instructions.md'), '.github/copilot-instructions.md'),
|
|
53
|
+
]);
|
|
54
|
+
return [
|
|
55
|
+
...direct.filter(Boolean),
|
|
56
|
+
...await directoryChildren(join(cwd, '.cursor', 'rules'), '.cursor/rules'),
|
|
57
|
+
].filter((item, index, items) => items.findIndex((other) => other.path === item.path) === index);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function discoverSpecSources(cwd) {
|
|
61
|
+
const direct = await Promise.all([
|
|
62
|
+
candidate(join(cwd, 'openspec.yaml'), 'openspec.yaml'),
|
|
63
|
+
candidate(join(cwd, 'openspec.yml'), 'openspec.yml'),
|
|
64
|
+
candidate(join(cwd, 'openspec.json'), 'openspec.json'),
|
|
65
|
+
candidate(join(cwd, 'open-spec.yaml'), 'open-spec.yaml'),
|
|
66
|
+
candidate(join(cwd, '.specify'), '.specify'),
|
|
67
|
+
candidate(join(cwd, 'specs'), 'specs'),
|
|
68
|
+
candidate(join(cwd, 'docs', 'changes'), 'docs/changes'),
|
|
69
|
+
candidate(join(cwd, 'docs', 'specs'), 'docs/specs'),
|
|
70
|
+
candidate(join(cwd, 'docs', 'adr'), 'docs/adr'),
|
|
71
|
+
candidate(join(cwd, 'docs', 'rfcs'), 'docs/rfcs'),
|
|
72
|
+
]);
|
|
73
|
+
return direct.filter(Boolean);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function packageRunner(cwd, packageJson) {
|
|
77
|
+
const packageManager = String(packageJson?.packageManager || '');
|
|
78
|
+
if (packageManager.startsWith('pnpm@') || existsSync(join(cwd, 'pnpm-lock.yaml'))) {
|
|
79
|
+
return 'pnpm';
|
|
80
|
+
}
|
|
81
|
+
if (packageManager.startsWith('yarn@') || existsSync(join(cwd, 'yarn.lock'))) {
|
|
82
|
+
return 'yarn';
|
|
83
|
+
}
|
|
84
|
+
if (packageManager.startsWith('bun@') || existsSync(join(cwd, 'bun.lock')) || existsSync(join(cwd, 'bun.lockb'))) {
|
|
85
|
+
return 'bun';
|
|
86
|
+
}
|
|
87
|
+
return 'npm';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function runScriptCommand(runner, scriptName) {
|
|
91
|
+
if (runner === 'npm') {
|
|
92
|
+
return scriptName === 'test' ? 'npm test' : `npm run ${scriptName}`;
|
|
93
|
+
}
|
|
94
|
+
return `${runner} ${scriptName}`;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function firstScript(scripts, names) {
|
|
98
|
+
return names.find((name) => Object.prototype.hasOwnProperty.call(scripts, name));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async function discoverPackageCommands(cwd) {
|
|
102
|
+
const packageJson = await readJsonIfExists(join(cwd, 'package.json'));
|
|
103
|
+
if (!packageJson) {
|
|
104
|
+
return {};
|
|
105
|
+
}
|
|
106
|
+
const runner = packageRunner(cwd, packageJson);
|
|
107
|
+
const scripts = packageJson.scripts || {};
|
|
108
|
+
const install = runner === 'npm' && existsSync(join(cwd, 'package-lock.json'))
|
|
109
|
+
? 'npm ci'
|
|
110
|
+
: `${runner} install`;
|
|
111
|
+
return {
|
|
112
|
+
install,
|
|
113
|
+
test: scripts.test ? runScriptCommand(runner, 'test') : null,
|
|
114
|
+
lint: scripts.lint ? runScriptCommand(runner, 'lint') : null,
|
|
115
|
+
typecheck: scripts.typecheck ? runScriptCommand(runner, 'typecheck') : null,
|
|
116
|
+
build: scripts.build ? runScriptCommand(runner, 'build') : null,
|
|
117
|
+
e2e: (() => {
|
|
118
|
+
const script = firstScript(scripts, ['test:e2e', 'e2e', 'test:browser', 'playwright']);
|
|
119
|
+
return script ? runScriptCommand(runner, script) : null;
|
|
120
|
+
})(),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function compactCommands(commands) {
|
|
125
|
+
return Object.fromEntries(
|
|
126
|
+
['install', 'test', 'lint', 'typecheck', 'build', 'e2e']
|
|
127
|
+
.map((key) => [key, commands[key] || null]),
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export async function discoverVerificationCommands(cwd) {
|
|
132
|
+
const packageCommands = await discoverPackageCommands(cwd);
|
|
133
|
+
if (Object.keys(packageCommands).length > 0) {
|
|
134
|
+
return compactCommands(packageCommands);
|
|
135
|
+
}
|
|
136
|
+
if (existsSync(join(cwd, 'go.mod'))) {
|
|
137
|
+
return compactCommands({
|
|
138
|
+
test: 'go test ./...',
|
|
139
|
+
build: 'go build ./...',
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
if (existsSync(join(cwd, 'pyproject.toml'))) {
|
|
143
|
+
return compactCommands({
|
|
144
|
+
install: 'pip install -e .',
|
|
145
|
+
test: 'pytest',
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
return compactCommands({});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export async function inspectProjectConventions(cwd) {
|
|
152
|
+
const [existingAiRules, existingSpecSources, verificationCommands] = await Promise.all([
|
|
153
|
+
discoverAiRules(cwd),
|
|
154
|
+
discoverSpecSources(cwd),
|
|
155
|
+
discoverVerificationCommands(cwd),
|
|
156
|
+
]);
|
|
157
|
+
return {
|
|
158
|
+
existing_ai_rules: existingAiRules,
|
|
159
|
+
existing_spec_sources: existingSpecSources,
|
|
160
|
+
verification_commands: verificationCommands,
|
|
161
|
+
source_of_truth_policy: 'preserve-existing-project-rules-and-use-loopx-artifacts-only-after-init',
|
|
162
|
+
};
|
|
163
|
+
}
|
package/src/workflow.mjs
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
import { doctorRuntime, ensureLoopxRoot, resolveLoopxRoot } from './runtime-maintenance.mjs';
|
|
17
17
|
import { DEFAULT_BUILD_MAX_ITERATIONS, createDefaultBuildAdapter } from './build-runtime.mjs';
|
|
18
18
|
import { DEFAULT_MAX_ITERATIONS, createDefaultPlanAdapter } from './plan-runtime.mjs';
|
|
19
|
+
import { inspectProjectConventions } from './project-discovery.mjs';
|
|
19
20
|
import { createDefaultReviewAdapter } from './review-runtime.mjs';
|
|
20
21
|
import { appendWorkspaceJournal } from './workspace-memory.mjs';
|
|
21
22
|
import { inspectWorkspaceContext, setupWorkspaceContext } from './workspace-context.mjs';
|
|
@@ -2509,6 +2510,7 @@ async function refreshExecutionStatus(root, state) {
|
|
|
2509
2510
|
|
|
2510
2511
|
export async function initWorkspace(cwd, { slug } = {}) {
|
|
2511
2512
|
const workspaceRoot = resolveWorkspaceRoot(cwd);
|
|
2513
|
+
const projectConventions = await inspectProjectConventions(cwd);
|
|
2512
2514
|
await ensureLoopxRoot(cwd);
|
|
2513
2515
|
await ensureDir(join(workspaceRoot, 'context'));
|
|
2514
2516
|
await ensureDir(join(workspaceRoot, 'intake'));
|
|
@@ -2527,6 +2529,12 @@ export async function initWorkspace(cwd, { slug } = {}) {
|
|
|
2527
2529
|
product_contract: 'skill-first-v1',
|
|
2528
2530
|
default_flow: ['clarify', 'plan', 'build', 'review', 'done', 'archive'],
|
|
2529
2531
|
preferred_surface: ['clarify', 'plan', 'build', 'review', 'archive', 'autopilot'],
|
|
2532
|
+
source_of_truth_policy: projectConventions.source_of_truth_policy,
|
|
2533
|
+
project_conventions: {
|
|
2534
|
+
existing_ai_rules: projectConventions.existing_ai_rules,
|
|
2535
|
+
existing_spec_sources: projectConventions.existing_spec_sources,
|
|
2536
|
+
},
|
|
2537
|
+
verification_commands: projectConventions.verification_commands,
|
|
2530
2538
|
};
|
|
2531
2539
|
|
|
2532
2540
|
if (!existsSync(workspaceConfigPath(workspaceRoot))) {
|