intentdna 1.5.7 → 1.5.8
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/dist/cli/commands/templates.d.ts +10 -0
- package/dist/cli/commands/templates.js +85 -0
- package/dist/cli/index.js +12 -0
- package/dist/templates/flutter-rewrite.dna.yaml +24 -8
- package/package.json +1 -1
- package/spec/flutter-rewrite-template-optimization.md +40 -9
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dna templates deploy — copy local src/templates/*.dna.yaml to global intentdna install
|
|
3
|
+
*/
|
|
4
|
+
export interface TemplatesDeployOptions {
|
|
5
|
+
/** Override local templates dir (for testing) */
|
|
6
|
+
localDir?: string;
|
|
7
|
+
/** Override global target dir (for testing) */
|
|
8
|
+
globalDir?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function runTemplatesDeploy(opts?: TemplatesDeployOptions): Promise<number>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dna templates deploy — copy local src/templates/*.dna.yaml to global intentdna install
|
|
3
|
+
*/
|
|
4
|
+
import { readdirSync, copyFileSync, existsSync, readFileSync, mkdirSync } from "node:fs";
|
|
5
|
+
import { resolve, join } from "node:path";
|
|
6
|
+
import { execSync } from "node:child_process";
|
|
7
|
+
/**
|
|
8
|
+
* Resolve the global intentdna templates directory.
|
|
9
|
+
* Strategy: npm root -g + /intentdna/dist/templates
|
|
10
|
+
*/
|
|
11
|
+
function resolveGlobalTemplatesDir() {
|
|
12
|
+
let globalRoot;
|
|
13
|
+
try {
|
|
14
|
+
globalRoot = execSync("npm root -g", { encoding: "utf-8" }).trim();
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
throw new Error("Failed to resolve npm global root. Is npm installed?");
|
|
18
|
+
}
|
|
19
|
+
const globalPkg = join(globalRoot, "intentdna");
|
|
20
|
+
if (!existsSync(globalPkg)) {
|
|
21
|
+
throw new Error("intentdna not installed globally, run: npm install -g intentdna");
|
|
22
|
+
}
|
|
23
|
+
// Templates live in dist/templates after build, and src/templates in source
|
|
24
|
+
const distTemplates = join(globalPkg, "dist", "templates");
|
|
25
|
+
const srcTemplates = join(globalPkg, "src", "templates");
|
|
26
|
+
if (existsSync(distTemplates))
|
|
27
|
+
return distTemplates;
|
|
28
|
+
if (existsSync(srcTemplates))
|
|
29
|
+
return srcTemplates;
|
|
30
|
+
// Create dist/templates if neither exists (fresh install edge case)
|
|
31
|
+
mkdirSync(distTemplates, { recursive: true });
|
|
32
|
+
return distTemplates;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Verify we're in the intentdna project root.
|
|
36
|
+
*/
|
|
37
|
+
function verifyProjectRoot(cwd) {
|
|
38
|
+
const pkgPath = join(cwd, "package.json");
|
|
39
|
+
if (!existsSync(pkgPath)) {
|
|
40
|
+
throw new Error("must run from intentdna project root (no package.json found)");
|
|
41
|
+
}
|
|
42
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
43
|
+
if (pkg.name !== "intentdna") {
|
|
44
|
+
throw new Error("must run from intentdna project root (package.json name is not 'intentdna')");
|
|
45
|
+
}
|
|
46
|
+
return cwd;
|
|
47
|
+
}
|
|
48
|
+
export async function runTemplatesDeploy(opts = {}) {
|
|
49
|
+
try {
|
|
50
|
+
const cwd = process.cwd();
|
|
51
|
+
const projectRoot = verifyProjectRoot(cwd);
|
|
52
|
+
const localDir = opts.localDir ?? resolve(projectRoot, "src", "templates");
|
|
53
|
+
const globalDir = opts.globalDir ?? resolveGlobalTemplatesDir();
|
|
54
|
+
if (!existsSync(localDir)) {
|
|
55
|
+
process.stderr.write(`Error: local templates dir not found: ${localDir}\n`);
|
|
56
|
+
return 1;
|
|
57
|
+
}
|
|
58
|
+
const files = readdirSync(localDir).filter((f) => f.endsWith(".dna.yaml"));
|
|
59
|
+
if (files.length === 0) {
|
|
60
|
+
process.stderr.write("No *.dna.yaml files found in local templates dir\n");
|
|
61
|
+
return 1;
|
|
62
|
+
}
|
|
63
|
+
let copied = 0;
|
|
64
|
+
for (const file of files) {
|
|
65
|
+
const src = join(localDir, file);
|
|
66
|
+
const dst = join(globalDir, file);
|
|
67
|
+
try {
|
|
68
|
+
copyFileSync(src, dst);
|
|
69
|
+
copied++;
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
73
|
+
process.stderr.write(`Error copying ${file}: ${msg}\n`);
|
|
74
|
+
return 1;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
process.stderr.write(`Copied ${copied} templates to ${globalDir}\n`);
|
|
78
|
+
return 0;
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
82
|
+
process.stderr.write(`Error: ${msg}\n`);
|
|
83
|
+
return 1;
|
|
84
|
+
}
|
|
85
|
+
}
|
package/dist/cli/index.js
CHANGED
|
@@ -30,6 +30,7 @@ Commands:
|
|
|
30
30
|
evolve Generate epigenetic markers from outcomes
|
|
31
31
|
epigenetic Record outcomes, view markers and summaries
|
|
32
32
|
feedback Analyze trace data, suggest template optimizations (--days <N>, --json, --evolve)
|
|
33
|
+
templates Template management (deploy to global install)
|
|
33
34
|
|
|
34
35
|
Options:
|
|
35
36
|
--help, -h Show help for a command
|
|
@@ -428,6 +429,17 @@ async function main() {
|
|
|
428
429
|
process.exit(code);
|
|
429
430
|
break;
|
|
430
431
|
}
|
|
432
|
+
case "templates": {
|
|
433
|
+
const subcommand = rest[0] ?? "";
|
|
434
|
+
if (subcommand !== "deploy") {
|
|
435
|
+
process.stderr.write(`Usage: dna templates deploy\n\nCopy local src/templates/*.dna.yaml to global intentdna install.\n`);
|
|
436
|
+
process.exit(subcommand ? 2 : 0);
|
|
437
|
+
}
|
|
438
|
+
const { runTemplatesDeploy } = await import("./commands/templates.js");
|
|
439
|
+
const code = await runTemplatesDeploy();
|
|
440
|
+
process.exit(code);
|
|
441
|
+
break;
|
|
442
|
+
}
|
|
431
443
|
default:
|
|
432
444
|
process.stderr.write(`Unknown command: ${command}\n\n`);
|
|
433
445
|
process.stderr.write(HELP);
|
|
@@ -168,7 +168,12 @@ roles:
|
|
|
168
168
|
- Never suggest code changes
|
|
169
169
|
- "If round > 1: review previous round's git diff first, judge if direction is correct"
|
|
170
170
|
- "If previous fix produced 0 red→green transitions: warn 'no progress'"
|
|
171
|
-
- "Categorize by severity
|
|
171
|
+
- "Categorize by severity and type:"
|
|
172
|
+
- " CRITICAL: compile errors, import failures — blocks everything"
|
|
173
|
+
- " HIGH-INFRA: mock incomplete causing test hang — blocks behavior verification, fix mock infrastructure first"
|
|
174
|
+
- " HIGH-LOGIC: logic test failures (state/notifier) — behavior inconsistency"
|
|
175
|
+
- " MEDIUM: widget test failures (rendering/navigation)"
|
|
176
|
+
- "hung tests ≠ failed tests. hung = mock infrastructure problem (needs mock fix), failed = behavior inconsistency (needs v2 code fix)"
|
|
172
177
|
|
|
173
178
|
surgeon:
|
|
174
179
|
description: Fixes breakpoints and builds missing layers by understanding v1 intent and rewriting in v2 style.
|
|
@@ -248,8 +253,9 @@ workflows:
|
|
|
248
253
|
Scenario 2 (re-run/incremental):
|
|
249
254
|
- Read the incremental diff from behavior doc
|
|
250
255
|
- Update existing tests incrementally — do NOT rewrite all tests (preserves rescue progress)
|
|
251
|
-
- Run `flutter test {{test_path}}/$ARGUMENTS
|
|
252
|
-
-
|
|
256
|
+
- Run `flutter test {{test_path}}/$ARGUMENTS/ --timeout 30s` — per-test safety net (hung tests marked fail, continues to next)
|
|
257
|
+
- Classify results: passed / failed (behavior mismatch) / hung (timed out = mock infrastructure issue, NOT behavior failure)
|
|
258
|
+
- Append baseline to behavior doc with hung/failed distinction
|
|
253
259
|
- Git commit: "behavior-lock($ARGUMENTS): N tests (X green, Y red from behavior change)"
|
|
254
260
|
|
|
255
261
|
BANNED patterns:
|
|
@@ -273,6 +279,13 @@ workflows:
|
|
|
273
279
|
description: "Fix v2 module $ARGUMENTS — investigate, fix, review, verify, report. Max 10 rounds with convergence protection."
|
|
274
280
|
max_rounds: 10
|
|
275
281
|
convergence_rule: "2 consecutive rounds with 0 test progress (green count not increasing) → STOP. Output blocked items + analysis."
|
|
282
|
+
round_budget: "Max 5 files per round. Each round must produce at least 1 test transition (red/skip/hung → green), otherwise counted as no progress."
|
|
283
|
+
priority_order: |
|
|
284
|
+
Phase 1: Fix CRITICAL (compile errors) — unblocks everything
|
|
285
|
+
Phase 2: Fix HIGH-INFRA (mock infrastructure, make hung tests runnable) — unblocks behavior verification
|
|
286
|
+
Phase 3: Fix HIGH-LOGIC (logic tests, red → green) — behavior alignment
|
|
287
|
+
Phase 4: Fix MEDIUM (widget tests, red → green) — UI alignment
|
|
288
|
+
Complete each phase before moving to the next.
|
|
276
289
|
steps:
|
|
277
290
|
- id: investigate
|
|
278
291
|
role: investigator
|
|
@@ -282,10 +295,13 @@ workflows:
|
|
|
282
295
|
- If round > 1: review previous round's git diff first
|
|
283
296
|
- If previous round had 0 test progress (no red→green or skip→green): warn "no progress" and consider changing approach
|
|
284
297
|
|
|
285
|
-
Run tests in {{test_path}}/$ARGUMENTS
|
|
286
|
-
CRITICAL: compile errors, import failures — fix first
|
|
287
|
-
HIGH:
|
|
288
|
-
|
|
298
|
+
Run tests in {{test_path}}/$ARGUMENTS/ --timeout 30s. Categorize all non-passing tests by severity:
|
|
299
|
+
CRITICAL: compile errors, import failures — blocks everything, fix first
|
|
300
|
+
HIGH-INFRA: mock incomplete causing test hang (timed out) — blocks behavior verification, fix mock infrastructure
|
|
301
|
+
HIGH-LOGIC: logic test failures (state/notifier/service) — behavior inconsistency, fix after infra
|
|
302
|
+
MEDIUM: widget test failures (rendering/navigation) — fix after logic
|
|
303
|
+
|
|
304
|
+
IMPORTANT: hung ≠ failed. A test that times out (hung) = mock infrastructure problem, NOT a v2 behavior issue. Classify separately.
|
|
289
305
|
|
|
290
306
|
Pick highest severity batch. Trace: what does v1 do vs what does v2 do? Find the breakpoints.
|
|
291
307
|
Report findings and the plan for this round.
|
|
@@ -348,7 +364,7 @@ workflows:
|
|
|
348
364
|
description: "Independent test verification + regression check."
|
|
349
365
|
prompt: |
|
|
350
366
|
Run tests independently (do not trust surgeon's reported results):
|
|
351
|
-
1. `flutter test {{test_path}}/$ARGUMENTS
|
|
367
|
+
1. `flutter test {{test_path}}/$ARGUMENTS/ --timeout 30s` (per-test safety net; hung = mock infra issue)
|
|
352
368
|
2. `flutter analyze` (compilation check)
|
|
353
369
|
3. Check for regressions in core module tests if applicable
|
|
354
370
|
|
package/package.json
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Spec: flutter-rewrite 模板优化
|
|
2
2
|
|
|
3
|
+
## 最终目标
|
|
4
|
+
|
|
5
|
+
**把 v1 (GetX) 重写为 v2 (Riverpod),行为完全一致。**
|
|
6
|
+
|
|
7
|
+
- behavior-lock: 写测试 = 定义"v1 的行为是什么"
|
|
8
|
+
- rescue: 写代码让测试通过 = "v2 的行为和 v1 一样"
|
|
9
|
+
- 完成标志: 所有测试 green = 重写成功,行为完全一致
|
|
10
|
+
|
|
11
|
+
所有设计决策必须服务于这个目标。timeout 是安全网(防卡死),不是解法。挂死的测试意味着行为没被验证——rescue 必须修复它们,不能跳过。
|
|
12
|
+
|
|
3
13
|
## 问题
|
|
4
14
|
|
|
5
15
|
flutter-rewrite 模板的 behavior-lock 和 rescue 工作流都有设计缺陷,导致:
|
|
@@ -47,14 +57,19 @@ commit: "behavior-lock($MODULE): N tests (X green, Y red from behavior change)"
|
|
|
47
57
|
3. 增量更新
|
|
48
58
|
4. 输出 diff 摘要
|
|
49
59
|
|
|
50
|
-
###
|
|
60
|
+
### 超时策略
|
|
51
61
|
|
|
52
|
-
|
|
|
53
|
-
|
|
54
|
-
| `
|
|
55
|
-
| `timeout Nm flutter test` |
|
|
56
|
-
|
|
|
57
|
-
|
|
|
62
|
+
| 操作 | 允许? | 原因 |
|
|
63
|
+
|------|--------|------|
|
|
64
|
+
| `flutter test --timeout 30s` | **允许** | per-test 安全网,挂死标 fail 继续下一个 |
|
|
65
|
+
| `timeout Nm flutter test` | 禁止 | 外部杀进程,丢失所有结果 |
|
|
66
|
+
| `sleep N && check` 轮询 | 禁止 | 浪费时间 |
|
|
67
|
+
| 全量重写已有测试 | 禁止 | 丢失 rescue 成果 |
|
|
68
|
+
| 首次跑 `flutter test` | 禁止 | 没实现,编译不过,用 `flutter analyze` |
|
|
69
|
+
|
|
70
|
+
**挂死的测试分类**:标记为 `hung: needs mock infrastructure`,不是 `failed`。区别:
|
|
71
|
+
- `failed` = 行为不一致,rescue 修 v2 代码
|
|
72
|
+
- `hung` = mock 不完整,rescue 先修测试基础设施
|
|
58
73
|
|
|
59
74
|
---
|
|
60
75
|
|
|
@@ -131,7 +146,13 @@ investigator:
|
|
|
131
146
|
# 现有的保留,新增:
|
|
132
147
|
- 非首轮:先 review 上轮 git diff,判断方向是否正确
|
|
133
148
|
- 如果上轮 fix 没有让任何测试从 red→green,警告"无进展"
|
|
134
|
-
-
|
|
149
|
+
- 分类时标注严重度和类型:
|
|
150
|
+
CRITICAL: 编译错误(阻塞一切)
|
|
151
|
+
HIGH-INFRA: mock 不完整导致 test hang(阻塞行为验证,rescue 优先修)
|
|
152
|
+
HIGH-LOGIC: 逻辑测试 fail(行为不一致)
|
|
153
|
+
MEDIUM: widget 测试 fail(渲染/导航差异)
|
|
154
|
+
LOW: 样式差异
|
|
155
|
+
- hung 测试 ≠ failed 测试。hung = mock 基础设施问题,不是 v2 行为问题
|
|
135
156
|
```
|
|
136
157
|
|
|
137
158
|
### 收敛保护
|
|
@@ -144,9 +165,19 @@ rescue:
|
|
|
144
165
|
输出卡点分析 + 剩余问题清单
|
|
145
166
|
round_budget: |
|
|
146
167
|
每轮最多改 5 个文件
|
|
147
|
-
每轮必须让至少 1 个测试从 red/skip → green,否则视为无进展
|
|
168
|
+
每轮必须让至少 1 个测试从 red/skip/hung → green,否则视为无进展
|
|
169
|
+
priority_order: |
|
|
170
|
+
Phase 1: 修 CRITICAL(编译错误)
|
|
171
|
+
Phase 2: 修 HIGH-INFRA(mock 基础设施,让 hung 测试能跑)
|
|
172
|
+
Phase 3: 修 HIGH-LOGIC(逻辑测试,让 red 变 green)
|
|
173
|
+
Phase 4: 修 MEDIUM(widget 测试,让 red 变 green)
|
|
174
|
+
每个 phase 完成后才进入下一个
|
|
148
175
|
```
|
|
149
176
|
|
|
177
|
+
**为什么 HIGH-INFRA 优先于 HIGH-LOGIC?**
|
|
178
|
+
|
|
179
|
+
hung 的测试 = 行为没被验证 = 重写目标的盲区。如果跳过 mock 修复直接改逻辑,可能 20 个 widget 行为从来没被检验过。先让所有测试能跑(pass 或 fail),再让它们变绿。
|
|
180
|
+
|
|
150
181
|
### 完整 rescue workflow
|
|
151
182
|
|
|
152
183
|
```yaml
|