@miniidealab/openlogos 0.9.7 → 0.9.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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "openlogos",
3
3
  "description": "OpenLogos methodology plugin — structured AI-driven development with Why → What → How progression",
4
- "version": "0.9.7",
4
+ "version": "0.9.9",
5
5
  "author": {
6
6
  "name": "MiniIdeaLab",
7
7
  "url": "https://github.com/miniidealab"
@@ -1 +1 @@
1
- {"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../../src/commands/archive.ts"],"names":[],"mappings":"AAIA,wBAAgB,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,QAoDpC"}
1
+ {"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../../src/commands/archive.ts"],"names":[],"mappings":"AAYA,wBAAgB,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,QAqDpC"}
@@ -1,6 +1,13 @@
1
1
  import { existsSync, mkdirSync, renameSync, readFileSync, unlinkSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import { readLocale, t } from '../i18n.js';
4
+ function archiveDirName(slug) {
5
+ const now = new Date();
6
+ const pad = (n) => String(n).padStart(2, '0');
7
+ const date = `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}`;
8
+ const time = `${pad(now.getHours())}${pad(now.getMinutes())}`;
9
+ return `${date}-${time}-${slug}`;
10
+ }
4
11
  export function archive(slug) {
5
12
  const root = process.cwd();
6
13
  const configPath = join(root, 'logos', 'logos.config.json');
@@ -22,9 +29,10 @@ export function archive(slug) {
22
29
  process.exit(1);
23
30
  }
24
31
  const archiveDir = join(root, 'logos', 'changes', 'archive');
25
- const archivePath = join(archiveDir, slug);
32
+ const archiveDirname = archiveDirName(slug);
33
+ const archivePath = join(archiveDir, archiveDirname);
26
34
  if (existsSync(archivePath)) {
27
- console.error(`Error: Archive '${slug}' already exists in logos/changes/archive/.`);
35
+ console.error(`Error: Archive '${archiveDirname}' already exists in logos/changes/archive/.`);
28
36
  process.exit(1);
29
37
  }
30
38
  mkdirSync(archiveDir, { recursive: true });
@@ -43,6 +51,6 @@ export function archive(slug) {
43
51
  }
44
52
  }
45
53
  console.log(`\n${t(locale, 'archive.done', { slug })}`);
46
- console.log(`${t(locale, 'archive.path', { slug })}\n`);
54
+ console.log(`${t(locale, 'archive.path', { slug: archiveDirname })}\n`);
47
55
  }
48
56
  //# sourceMappingURL=archive.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/commands/archive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACtF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,UAAU,OAAO,CAAC,IAAa;IACnC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC;IAE5D,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC3D,OAAO,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;QACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAEhC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACtD,OAAO,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACjD,OAAO,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;IAExD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,KAAK,CAAC,2BAA2B,IAAI,cAAc,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IAC7D,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAE3C,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,KAAK,CAAC,mBAAmB,IAAI,6CAA6C,CAAC,CAAC;QACpF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,UAAU,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IAEpC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,kBAAkB,CAAC,CAAC;IAC1D,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;YAC3D,IAAI,KAAK,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;gBAChC,UAAU,CAAC,SAAS,CAAC,CAAC;gBACtB,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,UAAU,CAAC,SAAS,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,cAAc,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;IACxD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,cAAc,EAAE,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC;AAC1D,CAAC"}
1
+ {"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/commands/archive.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miniidealab/openlogos",
3
- "version": "0.9.7",
3
+ "version": "0.9.8",
4
4
  "description": "CLI tool for the OpenLogos software engineering methodology",
5
5
  "type": "module",
6
6
  "bin": {
@@ -125,9 +125,21 @@ test-writer 不写代码;code-implementor 不设计用例;code-reviewer 不
125
125
  - `UT-S01-01` 在测试代码中必须原封不动使用,不允许改名、缩写或重排序
126
126
  - 这些 ID 是跨阶段契约:test-cases.md → 测试代码 → test-results.jsonl → acceptance-report.md
127
127
 
128
- #### OpenLogos Reporter 嵌入
128
+ #### OpenLogos Reporter 嵌入(强制前置)
129
129
 
130
- 每个测试文件必须嵌入 OpenLogos reporter,按照 `logos/spec/test-results.md` 中的模板实现:
130
+ > ⚠️ **Reporter 是第零步,不是最后一步。** 在写任何测试用例代码之前,必须先创建共享 reporter 工具文件。没有 reporter,`openlogos verify` 无法读取结果,Gate 3.5 永远无法通过。
131
+
132
+ **第一步:创建共享 reporter 文件**
133
+
134
+ 在测试目录下创建共享 reporter 工具文件(根据 `tech_stack` 选择语言),所有测试文件统一从这里 import,不要在每个测试文件里重复内联:
135
+
136
+ ```
137
+ <sourceRoots.test>/
138
+ └── helpers/
139
+ └── reporter.ts ← 先建这个,再写测试用例
140
+ ```
141
+
142
+ reporter 模板见 `logos/spec/test-results.md`。核心要求:
131
143
 
132
144
  - 输出路径:`logos/resources/verify/test-results.jsonl`
133
145
  - 格式:JSONL(每行一个 JSON 对象)
@@ -135,7 +147,28 @@ test-writer 不写代码;code-implementor 不设计用例;code-reviewer 不
135
147
  - 首次运行 truncate 文件,后续 append
136
148
  - 写入前确保 `logos/resources/verify/` 目录存在
137
149
 
138
- 根据 `tech_stack` 选择对应语言的 reporter 模板(TypeScript/Python/Go 等,模板见 `logos/spec/test-results.md`)。
150
+ **第二步:在每个测试文件顶部 import reporter**
151
+
152
+ ```typescript
153
+ import { reportResult } from './helpers/reporter';
154
+ ```
155
+
156
+ **第三步:每个测试用例用 try/catch 包裹并调用 reportResult**
157
+
158
+ ```typescript
159
+ it('UT-S01-01: ...', () => {
160
+ const start = Date.now();
161
+ try {
162
+ // 测试逻辑
163
+ reportResult('UT-S01-01', 'pass', undefined, Date.now() - start);
164
+ } catch (e) {
165
+ reportResult('UT-S01-01', 'fail', String(e), Date.now() - start);
166
+ throw e;
167
+ }
168
+ });
169
+ ```
170
+
171
+ Playwright E2E 测试使用 `test.afterEach` + fixture 捕获结果,参见 `logos/spec/test-results.md` 中的 Playwright 模板。
139
172
 
140
173
  #### 测试代码结构
141
174
 
@@ -153,7 +186,10 @@ test-writer 不写代码;code-implementor 不设计用例;code-reviewer 不
153
186
  - [ ] DB 操作的表名、列名与 DDL 一致
154
187
  - [ ] 多表写操作已使用事务
155
188
  - [ ] 批前声明的所有 UT/ST ID 在测试代码中都存在
156
- - [ ] Reporter 已嵌入且输出路径正确
189
+ - [ ] **共享 reporter 文件已创建**(`<test>/helpers/reporter.ts` 或等效路径)
190
+ - [ ] **每个测试文件都已 import reporter**,无遗漏
191
+ - [ ] **每个测试用例都有 try/catch + reportResult 调用**,无遗漏
192
+ - [ ] 运行测试后 `logos/resources/verify/test-results.jsonl` 已生成且非空
157
193
  - [ ] 无硬编码敏感信息(密码、密钥、测试数据)
158
194
 
159
195
  如果发现不一致,**立即修正后再交付**,不要等到 code-reviewer 阶段。
@@ -109,6 +109,21 @@ reporter 在写入前应确保 `logos/resources/verify/` 目录存在(`mkdir -
109
109
 
110
110
  以下是各语言的 reporter 参考实现。AI 在 Phase 3 Step 4(代码生成,由 `code-implementor` Skill 驱动)时,应根据项目的 `tech_stack` 选择对应语言的模板,嵌入到测试代码中。
111
111
 
112
+ ### 推荐:共享 reporter 文件模式
113
+
114
+ **不要在每个测试文件里内联 reporter 代码**。多文件项目应创建一个共享工具文件,统一 import:
115
+
116
+ ```
117
+ <test-root>/
118
+ └── helpers/
119
+ └── reporter.ts ← 所有测试文件从这里 import
120
+ ```
121
+
122
+ 这样做的好处:
123
+ - 路径配置只有一处,不会因为文件位置不同导致写入路径错误
124
+ - 新增测试文件时只需 import,不会遗漏 reporter
125
+ - 清空策略(truncate)只在一处维护
126
+
112
127
  ### TypeScript (vitest / jest)
113
128
 
114
129
  ````typescript