@bendyline/gilde 0.1.40 → 0.1.41
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/authoring/gstack/overlays/investigate.json +1 -0
- package/authoring/gstack/overlays/qa-only.json +1 -0
- package/authoring/gstack/wave.json +12 -2
- package/authoring/tactical/books/accessibility-retrofit.json +188 -0
- package/authoring/tactical/books/apply-review-findings.json +189 -0
- package/authoring/tactical/books/bug-fix-tdd.json +237 -0
- package/authoring/tactical/books/ci-pipeline.json +168 -0
- package/authoring/tactical/books/codemod-sweep.json +182 -0
- package/authoring/tactical/books/dependency-upgrade.json +196 -0
- package/authoring/tactical/books/flaky-test-fix.json +238 -0
- package/authoring/tactical/books/hotfix-flow.json +187 -0
- package/authoring/tactical/books/perf-optimization.json +219 -0
- package/authoring/tactical/books/refactor-module.json +217 -0
- package/authoring/tactical/books/schema-migration.json +192 -0
- package/authoring/tactical/books/test-suite-backfill.json +172 -0
- package/authoring/tactical/books/type-safety-pass.json +185 -0
- package/authoring/tactical/books/ux-update.json +178 -0
- package/authoring/tactical/evals/accessibility-retrofit.json +230 -0
- package/authoring/tactical/evals/apply-review-findings.json +290 -0
- package/authoring/tactical/evals/bug-fix-tdd.json +221 -0
- package/authoring/tactical/evals/ci-pipeline.json +227 -0
- package/authoring/tactical/evals/codemod-sweep.json +252 -0
- package/authoring/tactical/evals/dependency-upgrade.json +235 -0
- package/authoring/tactical/evals/flaky-test-fix.json +239 -0
- package/authoring/tactical/evals/hotfix-flow.json +220 -0
- package/authoring/tactical/evals/perf-optimization.json +235 -0
- package/authoring/tactical/evals/refactor-module.json +241 -0
- package/authoring/tactical/evals/schema-migration.json +225 -0
- package/authoring/tactical/evals/test-suite-backfill.json +197 -0
- package/authoring/tactical/evals/type-safety-pass.json +221 -0
- package/authoring/tactical/evals/ux-update.json +206 -0
- package/authoring/tactical/wave.json +89 -0
- package/data/chat-models/de/deepseek-r1-8b-q4/manifest.json +56 -1
- package/data/chat-models/gl/glm-5.2-754b-q2/manifest.json +56 -0
- package/data/chat-models/gp/gpt-oss-120b-q4/manifest.json +73 -1
- package/data/chat-models/gp/gpt-oss-20b-q4/manifest.json +77 -1
- package/data/chat-models/index.json +1 -1
- package/data/chat-models/ll/llama3.2-3b-q4/manifest.json +3 -1
- package/data/chat-models/mi/mistral-7b-q4/manifest.json +54 -3
- package/data/chat-models/mi/mistral-medium-3.5-128b-q4/manifest.json +76 -1
- package/data/craftbook-templates/ac/accessibility-retrofit/manifest.json +5 -4
- package/data/craftbook-templates/ac/accessibility-retrofit/versions/2.0.0/craftbook.json +451 -0
- package/data/craftbook-templates/ac/accessibility-retrofit/versions/2.0.0/test.json +231 -0
- package/data/craftbook-templates/al/alt-text-pass/manifest.json +5 -1
- package/data/craftbook-templates/ap/apply-review-findings/art.json +12 -0
- package/data/craftbook-templates/ap/apply-review-findings/logo.webp +0 -0
- package/data/craftbook-templates/ap/apply-review-findings/manifest.json +23 -0
- package/data/craftbook-templates/ap/apply-review-findings/versions/1.0.0/craftbook.json +436 -0
- package/data/craftbook-templates/ap/apply-review-findings/versions/1.0.0/test.json +291 -0
- package/data/craftbook-templates/br/browser-qa-audit/manifest.json +5 -1
- package/data/craftbook-templates/br/browser-qa-audit/versions/2.0.5/craftbook.json +438 -0
- package/data/craftbook-templates/br/browser-qa-audit/versions/2.0.5/test.json +379 -0
- package/data/craftbook-templates/bu/bug-fix-tdd/manifest.json +3 -3
- package/data/craftbook-templates/bu/bug-fix-tdd/versions/2.0.0/craftbook.json +545 -0
- package/data/craftbook-templates/bu/bug-fix-tdd/versions/2.0.0/test.json +222 -0
- package/data/craftbook-templates/ch/changelog-cut/manifest.json +5 -1
- package/data/craftbook-templates/ch/changelog-writeup/manifest.json +5 -1
- package/data/craftbook-templates/ci/ci-pipeline/manifest.json +5 -3
- package/data/craftbook-templates/ci/ci-pipeline/versions/2.0.0/craftbook.json +423 -0
- package/data/craftbook-templates/ci/ci-pipeline/versions/2.0.0/test.json +228 -0
- package/data/craftbook-templates/co/codemod-sweep/art.json +12 -0
- package/data/craftbook-templates/co/codemod-sweep/logo.webp +0 -0
- package/data/craftbook-templates/co/codemod-sweep/manifest.json +23 -0
- package/data/craftbook-templates/co/codemod-sweep/versions/1.0.0/craftbook.json +441 -0
- package/data/craftbook-templates/co/codemod-sweep/versions/1.0.0/test.json +253 -0
- package/data/craftbook-templates/de/dependency-upgrade/art.json +12 -0
- package/data/craftbook-templates/de/dependency-upgrade/logo.webp +0 -0
- package/data/craftbook-templates/de/dependency-upgrade/manifest.json +23 -0
- package/data/craftbook-templates/de/dependency-upgrade/versions/1.0.0/craftbook.json +459 -0
- package/data/craftbook-templates/de/dependency-upgrade/versions/1.0.0/test.json +236 -0
- package/data/craftbook-templates/fe/feature-flag-release/manifest.json +5 -1
- package/data/craftbook-templates/fe/feature-flag-rollout/manifest.json +4 -1
- package/data/craftbook-templates/fe/feature-flag-rollout/versions/1.1.0/craftbook.json +203 -0
- package/data/craftbook-templates/fe/feature-flag-rollout/versions/1.1.0/test.json +165 -0
- package/data/craftbook-templates/fl/flaky-test-fix/art.json +12 -0
- package/data/craftbook-templates/fl/flaky-test-fix/logo.webp +0 -0
- package/data/craftbook-templates/fl/flaky-test-fix/manifest.json +24 -0
- package/data/craftbook-templates/fl/flaky-test-fix/versions/1.0.0/craftbook.json +534 -0
- package/data/craftbook-templates/fl/flaky-test-fix/versions/1.0.0/test.json +240 -0
- package/data/craftbook-templates/ho/hotfix-flow/manifest.json +5 -3
- package/data/craftbook-templates/ho/hotfix-flow/versions/2.0.0/craftbook.json +442 -0
- package/data/craftbook-templates/ho/hotfix-flow/versions/2.0.0/test.json +221 -0
- package/data/craftbook-templates/in/investigate/manifest.json +4 -1
- package/data/craftbook-templates/in/investigate-root-cause/manifest.json +5 -1
- package/data/craftbook-templates/index.json +1 -1
- package/data/craftbook-templates/li/live-browser-qa/manifest.json +5 -1
- package/data/craftbook-templates/ni/nightly-fix-sweep/art.json +12 -0
- package/data/craftbook-templates/ni/nightly-fix-sweep/logo.webp +0 -0
- package/data/craftbook-templates/ni/nightly-fix-sweep/manifest.json +23 -0
- package/data/craftbook-templates/ni/nightly-fix-sweep/versions/1.0.0/craftbook.json +145 -0
- package/data/craftbook-templates/ni/nightly-fix-sweep/versions/1.0.0/test.json +121 -0
- package/data/craftbook-templates/pe/perf-audit/versions/1.1.0/craftbook.json +195 -0
- package/data/craftbook-templates/pe/perf-audit/versions/1.1.0/test.json +165 -0
- package/data/craftbook-templates/pe/perf-optimization/manifest.json +3 -3
- package/data/craftbook-templates/pe/perf-optimization/versions/2.0.0/craftbook.json +511 -0
- package/data/craftbook-templates/pe/perf-optimization/versions/2.0.0/test.json +236 -0
- package/data/craftbook-templates/qa/qa/manifest.json +3 -1
- package/data/craftbook-templates/re/refactor-module/manifest.json +2 -2
- package/data/craftbook-templates/re/refactor-module/versions/1.0.4/craftbook.json +150 -0
- package/data/craftbook-templates/re/refactor-module/versions/1.0.4/test.json +95 -0
- package/data/craftbook-templates/re/refactor-module/versions/2.0.0/craftbook.json +509 -0
- package/data/craftbook-templates/re/refactor-module/versions/2.0.0/test.json +242 -0
- package/data/craftbook-templates/re/release-notes/manifest.json +5 -1
- package/data/craftbook-templates/re/release-notes/versions/1.0.3/craftbook.json +220 -0
- package/data/craftbook-templates/re/release-notes/versions/1.0.3/test.json +114 -0
- package/data/craftbook-templates/re/release-pipeline-ci/manifest.json +5 -1
- package/data/craftbook-templates/re/release-readiness-review/versions/1.1.0/craftbook.json +192 -0
- package/data/craftbook-templates/re/release-readiness-review/versions/1.1.0/test.json +113 -0
- package/data/craftbook-templates/ro/root-cause-investigation/manifest.json +7 -1
- package/data/craftbook-templates/ro/root-cause-investigation/versions/2.0.5/craftbook.json +433 -0
- package/data/craftbook-templates/ro/root-cause-investigation/versions/2.0.5/test.json +157 -0
- package/data/craftbook-templates/sc/schema-migration/manifest.json +4 -4
- package/data/craftbook-templates/sc/schema-migration/versions/2.0.0/craftbook.json +459 -0
- package/data/craftbook-templates/sc/schema-migration/versions/2.0.0/test.json +226 -0
- package/data/craftbook-templates/te/test-coverage-review/versions/1.2.0/craftbook.json +195 -0
- package/data/craftbook-templates/te/test-coverage-review/versions/1.2.0/test.json +116 -0
- package/data/craftbook-templates/te/test-suite-backfill/manifest.json +1 -2
- package/data/craftbook-templates/te/test-suite-backfill/versions/2.0.0/craftbook.json +428 -0
- package/data/craftbook-templates/te/test-suite-backfill/versions/2.0.0/test.json +198 -0
- package/data/craftbook-templates/ty/type-safety-pass/manifest.json +3 -3
- package/data/craftbook-templates/ty/type-safety-pass/versions/2.0.0/craftbook.json +428 -0
- package/data/craftbook-templates/ty/type-safety-pass/versions/2.0.0/test.json +222 -0
- package/data/craftbook-templates/ux/ux-update/art.json +12 -0
- package/data/craftbook-templates/ux/ux-update/logo.webp +0 -0
- package/data/craftbook-templates/ux/ux-update/manifest.json +22 -0
- package/data/craftbook-templates/ux/ux-update/versions/1.0.0/craftbook.json +439 -0
- package/data/craftbook-templates/ux/ux-update/versions/1.0.0/test.json +207 -0
- package/data/craftbook-templates/ve/version-bump/versions/1.1.0/craftbook.json +206 -0
- package/data/craftbook-templates/ve/version-bump/versions/1.1.0/test.json +95 -0
- package/data/gezel-templates/bo/boekwachter/versions/1.1.0/about.md +29 -0
- package/data/gezel-templates/bo/boekwachter/versions/1.1.0/manifest.json +16 -0
- package/data/gezel-templates/bu/builder/versions/1.5.0/about.md +34 -0
- package/data/gezel-templates/bu/builder/versions/1.5.0/manifest.json +16 -0
- package/data/gezel-templates/de/developer/versions/1.5.0/about.md +34 -0
- package/data/gezel-templates/de/developer/versions/1.5.0/manifest.json +21 -0
- package/data/gezel-templates/index.json +1 -1
- package/data/gezel-templates/re/reviewer/versions/1.4.0/about.md +49 -0
- package/data/gezel-templates/re/reviewer/versions/1.4.0/manifest.json +21 -0
- package/data/project-types/index.json +1 -1
- package/data/project-types/so/software-project/manifest.json +20 -0
- package/data/project-types/so/software-project/versions/1.0.0/about.md +3 -0
- package/data/project-types/so/software-project/versions/1.0.0/manifest.json +41 -0
- package/data/project-types/so/software-project/versions/1.0.0/mission.md +4 -0
- package/package.json +1 -1
- package/schemas/craftbook-doc.schema.json +248 -0
- package/schemas/craftbook-template-version.schema.json +248 -0
- package/schemas/craftbook-test.schema.json +200 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"title": "Repo-wide rename sweep with reconciled counts",
|
|
4
|
+
"objective": "The craftbook drives a complete mechanical rename of fetchUserData to loadUser across a small repo whose sites include a re-export and a template-literal log string, with a changelog legitimately excluded as history - verified mechanically by a residual scan, behavior probes on every site, and a green suite.",
|
|
5
|
+
"tags": [
|
|
6
|
+
"code",
|
|
7
|
+
"codemod",
|
|
8
|
+
"rename",
|
|
9
|
+
"tactical-fleet"
|
|
10
|
+
],
|
|
11
|
+
"prompt": "Use the Codemod Sweep craftbook for this: rename fetchUserData to loadUser across the whole repo - the export, the re-export, every import and call site, and log strings that mention the old name. CHANGELOG.md is history and keeps the old name. The brief is in source/rename-brief.md. No behavior change.",
|
|
12
|
+
"setup": {
|
|
13
|
+
"projectName": "Profile Cards",
|
|
14
|
+
"about": "A tiny profile-rendering module with an in-memory user store. Tests run with `npm run test` (node --test).",
|
|
15
|
+
"files": [
|
|
16
|
+
{
|
|
17
|
+
"path": "package.json",
|
|
18
|
+
"content": "{\n \"name\": \"profile-cards\",\n \"private\": true,\n \"version\": \"1.0.0\",\n \"type\": \"module\",\n \"scripts\": {\n \"test\": \"node --test\"\n }\n}\n"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"path": "src/api.js",
|
|
22
|
+
"content": "const USERS = new Map([\n [1, { id: 1, name: 'Ada' }],\n [2, { id: 2, name: 'Grace' }],\n]);\n\nexport function fetchUserData(id) {\n const user = USERS.get(id);\n if (!user) throw new Error(`no user ${id}`);\n return { ...user };\n}\n"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"path": "src/index.js",
|
|
26
|
+
"content": "export { fetchUserData } from './api.js';\n"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"path": "src/log.js",
|
|
30
|
+
"content": "export const lines = [];\n\nexport function logLine(line) {\n lines.push(line);\n}\n"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"path": "src/profile.js",
|
|
34
|
+
"content": "import { fetchUserData } from './api.js';\nimport { logLine } from './log.js';\n\nexport function profileSummary(id) {\n const user = fetchUserData(id);\n logLine(`fetchUserData resolved user ${user.id}`);\n return `${user.name} (#${user.id})`;\n}\n"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"path": "tests/profile.test.mjs",
|
|
38
|
+
"content": "import assert from 'node:assert/strict';\nimport { test } from 'node:test';\nimport { fetchUserData } from '../src/index.js';\nimport { lines } from '../src/log.js';\nimport { profileSummary } from '../src/profile.js';\n\ntest('profileSummary renders the user line', () => {\n assert.equal(profileSummary(1), 'Ada (#1)');\n});\n\ntest('profileSummary logs the lookup', () => {\n profileSummary(2);\n assert.ok(lines.some((line) => line.includes('resolved user 2')));\n});\n\ntest('the re-export serves the same function', () => {\n assert.equal(fetchUserData(1).name, 'Ada');\n});\n"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"path": "CHANGELOG.md",
|
|
42
|
+
"content": "# Changelog\n\n## 1.2.0\n\n- fetchUserData now copies the record before returning it, so callers can\n mutate the result safely.\n\n## 1.0.0\n\n- Initial release with fetchUserData and the profile summary renderer.\n"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"path": "source/rename-brief.md",
|
|
46
|
+
"content": "# Rename brief: fetchUserData -> loadUser\n\nThe function does not fetch anything remote any more, so the name misleads.\nRename `fetchUserData` to `loadUser` everywhere it appears: the export, the\nre-export, every import and call site, and log strings that mention the old\nname - the log lines should follow the rename too.\n\nDo not rewrite history: `CHANGELOG.md` keeps the old name, because it records\nwhat past releases were actually called.\n\nNo behavior change: same records returned, same summary strings, same number\nof log lines.\n"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"path": "tests/verify-sweep.mjs",
|
|
50
|
+
"surface": "harness",
|
|
51
|
+
"content": "import assert from 'node:assert/strict';\nimport { execFileSync } from 'node:child_process';\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nconst root = process.cwd();\n\n// 1) Residual scan: zero mentions of the old name outside the excluded\n// history (CHANGELOG.md), the briefing material (source/), and\n// harness-owned files.\nconst SKIP_FILES = new Set(['CHANGELOG.md', 'task-notes.md', 'task-graph.md', 'tests/verify-sweep.mjs']);\nconst SKIP_DIRS = new Set(['node_modules', 'source']);\nconst hits = [];\nfunction scan(dir) {\n for (const entry of readdirSync(dir)) {\n if (entry.startsWith('.')) continue;\n const full = join(dir, entry);\n const rel = relative(root, full).split('\\\\').join('/');\n const stat = statSync(full);\n if (stat.isDirectory()) {\n if (SKIP_DIRS.has(entry)) continue;\n scan(full);\n continue;\n }\n if (SKIP_FILES.has(rel)) continue;\n if (!/\\.(js|mjs|cjs|json|md|txt)$/.test(entry)) continue;\n if (/\\bfetchUserData\\b/.test(readFileSync(full, 'utf8'))) hits.push(rel);\n }\n}\nscan(root);\nassert.deepEqual(hits, [], `the old name survives outside the exclusions in: ${hits.join(', ')}`);\nconsole.log('CODEMOD_ORACLE residual scan clean');\n\n// 2) Every site behaves under the new name, including the tricky ones.\nconst api = await import(pathToFileURL(join(root, 'src/api.js')).href);\nassert.equal(typeof api.loadUser, 'function', 'src/api.js must export loadUser');\nassert.equal(api.fetchUserData, undefined, 'src/api.js still exports the old name');\nconst index = await import(pathToFileURL(join(root, 'src/index.js')).href);\nassert.equal(typeof index.loadUser, 'function', 'src/index.js must re-export loadUser');\nassert.equal(index.fetchUserData, undefined, 'src/index.js still re-exports the old name');\nassert.equal(index.loadUser(1).name, 'Ada', 'the re-exported loadUser must return the same records');\nconst { profileSummary } = await import(pathToFileURL(join(root, 'src/profile.js')).href);\nconst { lines } = await import(pathToFileURL(join(root, 'src/log.js')).href);\nassert.equal(profileSummary(1), 'Ada (#1)', 'profileSummary behavior must be unchanged');\nassert.ok(\n lines.some((line) => line.includes('loadUser resolved user 1')),\n 'the log string must follow the rename',\n);\nassert.ok(\n !lines.some((line) => line.includes('fetchUserData')),\n 'a log string still mentions the old name',\n);\nconsole.log('CODEMOD_ORACLE behavior ok');\n\n// 3) History kept: the excluded changelog still records the old name.\nassert.ok(\n /\\bfetchUserData\\b/.test(readFileSync(join(root, 'CHANGELOG.md'), 'utf8')),\n 'CHANGELOG.md must keep the historical name',\n);\nconsole.log('CODEMOD_ORACLE history kept');\n\n// 4) The suite is green after the sweep, and the seeded test file survives.\nreadFileSync(join(root, 'tests/profile.test.mjs'));\nfunction runSuite(cwd) {\n try {\n execFileSync(process.execPath, ['--test'], { cwd, stdio: 'pipe', timeout: 30000 });\n return 0;\n } catch (err) {\n return typeof err.status === 'number' ? err.status : 1;\n }\n}\nassert.equal(runSuite(root), 0, 'the suite must be green after the sweep');\nconsole.log('CODEMOD_ORACLE suite green');\nconsole.log('CODEMOD_ORACLE done');\n"
|
|
52
|
+
}
|
|
53
|
+
],
|
|
54
|
+
"craftbookParams": {
|
|
55
|
+
"workPath": "tasks/eval",
|
|
56
|
+
"scope": "Rename fetchUserData to loadUser everywhere, including log strings that mention it; CHANGELOG.md keeps the historical name; no behavior change. See source/rename-brief.md."
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"success": {
|
|
60
|
+
"summary": "Zero references to the old name remain outside the excluded changelog and brief, every site (including the re-export and the log string) behaves under the new name, the suite is green, and every fleet artifact exists with counts that reconcile.",
|
|
61
|
+
"deliverables": [
|
|
62
|
+
{
|
|
63
|
+
"path": "tasks/eval/sites.md",
|
|
64
|
+
"kind": "markdown-notes",
|
|
65
|
+
"artifact": true,
|
|
66
|
+
"minBytes": 500,
|
|
67
|
+
"checks": [
|
|
68
|
+
{
|
|
69
|
+
"kind": "contains",
|
|
70
|
+
"file": "tasks/eval/sites.md",
|
|
71
|
+
"pattern": "^##\\s+Pattern[\\s\\S]*^##\\s+Sites found[\\s\\S]*^##\\s+Exclusions",
|
|
72
|
+
"flags": "im",
|
|
73
|
+
"label": "sites sections in order"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"kind": "contains",
|
|
77
|
+
"file": "tasks/eval/sites.md",
|
|
78
|
+
"pattern": "src/index\\.js",
|
|
79
|
+
"label": "found the re-export site"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"kind": "citationsResolve",
|
|
83
|
+
"file": "tasks/eval/sites.md",
|
|
84
|
+
"minCitations": 2,
|
|
85
|
+
"artifact": true
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"path": "tasks/eval/change-notes.md",
|
|
91
|
+
"kind": "markdown-notes",
|
|
92
|
+
"artifact": true,
|
|
93
|
+
"minBytes": 500,
|
|
94
|
+
"checks": [
|
|
95
|
+
{
|
|
96
|
+
"kind": "contains",
|
|
97
|
+
"file": "tasks/eval/change-notes.md",
|
|
98
|
+
"pattern": "^##\\s+Sites changed[\\s\\S]*^##\\s+Files touched[\\s\\S]*^##\\s+Invariants held",
|
|
99
|
+
"flags": "im",
|
|
100
|
+
"label": "change-notes sections in order"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"kind": "citationsResolve",
|
|
104
|
+
"file": "tasks/eval/change-notes.md",
|
|
105
|
+
"minCitations": 2,
|
|
106
|
+
"artifact": true
|
|
107
|
+
}
|
|
108
|
+
]
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"path": "tasks/eval/verification.md",
|
|
112
|
+
"kind": "markdown-notes",
|
|
113
|
+
"artifact": true,
|
|
114
|
+
"minBytes": 450,
|
|
115
|
+
"checks": [
|
|
116
|
+
{
|
|
117
|
+
"kind": "contains",
|
|
118
|
+
"file": "tasks/eval/verification.md",
|
|
119
|
+
"pattern": "^##\\s+Residual scan[\\s\\S]*^##\\s+Counts reconciled[\\s\\S]*^##\\s+Suite[\\s\\S]*^##\\s+Result",
|
|
120
|
+
"flags": "im",
|
|
121
|
+
"label": "verification sections in order"
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"path": "tasks/eval/review.md",
|
|
127
|
+
"kind": "markdown-report",
|
|
128
|
+
"artifact": true,
|
|
129
|
+
"minBytes": 400,
|
|
130
|
+
"checks": [
|
|
131
|
+
{
|
|
132
|
+
"kind": "contains",
|
|
133
|
+
"file": "tasks/eval/review.md",
|
|
134
|
+
"pattern": "Verdict:\\s*(?:PASS|REVISE)",
|
|
135
|
+
"flags": "i",
|
|
136
|
+
"label": "explicit reviewer verdict"
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
}
|
|
140
|
+
],
|
|
141
|
+
"checks": [
|
|
142
|
+
{
|
|
143
|
+
"kind": "notContains",
|
|
144
|
+
"file": "src/api.js",
|
|
145
|
+
"pattern": "\\bfetchUserData\\b",
|
|
146
|
+
"label": "the old name is gone from the definition site"
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"kind": "notContains",
|
|
150
|
+
"file": "src/index.js",
|
|
151
|
+
"pattern": "\\bfetchUserData\\b",
|
|
152
|
+
"label": "the old name is gone from the re-export site"
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"kind": "notContains",
|
|
156
|
+
"file": "src/profile.js",
|
|
157
|
+
"pattern": "\\bfetchUserData\\b",
|
|
158
|
+
"label": "the old name is gone from the call site and its log string"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"kind": "notContains",
|
|
162
|
+
"file": "tests/profile.test.mjs",
|
|
163
|
+
"pattern": "\\bfetchUserData\\b",
|
|
164
|
+
"label": "the old name is gone from the test call sites"
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"kind": "contains",
|
|
168
|
+
"file": "CHANGELOG.md",
|
|
169
|
+
"pattern": "\\bfetchUserData\\b",
|
|
170
|
+
"label": "the excluded changelog keeps the historical name"
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"kind": "sourceParses",
|
|
174
|
+
"file": "src/api.js"
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
"kind": "sourceParses",
|
|
178
|
+
"file": "src/profile.js"
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"kind": "nodeRuns",
|
|
182
|
+
"file": "tests/profile.test.mjs"
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"kind": "nodeScriptPasses",
|
|
186
|
+
"script": "tests/verify-sweep.mjs",
|
|
187
|
+
"timeoutMs": 60000,
|
|
188
|
+
"requiredOutput": [
|
|
189
|
+
{
|
|
190
|
+
"pattern": "CODEMOD_ORACLE residual scan clean",
|
|
191
|
+
"label": "zero un-excluded sites remain"
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"pattern": "CODEMOD_ORACLE behavior ok",
|
|
195
|
+
"label": "every site behaves under the new name"
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
"pattern": "CODEMOD_ORACLE suite green",
|
|
199
|
+
"label": "suite green after the sweep"
|
|
200
|
+
}
|
|
201
|
+
]
|
|
202
|
+
}
|
|
203
|
+
],
|
|
204
|
+
"taskNotes": {
|
|
205
|
+
"minBytes": 120,
|
|
206
|
+
"checks": [
|
|
207
|
+
{
|
|
208
|
+
"kind": "contains",
|
|
209
|
+
"file": "task-notes.md",
|
|
210
|
+
"pattern": "\\bDONE\\b[\\s\\S]*(npm\\s+run\\s+test|node\\s+--test)",
|
|
211
|
+
"flags": "i",
|
|
212
|
+
"label": "DONE note names the real test command"
|
|
213
|
+
}
|
|
214
|
+
]
|
|
215
|
+
},
|
|
216
|
+
"taskGraph": {
|
|
217
|
+
"requireCraftbookTask": true,
|
|
218
|
+
"requireTerminalStep": true
|
|
219
|
+
},
|
|
220
|
+
"unchangedFixtures": [
|
|
221
|
+
"CHANGELOG.md",
|
|
222
|
+
"source/rename-brief.md",
|
|
223
|
+
"package.json",
|
|
224
|
+
"src/log.js"
|
|
225
|
+
]
|
|
226
|
+
},
|
|
227
|
+
"rubric": {
|
|
228
|
+
"artifact": {
|
|
229
|
+
"path": "tasks/eval/verification.md",
|
|
230
|
+
"kind": "markdown"
|
|
231
|
+
},
|
|
232
|
+
"axes": [
|
|
233
|
+
{
|
|
234
|
+
"name": "Enumeration completeness",
|
|
235
|
+
"description": "Every site was found by real searches before any edit - the definition, the re-export, the imports and call sites, and the log string - with the changelog excluded for a stated reason rather than missed."
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"name": "Invariant discipline",
|
|
239
|
+
"description": "The change stayed mechanical: nothing changed beyond the declared rename, the excluded files are untouched, and behavior is identical."
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
"name": "Reconciled verification",
|
|
243
|
+
"description": "The residual re-scan is quoted with its result, the found/changed/excluded counts add up exactly, and the suite run backing the green claim is real."
|
|
244
|
+
}
|
|
245
|
+
]
|
|
246
|
+
},
|
|
247
|
+
"qualityFocus": [
|
|
248
|
+
"sweep completeness",
|
|
249
|
+
"count reconciliation",
|
|
250
|
+
"behavior invariants"
|
|
251
|
+
]
|
|
252
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"title": "Vendored dependency upgrade with staged receipts",
|
|
4
|
+
"objective": "The craftbook drives a staged upgrade of a vendored library across a breaking major: a recorded green suite before any change, the v2 API adopted at both real call sites with behavior preserved against the v1 reference, an honest stage record, and an enforced review - all verified mechanically, including a resolved-module check proving the call sites genuinely run v2.",
|
|
5
|
+
"tags": [
|
|
6
|
+
"code",
|
|
7
|
+
"dependency-upgrade",
|
|
8
|
+
"tactical-fleet"
|
|
9
|
+
],
|
|
10
|
+
"prompt": "Use the Upgrade a Dependency craftbook for this: upgrade our vendored markdownlite library from 1.4.2 to the staged 2.0.0 copy. The vendoring convention and the v2 changelog are in VENDORING.md, and the request is in source/upgrade-request.md. Rendering behavior must not change - adapt the call sites to the new API rather than accepting the new defaults.",
|
|
11
|
+
"setup": {
|
|
12
|
+
"projectName": "Relay Notes",
|
|
13
|
+
"about": "A tiny note-rendering module for a team relay tool. Dependencies are vendored under lib/vendored/ per VENDORING.md. Tests run with `npm run test` (node --test).",
|
|
14
|
+
"files": [
|
|
15
|
+
{
|
|
16
|
+
"path": "package.json",
|
|
17
|
+
"content": "{\n \"name\": \"relay-notes\",\n \"private\": true,\n \"version\": \"1.0.0\",\n \"type\": \"module\",\n \"scripts\": {\n \"test\": \"node --test\"\n }\n}\n"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"path": "lib/vendored/markdownlite.js",
|
|
21
|
+
"content": "// markdownlite 1.4.2 (vendored - see VENDORING.md)\nexport function parse(text) {\n const lines = String(text).split(/\\r?\\n/);\n const out = [];\n for (const line of lines) {\n const t = line.trim();\n if (t === '') continue;\n const h = /^(#{1,3})\\s+(.*)$/.exec(t);\n if (h) {\n out.push(`<h${h[1].length}>${inline(h[2])}</h${h[1].length}>`);\n } else {\n out.push(`<p>${inline(t)}</p>`);\n }\n }\n return out.join('\\n');\n}\n\nfunction inline(text) {\n return text.replace(/\\*([^*]+)\\*/g, '<em>$1</em>');\n}\n"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"path": "lib/vendored/v2/markdownlite.js",
|
|
25
|
+
"content": "// markdownlite 2.0.0 (vendored staging copy - see VENDORING.md)\nexport function parseDoc(text, options = {}) {\n const wrapParagraphs = options.wrapParagraphs ?? false;\n const lines = String(text).split(/\\r?\\n/);\n const out = [];\n for (const line of lines) {\n const t = line.trim();\n if (t === '') continue;\n const h = /^(#{1,3})\\s+(.*)$/.exec(t);\n if (h) {\n out.push(`<h${h[1].length}>${inline(h[2])}</h${h[1].length}>`);\n } else {\n out.push(wrapParagraphs ? `<p>${inline(t)}</p>` : inline(t));\n }\n }\n return out.join('\\n');\n}\n\nfunction inline(text) {\n return text.replace(/\\*([^*]+)\\*/g, '<em>$1</em>');\n}\n"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"path": "src/render-note.js",
|
|
29
|
+
"content": "import { parse } from '../lib/vendored/markdownlite.js';\n\nexport function renderNote(note) {\n return `<h2>${note.title}</h2>\\n${parse(note.body)}`;\n}\n"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"path": "src/render-digest.js",
|
|
33
|
+
"content": "import { parse } from '../lib/vendored/markdownlite.js';\n\nexport function renderDigest(notes) {\n return notes\n .map((note) => `<section>\\n<h2>${note.title}</h2>\\n${parse(note.body)}\\n</section>`)\n .join('\\n');\n}\n"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"path": "tests/render-note.test.mjs",
|
|
37
|
+
"content": "import assert from 'node:assert/strict';\nimport { test } from 'node:test';\nimport { renderNote } from '../src/render-note.js';\n\ntest('renders the body as wrapped paragraphs', () => {\n assert.equal(\n renderNote({ title: 'Standup', body: 'we shipped the *fast* path' }),\n '<h2>Standup</h2>\\n<p>we shipped the <em>fast</em> path</p>',\n );\n});\n\ntest('renders headings inside the body', () => {\n assert.equal(\n renderNote({ title: 'Plan', body: '# Goals\\nship it' }),\n '<h2>Plan</h2>\\n<h1>Goals</h1>\\n<p>ship it</p>',\n );\n});\n"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"path": "tests/render-digest.test.mjs",
|
|
41
|
+
"content": "import assert from 'node:assert/strict';\nimport { test } from 'node:test';\nimport { renderDigest } from '../src/render-digest.js';\n\ntest('joins every note as a wrapped section', () => {\n const html = renderDigest([\n { title: 'One', body: 'first' },\n { title: 'Two', body: 'second line' },\n ]);\n assert.equal(\n html,\n '<section>\\n<h2>One</h2>\\n<p>first</p>\\n</section>\\n<section>\\n<h2>Two</h2>\\n<p>second line</p>\\n</section>',\n );\n});\n"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"path": "VENDORING.md",
|
|
45
|
+
"content": "# Vendoring convention\n\nThis project vendors small dependencies directly under `lib/vendored/` instead\nof installing them from a registry. Each vendored library is a single file named\nafter the package. Upgrades arrive as a staged copy in a version subfolder\n(for example `lib/vendored/v2/`) so the switch is an explicit, reviewable\nchange: move the staged copy into place (or point the imports at it), adapt the\ncall sites, and remove the staging folder when the switch is complete.\n\n## markdownlite\n\nCurrent vendored version: 1.4.2 at `lib/vendored/markdownlite.js`.\nStaged upgrade: 2.0.0 at `lib/vendored/v2/markdownlite.js`.\n\n### markdownlite 2.0.0 changelog\n\n- BREAKING: `parse(text)` is renamed to `parseDoc(text, options)`.\n- BREAKING: plain lines are no longer wrapped in `<p>` by default. Paragraph\n wrapping is now opt-in: pass `{ wrapParagraphs: true }` to keep the 1.x\n output.\n- Heading and emphasis handling are unchanged.\n"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"path": "source/upgrade-request.md",
|
|
49
|
+
"content": "# Upgrade request\n\nPlease move us from vendored markdownlite 1.4.2 to the staged 2.0.0 copy.\nThe v2 changelog is in VENDORING.md. Rendering behavior must not change:\nnotes and digests must produce exactly the same HTML as today, so adapt the\ncall sites to the new API rather than accepting the new defaults.\n"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"path": "tests/verify-upgrade.mjs",
|
|
53
|
+
"surface": "harness",
|
|
54
|
+
"content": "import assert from 'node:assert/strict';\nimport { execFileSync } from 'node:child_process';\nimport { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nconst root = process.cwd();\n\n// 1) Both call sites moved off the removed v1 API and resolve to a v2 module.\n// Accepted either way: v2 copied into place at lib/vendored/markdownlite.js,\n// or imports repointed at the staged v2 file.\nconst callSites = ['src/render-note.js', 'src/render-digest.js'];\nfor (const file of callSites) {\n const source = readFileSync(join(root, file), 'utf8');\n assert.ok(/\\bparseDoc\\s*\\(/.test(source), `${file} must call the v2 parseDoc API`);\n assert.ok(!/\\bparse\\s*\\(/.test(source), `${file} still calls the removed v1 parse API`);\n const spec = /import\\s*\\{[^}]*\\}\\s*from\\s*['\"]([^'\"]*markdownlite[^'\"]*)['\"]/.exec(source);\n assert.ok(spec, `${file} must import the vendored markdownlite module`);\n const mod = await import(new URL(spec[1], pathToFileURL(join(root, file))).href);\n assert.equal(typeof mod.parseDoc, 'function', `${file} must resolve to markdownlite v2 (parseDoc export)`);\n assert.equal(mod.parse, undefined, `${file} resolves to a module that still exports the removed v1 parse API`);\n}\nconsole.log('DEPUPGRADE_ORACLE call sites adapted');\n\n// 2) Behavior is unchanged against the v1 reference output.\nconst { renderNote } = await import(pathToFileURL(join(root, 'src/render-note.js')).href);\nconst { renderDigest } = await import(pathToFileURL(join(root, 'src/render-digest.js')).href);\nassert.equal(\n renderNote({ title: 'Standup', body: 'we shipped the *fast* path' }),\n '<h2>Standup</h2>\\n<p>we shipped the <em>fast</em> path</p>',\n 'renderNote must keep wrapping paragraphs after the upgrade',\n);\nassert.equal(\n renderNote({ title: 'Plan', body: '# Goals\\nship it' }),\n '<h2>Plan</h2>\\n<h1>Goals</h1>\\n<p>ship it</p>',\n 'renderNote must keep heading handling after the upgrade',\n);\nassert.equal(\n renderDigest([\n { title: 'One', body: 'first' },\n { title: 'Two', body: 'second line' },\n ]),\n '<section>\\n<h2>One</h2>\\n<p>first</p>\\n</section>\\n<section>\\n<h2>Two</h2>\\n<p>second line</p>\\n</section>',\n 'renderDigest must keep its exact output after the upgrade',\n);\nconsole.log('DEPUPGRADE_ORACLE behavior ok');\n\n// 3) The suite is green on the upgraded tree, and the seeded tests survive.\nreadFileSync(join(root, 'tests/render-note.test.mjs'));\nreadFileSync(join(root, 'tests/render-digest.test.mjs'));\nfunction runSuite(cwd) {\n try {\n execFileSync(process.execPath, ['--test'], { cwd, stdio: 'pipe', timeout: 30000 });\n return 0;\n } catch (err) {\n return typeof err.status === 'number' ? err.status : 1;\n }\n}\nassert.equal(runSuite(root), 0, 'the suite must be green on the upgraded tree');\nconsole.log('DEPUPGRADE_ORACLE suite green');\nconsole.log('DEPUPGRADE_ORACLE done');\n"
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
"craftbookParams": {
|
|
58
|
+
"workPath": "tasks/eval",
|
|
59
|
+
"scope": "Upgrade the vendored markdownlite from 1.4.2 to the staged 2.0.0 copy per VENDORING.md; rendering behavior must not change."
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"success": {
|
|
63
|
+
"summary": "The vendored library runs at v2 through both call sites (either moved into place or repointed), every adaptation preserves the exact v1 rendering behavior, the suite is green, and every fleet artifact exists with honest receipts.",
|
|
64
|
+
"deliverables": [
|
|
65
|
+
{
|
|
66
|
+
"path": "tasks/eval/survey.md",
|
|
67
|
+
"kind": "markdown-notes",
|
|
68
|
+
"artifact": true,
|
|
69
|
+
"minBytes": 600,
|
|
70
|
+
"checks": [
|
|
71
|
+
{
|
|
72
|
+
"kind": "contains",
|
|
73
|
+
"file": "tasks/eval/survey.md",
|
|
74
|
+
"pattern": "^##\\s+Current state[\\s\\S]*^##\\s+Candidates[\\s\\S]*^##\\s+Breaking-change notes[\\s\\S]*^##\\s+Stage plan",
|
|
75
|
+
"flags": "im",
|
|
76
|
+
"label": "survey sections in order"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"kind": "contains",
|
|
80
|
+
"file": "tasks/eval/survey.md",
|
|
81
|
+
"pattern": "parseDoc",
|
|
82
|
+
"label": "names the real v2 API change from the local changelog"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"kind": "citationsResolve",
|
|
86
|
+
"file": "tasks/eval/survey.md",
|
|
87
|
+
"minCitations": 2,
|
|
88
|
+
"artifact": true
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"path": "tasks/eval/change-notes.md",
|
|
94
|
+
"kind": "markdown-notes",
|
|
95
|
+
"artifact": true,
|
|
96
|
+
"minBytes": 700,
|
|
97
|
+
"checks": [
|
|
98
|
+
{
|
|
99
|
+
"kind": "contains",
|
|
100
|
+
"file": "tasks/eval/change-notes.md",
|
|
101
|
+
"pattern": "^##\\s+Stages executed[\\s\\S]*^##\\s+Files touched[\\s\\S]*^##\\s+Adaptations[\\s\\S]*^##\\s+Reverted stages",
|
|
102
|
+
"flags": "im",
|
|
103
|
+
"label": "change-notes sections in order"
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"kind": "citationsResolve",
|
|
107
|
+
"file": "tasks/eval/change-notes.md",
|
|
108
|
+
"minCitations": 2,
|
|
109
|
+
"artifact": true
|
|
110
|
+
}
|
|
111
|
+
]
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"path": "tasks/eval/verification.md",
|
|
115
|
+
"kind": "markdown-notes",
|
|
116
|
+
"artifact": true,
|
|
117
|
+
"minBytes": 450,
|
|
118
|
+
"checks": [
|
|
119
|
+
{
|
|
120
|
+
"kind": "contains",
|
|
121
|
+
"file": "tasks/eval/verification.md",
|
|
122
|
+
"pattern": "^##\\s+Suite[\\s\\S]*^##\\s+Adaptations verified[\\s\\S]*^##\\s+Rollback[\\s\\S]*^##\\s+Result",
|
|
123
|
+
"flags": "im",
|
|
124
|
+
"label": "verification sections in order"
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"path": "tasks/eval/review.md",
|
|
130
|
+
"kind": "markdown-report",
|
|
131
|
+
"artifact": true,
|
|
132
|
+
"minBytes": 400,
|
|
133
|
+
"checks": [
|
|
134
|
+
{
|
|
135
|
+
"kind": "contains",
|
|
136
|
+
"file": "tasks/eval/review.md",
|
|
137
|
+
"pattern": "Verdict:\\s*(?:PASS|REVISE)",
|
|
138
|
+
"flags": "i",
|
|
139
|
+
"label": "explicit reviewer verdict"
|
|
140
|
+
}
|
|
141
|
+
]
|
|
142
|
+
}
|
|
143
|
+
],
|
|
144
|
+
"checks": [
|
|
145
|
+
{
|
|
146
|
+
"kind": "notContains",
|
|
147
|
+
"file": "src/render-note.js",
|
|
148
|
+
"pattern": "\\bparse\\s*\\(|import\\s*\\{[^}]*\\bparse\\b[^}]*\\}",
|
|
149
|
+
"label": "the removed v1 parse API is gone from the note call site"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"kind": "notContains",
|
|
153
|
+
"file": "src/render-digest.js",
|
|
154
|
+
"pattern": "\\bparse\\s*\\(|import\\s*\\{[^}]*\\bparse\\b[^}]*\\}",
|
|
155
|
+
"label": "the removed v1 parse API is gone from the digest call site"
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"kind": "sourceParses",
|
|
159
|
+
"file": "src/render-note.js"
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"kind": "sourceParses",
|
|
163
|
+
"file": "src/render-digest.js"
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"kind": "nodeRuns",
|
|
167
|
+
"file": "tests/render-note.test.mjs"
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"kind": "nodeScriptPasses",
|
|
171
|
+
"script": "tests/verify-upgrade.mjs",
|
|
172
|
+
"timeoutMs": 60000,
|
|
173
|
+
"requiredOutput": [
|
|
174
|
+
{
|
|
175
|
+
"pattern": "DEPUPGRADE_ORACLE call sites adapted",
|
|
176
|
+
"label": "both call sites run the v2 API"
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"pattern": "DEPUPGRADE_ORACLE behavior ok",
|
|
180
|
+
"label": "rendering behavior preserved against the v1 reference"
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
"pattern": "DEPUPGRADE_ORACLE suite green",
|
|
184
|
+
"label": "suite green on the upgraded tree"
|
|
185
|
+
}
|
|
186
|
+
]
|
|
187
|
+
}
|
|
188
|
+
],
|
|
189
|
+
"taskNotes": {
|
|
190
|
+
"minBytes": 120,
|
|
191
|
+
"checks": [
|
|
192
|
+
{
|
|
193
|
+
"kind": "contains",
|
|
194
|
+
"file": "task-notes.md",
|
|
195
|
+
"pattern": "\\bDONE\\b[\\s\\S]*(npm\\s+run\\s+test|node\\s+--test)",
|
|
196
|
+
"flags": "i",
|
|
197
|
+
"label": "DONE note names the real test command"
|
|
198
|
+
}
|
|
199
|
+
]
|
|
200
|
+
},
|
|
201
|
+
"taskGraph": {
|
|
202
|
+
"requireCraftbookTask": true,
|
|
203
|
+
"requireTerminalStep": true
|
|
204
|
+
},
|
|
205
|
+
"unchangedFixtures": [
|
|
206
|
+
"source/upgrade-request.md",
|
|
207
|
+
"package.json"
|
|
208
|
+
]
|
|
209
|
+
},
|
|
210
|
+
"rubric": {
|
|
211
|
+
"artifact": {
|
|
212
|
+
"path": "tasks/eval/change-notes.md",
|
|
213
|
+
"kind": "markdown"
|
|
214
|
+
},
|
|
215
|
+
"axes": [
|
|
216
|
+
{
|
|
217
|
+
"name": "Staged discipline",
|
|
218
|
+
"description": "The work ran as ordered stages with the suite genuinely run before the first change and between stages, and the record distinguishes executed stages from reverted or deferred ones."
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
"name": "Local evidence honesty",
|
|
222
|
+
"description": "Breaking-change notes come from sources actually read in the repository (VENDORING.md, the staged v2 file), with nothing presented as a release note that was invented."
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"name": "Adaptation fidelity",
|
|
226
|
+
"description": "Call sites were adapted at their real locations to preserve exact rendering behavior under the v2 API, rather than accepting changed defaults or weakening tests."
|
|
227
|
+
}
|
|
228
|
+
]
|
|
229
|
+
},
|
|
230
|
+
"qualityFocus": [
|
|
231
|
+
"staged upgrades with receipts",
|
|
232
|
+
"local breaking-change evidence",
|
|
233
|
+
"honest reverts"
|
|
234
|
+
]
|
|
235
|
+
}
|