@ultime/codecraft 1.4.0 → 1.6.0

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.
Files changed (70) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/CONTRIBUTING.md +3 -0
  3. package/README.md +78 -39
  4. package/SKILL.md +13 -9
  5. package/VERSION +1 -1
  6. package/adapters/README.md +3 -4
  7. package/codecraft.config.example.json +5 -1
  8. package/docs/00-constitution.md +5 -5
  9. package/docs/01-family-cards.md +2 -2
  10. package/docs/02-ai-contract.md +14 -3
  11. package/docs/04-gates.md +21 -6
  12. package/docs/06-architecture.md +5 -3
  13. package/docs/07-ai-prompts.md +16 -7
  14. package/docs/08-audit-contract.md +141 -0
  15. package/docs/09-glossary.md +22 -0
  16. package/evals/cases.json +110 -0
  17. package/evals/fixtures/a11-marker/packages/core/dist/tokens.css +4 -0
  18. package/evals/fixtures/a11-marker/packages/core/package.json +1 -0
  19. package/evals/fixtures/a11-marker/packages/core/src/index.ts +1 -0
  20. package/evals/fixtures/a17-boundaries/codecraft.config.json +5 -0
  21. package/evals/fixtures/a17-boundaries/src/pages/home.ts +1 -0
  22. package/evals/fixtures/a17-default/src/pages/home.ts +1 -0
  23. package/evals/fixtures/a17-generated-data/src/icons/icons.ts +2 -0
  24. package/evals/fixtures/a17-generated-data/src/pages/home.ts +3 -0
  25. package/evals/fixtures/a17-generated-header/src/pages/home.ts +5 -0
  26. package/evals/fixtures/a17-generated-header/src/types/project.ts +4 -0
  27. package/evals/fixtures/a17-local/src/pages/home.ts +4 -0
  28. package/evals/fixtures/a17-local/src/types/local.ts +3 -0
  29. package/evals/fixtures/a17-local/src/utils/format.ts +3 -0
  30. package/evals/fixtures/a2-declared/packages/core/package.json +6 -0
  31. package/evals/fixtures/a2-declared/packages/core/src/index.ts +3 -0
  32. package/evals/fixtures/a2-declared/packages/kit/package.json +1 -0
  33. package/evals/fixtures/a2-workspace/packages/core/package.json +1 -0
  34. package/evals/fixtures/a2-workspace/packages/core/src/index.ts +3 -0
  35. package/evals/fixtures/a2-workspace/packages/kit/package.json +1 -0
  36. package/evals/fixtures/a21-doc-paths/packages/ui/README.md +5 -0
  37. package/evals/fixtures/a21-doc-paths/packages/ui/package.json +1 -0
  38. package/evals/fixtures/a21-doc-paths/packages/ui/src/index.ts +1 -0
  39. package/evals/fixtures/a21-placeholders/.env +2 -0
  40. package/evals/fixtures/a21-placeholders/server/application.yml +9 -0
  41. package/evals/fixtures/a21-placeholders/src/pages/home.ts +1 -0
  42. package/evals/fixtures/a21-plaintext/application.yml +5 -0
  43. package/evals/fixtures/a21-plaintext/src/main/java/Ali.java +3 -0
  44. package/evals/fixtures/a21-plaintext/src/pages/home.ts +1 -0
  45. package/evals/fixtures/a6-clean/src/pages/handled.ts +8 -0
  46. package/evals/fixtures/a6-empty-catch/src/pages/empty.ts +3 -0
  47. package/evals/fixtures/ignore-active/codecraft.config.json +5 -0
  48. package/evals/fixtures/ignore-active/src/pages/home.ts +1 -0
  49. package/evals/fixtures/ignore-expired/codecraft.config.json +5 -0
  50. package/evals/fixtures/ignore-expired/src/pages/home.ts +1 -0
  51. package/evals/fixtures/library-a11/dist/tokens.css +3 -0
  52. package/evals/fixtures/library-a11/package.json +4 -0
  53. package/evals/fixtures/library-a11/src/index.ts +1 -0
  54. package/evals/fixtures/zero-files/package.json +4 -0
  55. package/evals/golden-tasks.md +14 -1
  56. package/evals/run.mjs +75 -0
  57. package/package.json +4 -2
  58. package/prompts/output.md +19 -4
  59. package/scenarios/architecture-report.md +88 -0
  60. package/scenarios/audit-existing.md +15 -8
  61. package/scenarios/new-project.md +1 -1
  62. package/scenarios/refactor-review.md +1 -1
  63. package/src/check.mjs +290 -40
  64. package/src/cli.mjs +158 -8
  65. package/src/gates.mjs +28 -1
  66. package/src/plan.mjs +2 -0
  67. package/templates/README.md +3 -1
  68. package/templates/architecture-report.md +97 -0
  69. package/adapters/claude/SKILL.md +0 -42
  70. package/adapters/trae/SKILL.md +0 -42
package/src/cli.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  import fs from 'node:fs'
2
2
  import path from 'node:path'
3
+ import { spawnSync } from 'node:child_process'
3
4
  import { check } from './check.mjs'
4
5
  import { loadConfig, runGates } from './gates.mjs'
5
6
  import { buildPlan, summarizePlan } from './plan.mjs'
@@ -22,12 +23,15 @@ Options:
22
23
  --root <path> Project root (default: cwd)
23
24
  --pack app|library|design-system|auto Rule pack (default: auto)
24
25
  --config <path> Config file (default: codecraft.config.json)
26
+ --changed Only report findings in changed / untracked files
27
+ --since <ref> Only report findings changed since a git ref (e.g. origin/main)
28
+ --exclude <glob> Skip files when scanning (repeatable; e.g. "evals/fixtures/**")
25
29
  --no-gates Skip gates in audit / plan
26
30
  --with-gates Run configured gates in plan
27
31
  --fail-fast Stop gates after the first failure
28
32
  --name <name> Scaffold name (required with --apply)
29
33
  --apply Write the scaffold; existing paths are skipped
30
- --format md|json Output format (default: md)
34
+ --format md|json|sarif Output format (default: md)
31
35
  --severity warn|error Reported severity (default: warn)
32
36
  --ci Treat findings as errors
33
37
  --help, -h
@@ -106,9 +110,28 @@ export function main(argv) {
106
110
  return 0
107
111
  }
108
112
 
109
- const result = check(root, { pack })
113
+ const result = check(root, {
114
+ pack,
115
+ boundaries: config.config.boundaries,
116
+ exclude: args.exclude,
117
+ })
118
+ let changed = null
119
+ let scoped = result.findings
120
+ if (args.changed || args.since) {
121
+ try {
122
+ changed = changedFiles(root, args.since)
123
+ } catch (error) {
124
+ console.error(`codecraft: ${error.message}`)
125
+ return 2
126
+ }
127
+ const files = new Set(changed)
128
+ scoped = scoped.filter((finding) => {
129
+ const file = finding.file.replace(/\\/g, '/')
130
+ return files.has(file) || [...files].some((candidate) => candidate.endsWith(`/${file}`))
131
+ })
132
+ }
110
133
  const severity = args.ci ? 'error' : args.severity
111
- const findings = result.findings.map((finding) => ({ ...finding, severity }))
134
+ const findings = scoped.map((finding) => ({ ...finding, severity }))
112
135
  const filtered = applyIgnores(findings, config.config.ignore ?? [])
113
136
  const activeFindings = filtered.findings
114
137
  const warnings = []
@@ -127,8 +150,11 @@ export function main(argv) {
127
150
  root,
128
151
  config: config.file,
129
152
  severity,
130
- rules: pack === 'app' ? ['A17', 'A21'] : ['A2', 'A11', 'A21'],
153
+ rules: pack === 'app' ? ['A6', 'A17', 'A21'] : ['A2', 'A6', 'A11', 'A21'],
131
154
  files: result.files,
155
+ scope: args.changed || args.since ? 'changed' : 'full',
156
+ changed: changed?.length ?? null,
157
+ exclude: args.exclude,
132
158
  findings: activeFindings.length,
133
159
  ignored: filtered.ignored.length,
134
160
  expired: filtered.expired.length,
@@ -161,6 +187,8 @@ export function main(argv) {
161
187
  2,
162
188
  ),
163
189
  )
190
+ } else if (args.format === 'sarif') {
191
+ console.log(formatSarif(meta, activeFindings))
164
192
  } else if (command === 'plan') {
165
193
  console.log(formatPlan(meta, activeFindings, plan, gates))
166
194
  } else {
@@ -200,6 +228,9 @@ function parseArgs(argv) {
200
228
  failFast: false,
201
229
  name: '',
202
230
  apply: false,
231
+ changed: false,
232
+ since: '',
233
+ exclude: [],
203
234
  format: 'md',
204
235
  severity: 'warn',
205
236
  ci: false,
@@ -216,6 +247,13 @@ function parseArgs(argv) {
216
247
  else if (arg === '--with-gates') args.withGates = true
217
248
  else if (arg === '--fail-fast') args.failFast = true
218
249
  else if (arg === '--apply') args.apply = true
250
+ else if (arg === '--changed') args.changed = true
251
+ else if (arg === '--since') args.since = argv[++i] ?? ''
252
+ else if (arg === '--exclude') {
253
+ const pattern = argv[++i] ?? ''
254
+ if (!pattern) fail('--exclude needs a path or glob (e.g. "evals/fixtures/**")')
255
+ args.exclude.push(pattern)
256
+ }
219
257
  else if (arg === '--name') args.name = argv[++i] ?? ''
220
258
  else if (arg === '--root') args.root = argv[++i] ?? '.'
221
259
  else if (arg === '--pack') args.pack = argv[++i] ?? 'auto'
@@ -227,7 +265,9 @@ function parseArgs(argv) {
227
265
  }
228
266
 
229
267
  if (!['app', 'library', 'design-system', 'auto'].includes(args.pack)) fail(`invalid --pack: ${args.pack}`)
230
- if (args.format !== 'md' && args.format !== 'json') fail(`invalid --format: ${args.format}`)
268
+ if (args.format !== 'md' && args.format !== 'json' && args.format !== 'sarif') {
269
+ fail(`invalid --format: ${args.format}`)
270
+ }
231
271
  if (args.severity !== 'warn' && args.severity !== 'error') {
232
272
  fail(`invalid --severity: ${args.severity}`)
233
273
  }
@@ -235,6 +275,39 @@ function parseArgs(argv) {
235
275
  return args
236
276
  }
237
277
 
278
+ function changedFiles(root, since) {
279
+ const top = git(root, ['rev-parse', '--show-toplevel'])
280
+ if (top == null) {
281
+ throw new Error('not a git repository; --changed / --since need git (run inside a git repo or drop the flag)')
282
+ }
283
+
284
+ const lists = [git(root, ['diff', '--name-only', '--diff-filter=ACMRT', 'HEAD'])]
285
+ if (since) lists.push(git(root, ['diff', '--name-only', '--diff-filter=ACMRT', `${since}...HEAD`]))
286
+ lists.push(git(root, ['ls-files', '--others', '--exclude-standard']))
287
+
288
+ const realRoot = fs.realpathSync(root)
289
+ const files = new Set()
290
+ for (const list of lists) {
291
+ if (!list) continue
292
+ for (const line of list.split('\n')) {
293
+ const file = line.trim()
294
+ if (!file) continue
295
+ const relative = path.relative(realRoot, path.resolve(top, file)).split(path.sep).join('/')
296
+ if (relative && !relative.startsWith('..')) files.add(relative)
297
+ }
298
+ }
299
+ return [...files]
300
+ }
301
+
302
+ function git(root, args) {
303
+ const result = spawnSync('git', ['-C', root, ...args], { encoding: 'utf8' })
304
+ if (result.status !== 0) {
305
+ const message = (result.stderr || '').trim()
306
+ throw new Error(`git ${args.join(' ')} failed${message ? `: ${message}` : ''}`)
307
+ }
308
+ return result.stdout.trim()
309
+ }
310
+
238
311
  export function detectPack(root) {
239
312
  if (isDir(path.join(root, 'apps'))) return 'app'
240
313
  if (hasAppMarkers(root)) return 'app'
@@ -256,13 +329,28 @@ const APP_FILE_MARKERS = [
256
329
  'src/app.config.ts',
257
330
  'taro.config.js',
258
331
  'taro.config.ts',
332
+ 'vue.config.js',
333
+ 'vue.config.ts',
259
334
  ]
260
335
  const APP_DEPS = ['nuxt', '@tarojs/taro', '@dcloudio/uni-app', 'uni-app', 'next']
336
+ /** 单页 Web 应用入口;库的 demo 页通常不具备「框架依赖 + 入口 + html」三件套。 */
337
+ const WEB_ENTRIES = [
338
+ 'src/main.ts',
339
+ 'src/main.js',
340
+ 'src/main.tsx',
341
+ 'src/main.jsx',
342
+ 'src/index.ts',
343
+ 'src/index.js',
344
+ 'src/index.tsx',
345
+ 'src/index.jsx',
346
+ ]
347
+ const WEB_DEPS = ['vue', 'react', 'react-dom', 'react-scripts', 'svelte', 'solid-js', 'preact', '@angular/core']
261
348
 
262
349
  function hasAppMarkers(root) {
263
350
  if (APP_DIR_MARKERS.some((dir) => isDir(path.join(root, dir)))) return true
264
351
  if (APP_FILE_MARKERS.some((file) => isFile(path.join(root, file)))) return true
265
352
  if (hasUniAppFiles(root)) return true
353
+ if (hasWebEntry(root)) return true
266
354
  return hasAppDependency(root)
267
355
  }
268
356
 
@@ -282,6 +370,7 @@ function hasNestedApp(root) {
282
370
  if (APP_DIR_MARKERS.some((dir) => isDir(path.join(child, dir)))) return true
283
371
  if (APP_FILE_MARKERS.some((file) => isFile(path.join(child, file)))) return true
284
372
  if (hasUniAppFiles(child)) return true
373
+ if (hasWebEntry(child)) return true
285
374
  if (hasAppDependency(child)) return true
286
375
  }
287
376
  return false
@@ -294,14 +383,25 @@ function hasUniAppFiles(root) {
294
383
  }
295
384
 
296
385
  function hasAppDependency(root) {
386
+ return dependencyNames(root).some((dep) => APP_DEPS.includes(dep))
387
+ }
388
+
389
+ /** 框架依赖 + html + 入口;三者齐全才按单页应用处理,避免把带 demo 的库判成 app。 */
390
+ function hasWebEntry(root) {
391
+ const html = isFile(path.join(root, 'index.html')) || isFile(path.join(root, 'public', 'index.html'))
392
+ if (!html) return false
393
+ if (!dependencyNames(root).some((dep) => WEB_DEPS.includes(dep))) return false
394
+ return WEB_ENTRIES.some((file) => isFile(path.join(root, file)))
395
+ }
396
+
397
+ function dependencyNames(root) {
297
398
  let manifest
298
399
  try {
299
400
  manifest = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'))
300
401
  } catch {
301
- return false
402
+ return []
302
403
  }
303
- const deps = { ...(manifest.dependencies ?? {}), ...(manifest.devDependencies ?? {}) }
304
- return APP_DEPS.some((dep) => dep in deps)
404
+ return Object.keys({ ...(manifest.dependencies ?? {}), ...(manifest.devDependencies ?? {}) })
305
405
  }
306
406
 
307
407
  function isFile(target) {
@@ -317,6 +417,55 @@ function fail(message) {
317
417
  process.exit(2)
318
418
  }
319
419
 
420
+ function formatSarif(meta, findings) {
421
+ const rules = meta.rules.map((id) => ({
422
+ id,
423
+ name: SARIF_RULES[id]?.name ?? id,
424
+ shortDescription: { text: SARIF_RULES[id]?.short ?? id },
425
+ }))
426
+ return JSON.stringify(
427
+ {
428
+ $schema: 'https://json.schemastore.org/sarif-2.1.0.json',
429
+ version: '2.1.0',
430
+ runs: [
431
+ {
432
+ tool: {
433
+ driver: {
434
+ name: 'codecraft',
435
+ informationUri: 'https://github.com/ultime-space/skills',
436
+ version: meta.version,
437
+ rules,
438
+ },
439
+ },
440
+ results: findings.map((finding) => ({
441
+ ruleId: finding.rule,
442
+ level: finding.severity === 'error' ? 'error' : 'warning',
443
+ message: { text: finding.message },
444
+ locations: [
445
+ {
446
+ physicalLocation: {
447
+ artifactLocation: { uri: finding.file.replace(/\\/g, '/') },
448
+ region: { startLine: finding.line },
449
+ },
450
+ },
451
+ ],
452
+ })),
453
+ },
454
+ ],
455
+ },
456
+ null,
457
+ 2,
458
+ )
459
+ }
460
+
461
+ const SARIF_RULES = {
462
+ A2: { name: 'DependencyDirection', short: 'Dependencies must point inward' },
463
+ A6: { name: 'EmptyCatch', short: 'Empty catch swallows failures' },
464
+ A11: { name: 'GeneratedReadOnly', short: 'Generated files must be read-only and marked' },
465
+ A17: { name: 'ExternalBoundary', short: 'Internal layers must not import external or generated types' },
466
+ A21: { name: 'SecretScan', short: 'No secrets or internal paths in repository' },
467
+ }
468
+
320
469
  function formatReport(meta, findings, ignored, expired, gates) {
321
470
  const lines = header(meta)
322
471
 
@@ -457,6 +606,7 @@ function header(meta) {
457
606
  `- Pack: ${meta.pack}`,
458
607
  `- Root: ${meta.root}`,
459
608
  `- Config: ${meta.config ?? '(none)'}`,
609
+ `- Exclude: ${meta.exclude?.length ? meta.exclude.join(', ') : '(none)'}`,
460
610
  `- Rules: ${meta.rules.join(' / ')}`,
461
611
  `- Severity: ${meta.severity}`,
462
612
  `- Files: ${meta.files}`,
package/src/gates.mjs CHANGED
@@ -27,7 +27,34 @@ export function loadConfig(root, configPath) {
27
27
  }
28
28
  }
29
29
 
30
- return { file, config: { ...config, ignore: validateIgnore(config.ignore, file) } }
30
+ return {
31
+ file,
32
+ config: {
33
+ ...config,
34
+ ignore: validateIgnore(config.ignore, file),
35
+ ...(config.boundaries ? { boundaries: validateBoundaries(config.boundaries, file) } : {}),
36
+ },
37
+ }
38
+ }
39
+
40
+ function validateBoundaries(value, file) {
41
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
42
+ throw new Error(`invalid config ${file}: "boundaries" must be an object with external / generated arrays`)
43
+ }
44
+ const boundaries = {}
45
+ for (const key of ['external', 'generated']) {
46
+ if (value[key] == null) continue
47
+ if (!Array.isArray(value[key])) {
48
+ throw new Error(`invalid config ${file}: boundaries.${key} must be an array of import prefixes or globs`)
49
+ }
50
+ boundaries[key] = value[key].map((item) => {
51
+ if (typeof item !== 'string' || !item.trim()) {
52
+ throw new Error(`invalid config ${file}: boundaries.${key} entries must be non-empty strings`)
53
+ }
54
+ return item.trim()
55
+ })
56
+ }
57
+ return boundaries
31
58
  }
32
59
 
33
60
  export function runGates(root, gates, options = {}) {
package/src/plan.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  const ACTIONS = {
2
2
  A2: 'Declare the workspace dependency in package.json, or remove the import; if shared, move it to a lower-layer package.',
3
3
  A4: 'Move the external import to a Wrapper/API module; expose an internal type to the caller.',
4
+ A6: 'Return a Result or handle the error; never swallow it in an empty catch.',
4
5
  A11: "Regenerate the file from source and add a 'do not edit' marker; if it is not generated, move it out of generated paths.",
5
6
  A17: 'Move the external import to a Wrapper/API module; expose an internal type to the caller.',
6
7
  }
@@ -8,6 +9,7 @@ const ACTIONS = {
8
9
  const VERIFY = {
9
10
  A2: 'codecraft check --pack library',
10
11
  A4: 'codecraft check --pack app',
12
+ A6: 'codecraft check',
11
13
  A11: 'codecraft check --pack library',
12
14
  A17: 'codecraft check --pack app',
13
15
  }
@@ -6,6 +6,8 @@
6
6
  |---|---|
7
7
  | `app/` | 应用骨架:`README.md` + `package.json` |
8
8
  | `library/` | 包骨架:`README.md` + `CHANGELOG.md` + `compat.md` + `package.json` |
9
+ | `architecture-report.md` | 代码架构分析报告模板(Agent 输出用,不是 init 骨架) |
9
10
 
10
11
  - 目录结构由 `src/init.mjs` 定义,模板只提供文件内容。
11
- - 页面 / 组件 / Wrapper 的单文件形态见 `docs/01-family-cards.md`,不单独出模板:不同框架的写法差异大于共性。
12
+ - `architecture-report.md` 只被 `scenarios/architecture-report.md` 引用,不参与 `init`。
13
+ - 页面 / 组件 / Wrapper的单文件形态见 `docs/01-family-cards.md`,不单独出模板:不同框架的写法差异大于共性。
@@ -0,0 +1,97 @@
1
+ # <项目 / 模块> 代码架构分析报告(Codecraft)
2
+
3
+ > 模式:Audit / Plan,只读 · 日期:YYYY-MM-DD · 仓库:`<repo>` · 分支:`<branch>` · HEAD:`<sha>`
4
+ > 范围:`<目录 / 包>` · 规则版本:Codecraft `<version>`
5
+ > 只读声明:未改代码、未起服务。未执行:`<typecheck / build / 单测>`。
6
+ > 边界:本文只讨论代码架构;业务能力、角色、业务流程、领域规则不在范围。
7
+
8
+ ## 1. 结论与置信度
9
+
10
+ - 一句话结论:
11
+ - 置信度:High / Medium / Low(依据:静态 + 人工抽样 + 关键路径)
12
+ - 最高风险:
13
+ - 最需要先做的决定:
14
+
15
+ ## 2. 范围与方法
16
+
17
+ | 项 | 内容 |
18
+ |---|---|
19
+ | 范围 | |
20
+ | 已执行 | |
21
+ | 未执行 | |
22
+ | 覆盖边界 | |
23
+ | 判定口径 | |
24
+
25
+ ## 3. 架构现状
26
+
27
+ ### 3.1 系统与容器
28
+
29
+ | 单元 | 职责 | 运行时 / 部署 | 外部依赖 |
30
+ |---|---|---|---|
31
+ | | | | |
32
+
33
+ ### 3.2 模块与依赖
34
+
35
+ | 模块 / 包 | 职责 | 允许依赖 | 禁止依赖 | 证据 |
36
+ |---|---|---|---|---|
37
+ | | | | | |
38
+
39
+ - 依赖方向:
40
+ - 边界与内外分离:
41
+ - 公共 API / 内部实现:
42
+
43
+ ### 3.3 关键链路
44
+
45
+ | 链路 | 入口 | 关键节点 | 失败模式 | 证据 |
46
+ |---|---|---|---|---|
47
+ | 请求 | | | | |
48
+ | 状态 | | | | |
49
+ | 错误 | | | | |
50
+ | 数据 | | | | |
51
+ | 生成 | | | | |
52
+
53
+ ## 4. A1–A21 判定
54
+
55
+ | ID | 判定 | 证据 | 局限 |
56
+ |---|---|---|---|
57
+ | A1 | pass / pass(静态)/ warn / fail / na | `path:line` 或命令 | |
58
+ | … | | | |
59
+
60
+ - 一致性检查:
61
+ - `codecraft check` 结果:`files / findings / 覆盖范围`
62
+ - A17 / A21 盲区:
63
+
64
+ ## 5. 风险与技术债
65
+
66
+ | 优先级 | 问题 | 证据 | 影响 | 建议 |
67
+ |---|---|---|---|---|
68
+ | P0 | | | | |
69
+ | P1 | | | | |
70
+ | P2 | | | | |
71
+ | P3 | | | | |
72
+
73
+ ## 6. 演进计划
74
+
75
+ | 阶段 | 内容 | 可回滚 | 验收 |
76
+ |---|---|---|---|
77
+ | 0 | | | |
78
+ | 1 | | | |
79
+ | 2 | | | |
80
+
81
+ - 不写时间估算。
82
+ - 每阶段一个可验收的垂直切片。
83
+
84
+ ## 7. 未知项与待确认
85
+
86
+ | # | 问题 | 为什么无法确认 | 需要谁 / 什么证据 |
87
+ |---|---|---|---|
88
+ | 1 | | | |
89
+
90
+ ## 8. 附录:证据与命令
91
+
92
+ ```bash
93
+ # 本次执行的检查
94
+ ```
95
+
96
+ - 相关文件:
97
+ - 相关文档:
@@ -1,42 +0,0 @@
1
- ---
2
- name: codecraft
3
- description: 面向 JS/TS 的代码规范与架构设计(Codecraft)。默认 Web 前端,Node 后端可复用结构规则;用于审计、架构设计、重构评审、规范检查与脚手架。
4
- ---
5
-
6
- # Codecraft(代码手艺)
7
-
8
- > 方向:JS/TS(默认前端)。后端只复用结构规则;Page / Component 等前端族不套用到后端。
9
-
10
- ## 先读
11
-
12
- 1. 项目 `AGENTS.md` / `rules/`
13
- 2. `../../docs/00-constitution.md`
14
- 3. 只读相关族卡:`../../docs/01-family-cards.md`
15
- 4. 设计架构时:`../../docs/06-architecture.md`
16
- 5. 需要选型时:`../../docs/05-patterns.md`
17
- 6. 选场景:`../../scenarios/`
18
-
19
- ## 模式
20
-
21
- - **Audit(审计)**:只读,出报告。
22
- - **Plan(计划)**:只读,出架构 / 升级计划。
23
- - **Apply(执行)**:改代码 + 跑门禁。
24
-
25
- ## 工作流
26
-
27
- 1. 判定任务属于哪个场景。
28
- 2. 只读相关族卡,不要一次加载全部。
29
- 3. 先出计划;Apply 前确认范围。
30
- 4. 跑项目验证命令;不能跑要说明原因。
31
- 5. 按 `../../prompts/output.md` 输出。
32
-
33
- ## 禁止
34
-
35
- - Audit / Plan 模式改文件。
36
- - 把业务逻辑放进 Transport 或 Page。
37
- - 内部代码 import `external/` 或生成类型。
38
- - 手改生成物。
39
- - 写敏感信息;发现即停止、脱敏、提示轮换。
40
- - 安全红线登记例外。
41
-
42
- 规则正文只在 `docs/`;本文件只做入口。
@@ -1,42 +0,0 @@
1
- ---
2
- name: codecraft
3
- description: 面向 JS/TS 的代码规范与架构设计(Codecraft)。默认 Web 前端,Node 后端可复用结构规则;用于审计、架构设计、重构评审、规范检查与脚手架。
4
- ---
5
-
6
- # Codecraft(代码手艺)
7
-
8
- > 方向:JS/TS(默认前端)。后端只复用结构规则;Page / Component 等前端族不套用到后端。
9
-
10
- ## 先读
11
-
12
- 1. 项目 `AGENTS.md` / `rules/`
13
- 2. `../../docs/00-constitution.md`
14
- 3. 只读相关族卡:`../../docs/01-family-cards.md`
15
- 4. 设计架构时:`../../docs/06-architecture.md`
16
- 5. 需要选型时:`../../docs/05-patterns.md`
17
- 6. 选场景:`../../scenarios/`
18
-
19
- ## 模式
20
-
21
- - **Audit(审计)**:只读,出报告。
22
- - **Plan(计划)**:只读,出架构 / 升级计划。
23
- - **Apply(执行)**:改代码 + 跑门禁。
24
-
25
- ## 工作流
26
-
27
- 1. 判定任务属于哪个场景。
28
- 2. 只读相关族卡,不要一次加载全部。
29
- 3. 先出计划;Apply 前确认范围。
30
- 4. 跑项目验证命令;不能跑要说明原因。
31
- 5. 按 `../../prompts/output.md` 输出。
32
-
33
- ## 禁止
34
-
35
- - Audit / Plan 模式改文件。
36
- - 把业务逻辑放进 Transport 或 Page。
37
- - 内部代码 import `external/` 或生成类型。
38
- - 手改生成物。
39
- - 写敏感信息;发现即停止、脱敏、提示轮换。
40
- - 安全红线登记例外。
41
-
42
- 规则正文只在 `docs/`;本文件只做入口。