@bendyline/gilde 0.1.40 → 0.1.42
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/po/powerpoint-deck/versions/1.7.4/test.json +0 -1
- package/data/craftbook-templates/pu/pull-request-review/versions/1.8.0/craftbook.json +304 -0
- package/data/craftbook-templates/pu/pull-request-review/versions/1.8.0/test.json +144 -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,239 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"title": "Deflake an order-dependent test with receipts",
|
|
4
|
+
"objective": "The craftbook drives a real deflake of a seeded order-dependence flake: statistical reproduction with recorded failing runs, a mechanism-level diagnosis, cleanup at the level every test shares (never skipping or weakening the test), and a stability proof - verified mechanically, including a five-run consecutive-green oracle, a late-probe order-robustness check, and a mutant restoring the original leaking order.",
|
|
5
|
+
"tags": [
|
|
6
|
+
"code",
|
|
7
|
+
"flaky-test",
|
|
8
|
+
"tests",
|
|
9
|
+
"tactical-fleet"
|
|
10
|
+
],
|
|
11
|
+
"prompt": "Use the Fix a Flaky Test craftbook: our suite is red in CI but the failing test passes when people run it by itself, so it keeps getting waved through. The report is in source/flake-report.md. Find the nondeterminism, remove it for real, and prove the suite stays green.",
|
|
12
|
+
"setup": {
|
|
13
|
+
"projectName": "Flagship Flags",
|
|
14
|
+
"about": "A tiny feature-flags module and its test suite. Tests run with `npm run test` (node --test).",
|
|
15
|
+
"files": [
|
|
16
|
+
{
|
|
17
|
+
"path": "package.json",
|
|
18
|
+
"content": "{\n \"name\": \"flagship\",\n \"private\": true,\n \"version\": \"1.0.0\",\n \"type\": \"module\",\n \"scripts\": {\n \"test\": \"node --test\"\n }\n}\n",
|
|
19
|
+
"modelInput": false
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"path": "src/flags.js",
|
|
23
|
+
"content": "const flags = new Map();\n\nexport function enable(name) {\n flags.set(name, true);\n}\n\nexport function disable(name) {\n flags.delete(name);\n}\n\nexport function isEnabled(name) {\n return flags.get(name) === true;\n}\n\nexport function enabledCount() {\n return flags.size;\n}\n\nexport function resetFlags() {\n flags.clear();\n}\n"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"path": "tests/flags.test.mjs",
|
|
27
|
+
"content": "import assert from 'node:assert/strict';\nimport { test } from 'node:test';\nimport { enable, disable, isEnabled, enabledCount } from '../src/flags.js';\n\ntest('enable turns a flag on', () => {\n enable('beta-banner');\n assert.equal(isEnabled('beta-banner'), true);\n});\n\ntest('disable turns a flag off again', () => {\n enable('holiday-theme');\n disable('holiday-theme');\n assert.equal(isEnabled('holiday-theme'), false);\n});\n\ntest('unknown flags read as disabled', () => {\n assert.equal(isEnabled('dark-mode'), false);\n});\n\ntest('a fresh session starts with no flags enabled', () => {\n assert.equal(enabledCount(), 0);\n});\n"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"path": "source/flake-report.md",
|
|
31
|
+
"content": "# Flake report\n\nThe suite has been red in CI all week, and every developer who ran the failing test by itself saw it pass - so it kept getting waved through.\n\n npm run test\n not ok 4 - a fresh session starts with no flags enabled\n AssertionError: 1 !== 0\n\nRunning the full suite fails on that test consistently; running just that one test with `--test-name-pattern \"fresh session\"` is green every time. Nobody has touched `src/flags.js` in weeks.\n\nConstraints:\n\n- The pristine-session test guards a real invariant (feature sessions must start clean). Do not delete or weaken it.\n- The app depends on `src/flags.js` exactly as it is - fix the tests' hygiene, not the module's API.\n",
|
|
32
|
+
"modelInput": true
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"path": "tests/verify-deflake.mjs",
|
|
36
|
+
"surface": "harness",
|
|
37
|
+
"content": "import assert from 'node:assert/strict';\nimport { execFileSync } from 'node:child_process';\nimport { cpSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { enable, isEnabled, resetFlags, enabledCount } from '../src/flags.js';\n\nconst root = process.cwd();\nconst ORACLE_FILE = 'verify-deflake.mjs';\n\n// 1) The flags module still means what it meant.\nresetFlags();\nenable('oracle-probe');\nassert.equal(isEnabled('oracle-probe'), true, 'enable must still work');\nassert.equal(enabledCount(), 1, 'enabledCount must still count');\nresetFlags();\nassert.equal(enabledCount(), 0, 'resetFlags must still clear');\nconsole.log('DEFLAKE_ORACLE flags semantics ok');\n\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}\n\nfunction copyTree(dest) {\n rmSync(dest, { recursive: true, force: true });\n mkdirSync(dest, { recursive: true });\n cpSync(join(root, 'src'), join(dest, 'src'), { recursive: true });\n cpSync(join(root, 'tests'), join(dest, 'tests'), { recursive: true });\n rmSync(join(dest, 'tests', ORACLE_FILE), { force: true });\n cpSync(join(root, 'package.json'), join(dest, 'package.json'));\n return dest;\n}\n\n// 2) Five consecutive green runs of the real suite.\nfor (let run = 1; run <= 5; run += 1) {\n assert.equal(runSuite(root), 0, `full-suite run ${run} of 5 must be green`);\n}\nconsole.log('DEFLAKE_ORACLE stable 5x');\n\n// 3) The pristine-session assertion survives, unweakened and unskipped.\nconst testFiles = readdirSync(join(root, 'tests')).filter(\n (name) => name !== ORACLE_FILE && /\\.(mjs|cjs|js)$/.test(name),\n);\nconst combined = testFiles\n .map((name) => readFileSync(join(root, 'tests', name), 'utf8'))\n .join('\\n');\nassert.match(\n combined,\n /enabledCount\\s*\\(\\s*\\)\\s*(?:,\\s*0|===\\s*0)/,\n 'the pristine-session assertion (enabledCount() must be 0) has to survive',\n);\nassert.ok(\n !/\\.skip\\s*\\(|\\.todo\\s*\\(|\\.only\\s*\\(|\\{\\s*skip\\s*:|\\{\\s*todo\\s*:/.test(combined),\n 'no test may be skipped, stubbed as todo, or narrowed with only',\n);\nconsole.log('DEFLAKE_ORACLE assertion intact');\n\n// 4) Order robustness: tests appended at the END of the suite must inherit\n// the cleanup. The first probe enables a flag and never cleans up; the\n// second expects a pristine session anyway. Only hygiene that covers every\n// test (beforeEach/afterEach-style) passes both - a one-off reset inside\n// the seeded failing test, or a reorder, fails here. Aliased imports keep\n// the probe valid whatever the model did to the file's own imports.\nconst hostFile = testFiles.find((name) =>\n /enabledCount/.test(readFileSync(join(root, 'tests', name), 'utf8')),\n);\nassert.ok(hostFile, 'no test file references enabledCount');\nconst probeRoot = copyTree(join(root, '.oracle-probe'));\nconst probeTests =\n readFileSync(join(probeRoot, 'tests', hostFile), 'utf8') +\n \"\\n\\nimport { test as zzTest } from 'node:test';\\nimport zzAssert from 'node:assert/strict';\\nimport { enable as zzEnable, isEnabled as zzIsEnabled, enabledCount as zzEnabledCount } from '../src/flags.js';\\n\\nzzTest('zz probe enables a flag of its own', () => {\\n zzEnable('zz-probe-flag');\\n zzAssert.equal(zzIsEnabled('zz-probe-flag'), true);\\n});\\n\\nzzTest('zz probe still gets a pristine session', () => {\\n zzAssert.equal(zzEnabledCount(), 0);\\n});\\n\";\nwriteFileSync(join(probeRoot, 'tests', hostFile), probeTests);\nassert.equal(\n runSuite(probeRoot),\n 0,\n 'a test appended after the suite must still see a pristine session - cleanup has to cover every test, not only the seeded order',\n);\nconsole.log('DEFLAKE_ORACLE order robust');\n\n// 5) Mutant: restore the ORIGINAL leaking test file - the suite must fail\n// again, proving the seeded defect is still detectable and the green suite\n// comes from removed nondeterminism, not from a neutered module or dodge.\nconst ORIGINAL_TEST_FILE = `import assert from 'node:assert/strict';\nimport { test } from 'node:test';\nimport { enable, disable, isEnabled, enabledCount } from '../src/flags.js';\n\ntest('enable turns a flag on', () => {\n enable('beta-banner');\n assert.equal(isEnabled('beta-banner'), true);\n});\n\ntest('disable turns a flag off again', () => {\n enable('holiday-theme');\n disable('holiday-theme');\n assert.equal(isEnabled('holiday-theme'), false);\n});\n\ntest('unknown flags read as disabled', () => {\n assert.equal(isEnabled('dark-mode'), false);\n});\n\ntest('a fresh session starts with no flags enabled', () => {\n assert.equal(enabledCount(), 0);\n});\n`;\nconst mutantRoot = copyTree(join(root, '.oracle-mutant'));\nwriteFileSync(join(mutantRoot, 'tests', 'flags.test.mjs'), ORIGINAL_TEST_FILE);\nassert.notEqual(\n runSuite(mutantRoot),\n 0,\n 'restoring the original leaking order must make the suite fail again - the seeded defect stopped being detectable',\n);\nconsole.log('DEFLAKE_ORACLE mutant caught');\nconsole.log('DEFLAKE_ORACLE done');\n"
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
"craftbookParams": {
|
|
41
|
+
"workPath": "tasks/eval",
|
|
42
|
+
"scope": "The test 'a fresh session starts with no flags enabled' in tests/flags.test.mjs fails whenever the whole suite runs and passes by itself; see source/flake-report.md. Make the suite deterministic without weakening that test."
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"success": {
|
|
46
|
+
"summary": "The order-dependence mechanism is removed with hygiene that covers every test, the pristine-session assertion survives unweakened, five consecutive suite runs are green, a late-appended probe still sees a pristine session, and restoring the original test file makes the suite fail again.",
|
|
47
|
+
"deliverables": [
|
|
48
|
+
{
|
|
49
|
+
"path": "tasks/eval/flake-evidence.md",
|
|
50
|
+
"kind": "markdown-notes",
|
|
51
|
+
"artifact": true,
|
|
52
|
+
"minBytes": 500,
|
|
53
|
+
"checks": [
|
|
54
|
+
{
|
|
55
|
+
"kind": "contains",
|
|
56
|
+
"file": "tasks/eval/flake-evidence.md",
|
|
57
|
+
"pattern": "^##\\s+Symptom[\\s\\S]*^##\\s+Runs observed[\\s\\S]*^##\\s+Failure signature[\\s\\S]*^##\\s+Suspected class",
|
|
58
|
+
"flags": "im",
|
|
59
|
+
"label": "flake-evidence sections in order"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"kind": "citationsResolve",
|
|
63
|
+
"file": "tasks/eval/flake-evidence.md",
|
|
64
|
+
"minCitations": 2,
|
|
65
|
+
"artifact": true
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"path": "tasks/eval/diagnosis.md",
|
|
71
|
+
"kind": "markdown-notes",
|
|
72
|
+
"artifact": true,
|
|
73
|
+
"minBytes": 600,
|
|
74
|
+
"checks": [
|
|
75
|
+
{
|
|
76
|
+
"kind": "contains",
|
|
77
|
+
"file": "tasks/eval/diagnosis.md",
|
|
78
|
+
"pattern": "^##\\s+Mechanism[\\s\\S]*^##\\s+Experiment[\\s\\S]*^##\\s+Defect site[\\s\\S]*^##\\s+Siblings checked",
|
|
79
|
+
"flags": "im",
|
|
80
|
+
"label": "diagnosis sections in order"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"kind": "contains",
|
|
84
|
+
"file": "tasks/eval/diagnosis.md",
|
|
85
|
+
"pattern": "tests/flags\\.test\\.mjs|src/flags\\.js",
|
|
86
|
+
"label": "names the real site of the shared-state hazard"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"kind": "citationsResolve",
|
|
90
|
+
"file": "tasks/eval/diagnosis.md",
|
|
91
|
+
"minCitations": 2,
|
|
92
|
+
"artifact": true
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"path": "tasks/eval/fix-notes.md",
|
|
98
|
+
"kind": "markdown-notes",
|
|
99
|
+
"artifact": true,
|
|
100
|
+
"minBytes": 700,
|
|
101
|
+
"checks": [
|
|
102
|
+
{
|
|
103
|
+
"kind": "contains",
|
|
104
|
+
"file": "tasks/eval/fix-notes.md",
|
|
105
|
+
"pattern": "^##\\s+Problem[\\s\\S]*^##\\s+Change[\\s\\S]*^##\\s+Files touched[\\s\\S]*^##\\s+Regression coverage[\\s\\S]*^##\\s+Risk[\\s\\S]*^##\\s+How to verify",
|
|
106
|
+
"flags": "im",
|
|
107
|
+
"label": "fix-notes sections in order"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"kind": "citationsResolve",
|
|
111
|
+
"file": "tasks/eval/fix-notes.md",
|
|
112
|
+
"minCitations": 2,
|
|
113
|
+
"artifact": true
|
|
114
|
+
}
|
|
115
|
+
]
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"path": "tasks/eval/validation.md",
|
|
119
|
+
"kind": "markdown-notes",
|
|
120
|
+
"artifact": true,
|
|
121
|
+
"minBytes": 300,
|
|
122
|
+
"checks": [
|
|
123
|
+
{
|
|
124
|
+
"kind": "contains",
|
|
125
|
+
"file": "tasks/eval/validation.md",
|
|
126
|
+
"pattern": "^##\\s+Runs[\\s\\S]*^##\\s+Result",
|
|
127
|
+
"flags": "im",
|
|
128
|
+
"label": "validation sections in order"
|
|
129
|
+
}
|
|
130
|
+
]
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"path": "tasks/eval/review.md",
|
|
134
|
+
"kind": "markdown-report",
|
|
135
|
+
"artifact": true,
|
|
136
|
+
"minBytes": 400,
|
|
137
|
+
"checks": [
|
|
138
|
+
{
|
|
139
|
+
"kind": "contains",
|
|
140
|
+
"file": "tasks/eval/review.md",
|
|
141
|
+
"pattern": "Verdict:\\s*(?:PASS|REVISE)",
|
|
142
|
+
"flags": "i",
|
|
143
|
+
"label": "explicit reviewer verdict"
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
}
|
|
147
|
+
],
|
|
148
|
+
"checks": [
|
|
149
|
+
{
|
|
150
|
+
"kind": "notContains",
|
|
151
|
+
"file": "tests/flags.test.mjs",
|
|
152
|
+
"pattern": "\\.skip\\s*\\(|\\.todo\\s*\\(|\\.only\\s*\\(|\\{\\s*skip\\s*:|\\{\\s*todo\\s*:",
|
|
153
|
+
"label": "the flaky test is not skipped, stubbed, or narrowed"
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"kind": "sourceParses",
|
|
157
|
+
"file": "tests/flags.test.mjs"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"kind": "nodeRuns",
|
|
161
|
+
"file": "tests/flags.test.mjs",
|
|
162
|
+
"timeoutMs": 30000
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"kind": "nodeScriptPasses",
|
|
166
|
+
"script": "tests/verify-deflake.mjs",
|
|
167
|
+
"timeoutMs": 60000,
|
|
168
|
+
"requiredOutput": [
|
|
169
|
+
{
|
|
170
|
+
"pattern": "DEFLAKE_ORACLE flags semantics ok",
|
|
171
|
+
"label": "the flags module still behaves"
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"pattern": "DEFLAKE_ORACLE stable 5x",
|
|
175
|
+
"label": "five consecutive green suite runs"
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"pattern": "DEFLAKE_ORACLE assertion intact",
|
|
179
|
+
"label": "the pristine-session assertion survives unweakened"
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"pattern": "DEFLAKE_ORACLE order robust",
|
|
183
|
+
"label": "a late-appended test still sees a pristine session"
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"pattern": "DEFLAKE_ORACLE mutant caught",
|
|
187
|
+
"label": "restoring the original order makes the suite fail again"
|
|
188
|
+
}
|
|
189
|
+
]
|
|
190
|
+
}
|
|
191
|
+
],
|
|
192
|
+
"taskNotes": {
|
|
193
|
+
"minBytes": 120,
|
|
194
|
+
"checks": [
|
|
195
|
+
{
|
|
196
|
+
"kind": "contains",
|
|
197
|
+
"file": "task-notes.md",
|
|
198
|
+
"pattern": "\\bDONE\\b[\\s\\S]*(npm\\s+run\\s+test|node\\s+--test|consecutive)",
|
|
199
|
+
"flags": "i",
|
|
200
|
+
"label": "DONE note cites the stability proof"
|
|
201
|
+
}
|
|
202
|
+
]
|
|
203
|
+
},
|
|
204
|
+
"taskGraph": {
|
|
205
|
+
"requireCraftbookTask": true,
|
|
206
|
+
"requireTerminalStep": true
|
|
207
|
+
},
|
|
208
|
+
"unchangedFixtures": [
|
|
209
|
+
"package.json",
|
|
210
|
+
"src/flags.js",
|
|
211
|
+
"source/flake-report.md"
|
|
212
|
+
]
|
|
213
|
+
},
|
|
214
|
+
"rubric": {
|
|
215
|
+
"artifact": {
|
|
216
|
+
"path": "tasks/eval/fix-notes.md",
|
|
217
|
+
"kind": "markdown"
|
|
218
|
+
},
|
|
219
|
+
"axes": [
|
|
220
|
+
{
|
|
221
|
+
"name": "Mechanism-level diagnosis",
|
|
222
|
+
"description": "The nondeterminism is named as a concrete mechanism (shared module state leaking across tests) and pinned with a real experiment, not guessed from the symptom."
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"name": "No masking",
|
|
226
|
+
"description": "The flake is removed with cleanup or isolation that covers every test; the flaky test keeps its exact assertion and gains no skip, retry, or widened timeout."
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
"name": "Receipt-backed stability",
|
|
230
|
+
"description": "Stability is proven with consecutive green runs recorded as real receipts, and anything unverified is stated plainly instead of claimed."
|
|
231
|
+
}
|
|
232
|
+
]
|
|
233
|
+
},
|
|
234
|
+
"qualityFocus": [
|
|
235
|
+
"statistical reproduction",
|
|
236
|
+
"mechanism removal over masking",
|
|
237
|
+
"consecutive-green receipts"
|
|
238
|
+
]
|
|
239
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"title": "Hotfix with minimal blast radius and a rollback path",
|
|
4
|
+
"objective": "The craftbook drives an urgent fix of a seeded null-guard crash in a receipts formatter: reproduction with the least machinery, the smallest change at the real defect site, honest validation with a rollback path, and an enforced review — verified mechanically, including a mutant re-seed proving the patch engaged the real site.",
|
|
5
|
+
"tags": [
|
|
6
|
+
"code",
|
|
7
|
+
"bug-fix",
|
|
8
|
+
"hotfix",
|
|
9
|
+
"tactical-fleet"
|
|
10
|
+
],
|
|
11
|
+
"prompt": "Use the Hotfix Flow craftbook for this emergency: the nightly receipts export is crashing in production on orders without a gift note. The incident report is in source/incident.md. Reproduce it with the least machinery that shows it, patch minimally at the real defect site, and leave a rollback path.",
|
|
12
|
+
"setup": {
|
|
13
|
+
"projectName": "Receiptline",
|
|
14
|
+
"about": "A tiny order-receipt formatting module behind a nightly export. No test suite - the export script is the only runnable surface.",
|
|
15
|
+
"files": [
|
|
16
|
+
{
|
|
17
|
+
"path": "package.json",
|
|
18
|
+
"content": "{\n \"name\": \"receiptline\",\n \"private\": true,\n \"version\": \"1.0.0\",\n \"type\": \"module\"\n}\n",
|
|
19
|
+
"modelInput": false
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"path": "src/format-order.js",
|
|
23
|
+
"content": "export function formatOrder(order) {\n const lines = [];\n lines.push('Order ' + order.id + ' for ' + order.customer);\n for (const item of order.items) {\n lines.push(' ' + item.qty + ' x ' + item.name + ' @ ' + money(item.unitPrice));\n }\n lines.push('Total: ' + money(orderTotal(order)));\n lines.push('Gift note: ' + order.giftNote.trim());\n return lines.join('\\n');\n}\n\nexport function orderTotal(order) {\n let total = 0;\n for (const item of order.items) {\n total += item.qty * item.unitPrice;\n }\n return Math.round(total * 100) / 100;\n}\n\nfunction money(value) {\n return value.toFixed(2);\n}\n"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"path": "data/orders.json",
|
|
27
|
+
"content": "[\n {\n \"id\": \"A-1041\",\n \"customer\": \"Ana Torres\",\n \"items\": [{ \"qty\": 1, \"name\": \"Ceramic Vase\", \"unitPrice\": 30 }],\n \"giftNote\": \" Happy birthday, Ana! \"\n },\n {\n \"id\": \"A-1042\",\n \"customer\": \"Ben Ito\",\n \"items\": [{ \"qty\": 2, \"name\": \"Stone Mug\", \"unitPrice\": 9.5 }]\n },\n {\n \"id\": \"A-1043\",\n \"customer\": \"Priya Shah\",\n \"items\": [\n { \"qty\": 3, \"name\": \"Linen Napkin\", \"unitPrice\": 4 },\n { \"qty\": 1, \"name\": \"Oak Tray\", \"unitPrice\": 18 }\n ]\n }\n]\n",
|
|
28
|
+
"modelInput": false
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"path": "scripts/print-receipts.mjs",
|
|
32
|
+
"content": "import { readFileSync } from 'node:fs';\nimport { formatOrder } from '../src/format-order.js';\n\nconst orders = JSON.parse(\n readFileSync(new URL('../data/orders.json', import.meta.url), 'utf8'),\n);\nfor (const order of orders) {\n console.log(formatOrder(order));\n console.log('---');\n}\n",
|
|
33
|
+
"modelInput": false
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"path": "source/incident.md",
|
|
37
|
+
"content": "# Incident: receipts export crashing\n\n02:14 - the nightly receipts export died partway through and retail has no morning receipts. Support traced it to orders without a gift note:\n\n TypeError: Cannot read properties of undefined (reading 'trim')\n at formatOrder (src/format-order.js)\n\n`node scripts/print-receipts.mjs` reproduces it: the first order (which has a gift note) prints fine, then the export falls over on the second order in `data/orders.json`.\n\nWhat must hold once this is fixed:\n\n- Orders with a gift note keep printing the trimmed note line.\n- Orders without one print a normal receipt with NO gift-note line.\n- Item lines and totals unchanged.\n\nWe need the smallest safe patch now. The proper cleanup of the formatter can wait for daylight - write it down instead of doing it.\n"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"path": "tests/verify-hotfix.mjs",
|
|
41
|
+
"surface": "harness",
|
|
42
|
+
"content": "import assert from 'node:assert/strict';\nimport { execFileSync } from 'node:child_process';\nimport { cpSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { formatOrder, orderTotal } from '../src/format-order.js';\n\nconst root = process.cwd();\n\n// 1) The crash case is fixed: an order without a gift note formats cleanly.\nconst plain = {\n id: 'A-1042',\n customer: 'Ben Ito',\n items: [{ qty: 2, name: 'Stone Mug', unitPrice: 9.5 }],\n};\nconst plainReceipt = formatOrder(plain);\nassert.ok(!plainReceipt.includes('undefined'), 'a receipt must not leak \"undefined\"');\nassert.ok(!/Gift note:/.test(plainReceipt), 'an order without a gift note must not print a gift-note line');\nassert.ok(plainReceipt.includes('Total: 19.00'), 'totals must survive the patch');\nconsole.log('HOTFIX_ORACLE crash case fixed');\n\n// 2) Neighborhood intact: gift notes still print trimmed, totals still add up.\nconst gifted = {\n id: 'A-1041',\n customer: 'Ana Torres',\n items: [{ qty: 1, name: 'Ceramic Vase', unitPrice: 30 }],\n giftNote: ' Happy birthday, Ana! ',\n};\nconst giftedReceipt = formatOrder(gifted);\nassert.ok(giftedReceipt.includes('Gift note: Happy birthday, Ana!'), 'gift notes must still print, trimmed');\nconst multi = {\n id: 'A-1043',\n customer: 'Priya Shah',\n items: [\n { qty: 3, name: 'Linen Napkin', unitPrice: 4 },\n { qty: 1, name: 'Oak Tray', unitPrice: 18 },\n ],\n};\nassert.equal(orderTotal(multi), 30, 'orderTotal must be untouched');\nconsole.log('HOTFIX_ORACLE neighborhood intact');\n\n// 3) The export the incident names runs clean end to end.\nconst exportOut = execFileSync(process.execPath, ['scripts/print-receipts.mjs'], {\n cwd: root,\n stdio: 'pipe',\n timeout: 30000,\n}).toString();\nassert.ok(exportOut.includes('A-1043'), 'the export must reach the last order');\nconsole.log('HOTFIX_ORACLE export green');\n\n// 4) Re-seed the original defect into a mutant tree: the crash must come\n// back, proving the patch engaged the real site rather than the callers\n// or the data (both of which are pinned fixtures anyway).\nconst ORIGINAL = `export function formatOrder(order) {\n const lines = [];\n lines.push('Order ' + order.id + ' for ' + order.customer);\n for (const item of order.items) {\n lines.push(' ' + item.qty + ' x ' + item.name + ' @ ' + money(item.unitPrice));\n }\n lines.push('Total: ' + money(orderTotal(order)));\n lines.push('Gift note: ' + order.giftNote.trim());\n return lines.join('\\\\n');\n}\n\nexport function orderTotal(order) {\n let total = 0;\n for (const item of order.items) {\n total += item.qty * item.unitPrice;\n }\n return Math.round(total * 100) / 100;\n}\n\nfunction money(value) {\n return value.toFixed(2);\n}\n`;\nconst mutantRoot = join(root, '.oracle-mutant');\nrmSync(mutantRoot, { recursive: true, force: true });\nmkdirSync(join(mutantRoot, 'src'), { recursive: true });\ncpSync(join(root, 'scripts'), join(mutantRoot, 'scripts'), { recursive: true });\ncpSync(join(root, 'data'), join(mutantRoot, 'data'), { recursive: true });\ncpSync(join(root, 'package.json'), join(mutantRoot, 'package.json'));\nwriteFileSync(join(mutantRoot, 'src', 'format-order.js'), ORIGINAL);\nlet mutantStatus = 0;\ntry {\n execFileSync(process.execPath, ['scripts/print-receipts.mjs'], {\n cwd: mutantRoot,\n stdio: 'pipe',\n timeout: 30000,\n });\n} catch (err) {\n mutantStatus = typeof err.status === 'number' ? err.status : 1;\n}\nassert.notEqual(mutantStatus, 0, 're-seeding the original defect must restore the crash - the patch did not engage the real site');\nconsole.log('HOTFIX_ORACLE mutant caught');\nconsole.log('HOTFIX_ORACLE done');\n"
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
"craftbookParams": {
|
|
46
|
+
"workPath": "tasks/eval",
|
|
47
|
+
"scope": "The nightly receipts export crashes on orders without a gift note; see source/incident.md. Smallest safe patch now - the proper cleanup is deferred, not attempted."
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"success": {
|
|
51
|
+
"summary": "The seeded null-guard crash is fixed at the real site with minimal blast radius, the export runs clean, a mutant re-seed restores the crash, and the fleet artifacts carry honest evidence, a Follow-up debt record, and a runnable rollback.",
|
|
52
|
+
"deliverables": [
|
|
53
|
+
{
|
|
54
|
+
"path": "tasks/eval/repro.md",
|
|
55
|
+
"kind": "markdown-notes",
|
|
56
|
+
"artifact": true,
|
|
57
|
+
"minBytes": 500,
|
|
58
|
+
"checks": [
|
|
59
|
+
{
|
|
60
|
+
"kind": "contains",
|
|
61
|
+
"file": "tasks/eval/repro.md",
|
|
62
|
+
"pattern": "^##\\s+Symptom[\\s\\S]*^##\\s+Repro command[\\s\\S]*^##\\s+Expected[\\s\\S]*^##\\s+Actual[\\s\\S]*^##\\s+Evidence",
|
|
63
|
+
"flags": "im",
|
|
64
|
+
"label": "reproduction sections in order"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"kind": "citationsResolve",
|
|
68
|
+
"file": "tasks/eval/repro.md",
|
|
69
|
+
"minCitations": 2,
|
|
70
|
+
"artifact": true
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"path": "tasks/eval/fix-notes.md",
|
|
76
|
+
"kind": "markdown-notes",
|
|
77
|
+
"artifact": true,
|
|
78
|
+
"minBytes": 700,
|
|
79
|
+
"checks": [
|
|
80
|
+
{
|
|
81
|
+
"kind": "contains",
|
|
82
|
+
"file": "tasks/eval/fix-notes.md",
|
|
83
|
+
"pattern": "^##\\s+Problem[\\s\\S]*^##\\s+Change[\\s\\S]*^##\\s+Files touched[\\s\\S]*^##\\s+Risk[\\s\\S]*^##\\s+How to verify[\\s\\S]*^##\\s+Follow-up",
|
|
84
|
+
"flags": "im",
|
|
85
|
+
"label": "fix-notes sections in order, Follow-up included"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"kind": "contains",
|
|
89
|
+
"file": "tasks/eval/fix-notes.md",
|
|
90
|
+
"pattern": "src/format-order\\.js",
|
|
91
|
+
"label": "names the real defect site"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"kind": "citationsResolve",
|
|
95
|
+
"file": "tasks/eval/fix-notes.md",
|
|
96
|
+
"minCitations": 2,
|
|
97
|
+
"artifact": true
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"path": "tasks/eval/validation.md",
|
|
103
|
+
"kind": "markdown-notes",
|
|
104
|
+
"artifact": true,
|
|
105
|
+
"minBytes": 400,
|
|
106
|
+
"checks": [
|
|
107
|
+
{
|
|
108
|
+
"kind": "contains",
|
|
109
|
+
"file": "tasks/eval/validation.md",
|
|
110
|
+
"pattern": "^##\\s+Repro re-run[\\s\\S]*^##\\s+Result[\\s\\S]*^##\\s+Rollback",
|
|
111
|
+
"flags": "im",
|
|
112
|
+
"label": "validation sections in order, Rollback included"
|
|
113
|
+
}
|
|
114
|
+
]
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"path": "tasks/eval/review.md",
|
|
118
|
+
"kind": "markdown-report",
|
|
119
|
+
"artifact": true,
|
|
120
|
+
"minBytes": 400,
|
|
121
|
+
"checks": [
|
|
122
|
+
{
|
|
123
|
+
"kind": "contains",
|
|
124
|
+
"file": "tasks/eval/review.md",
|
|
125
|
+
"pattern": "Verdict:\\s*(?:PASS|REVISE)",
|
|
126
|
+
"flags": "i",
|
|
127
|
+
"label": "explicit reviewer verdict"
|
|
128
|
+
}
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
],
|
|
132
|
+
"checks": [
|
|
133
|
+
{
|
|
134
|
+
"kind": "notContains",
|
|
135
|
+
"file": "src/format-order.js",
|
|
136
|
+
"pattern": "\\btry\\s*\\{|\\bcatch\\s*\\(",
|
|
137
|
+
"label": "the crash is fixed at the site, not swallowed with try/catch"
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"kind": "sourceParses",
|
|
141
|
+
"file": "src/format-order.js"
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"kind": "nodeRuns",
|
|
145
|
+
"file": "scripts/print-receipts.mjs",
|
|
146
|
+
"timeoutMs": 30000
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"kind": "nodeScriptPasses",
|
|
150
|
+
"script": "tests/verify-hotfix.mjs",
|
|
151
|
+
"timeoutMs": 60000,
|
|
152
|
+
"requiredOutput": [
|
|
153
|
+
{
|
|
154
|
+
"pattern": "HOTFIX_ORACLE crash case fixed",
|
|
155
|
+
"label": "the null-guard crash is gone"
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"pattern": "HOTFIX_ORACLE neighborhood intact",
|
|
159
|
+
"label": "gift notes and totals still behave"
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"pattern": "HOTFIX_ORACLE export green",
|
|
163
|
+
"label": "the incident's export runs end to end"
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"pattern": "HOTFIX_ORACLE mutant caught",
|
|
167
|
+
"label": "re-seeding the defect restores the crash"
|
|
168
|
+
}
|
|
169
|
+
]
|
|
170
|
+
}
|
|
171
|
+
],
|
|
172
|
+
"taskNotes": {
|
|
173
|
+
"minBytes": 120,
|
|
174
|
+
"checks": [
|
|
175
|
+
{
|
|
176
|
+
"kind": "contains",
|
|
177
|
+
"file": "task-notes.md",
|
|
178
|
+
"pattern": "\\bDONE\\b[\\s\\S]*validation\\.md",
|
|
179
|
+
"flags": "i",
|
|
180
|
+
"label": "DONE note names the validation deliverable"
|
|
181
|
+
}
|
|
182
|
+
]
|
|
183
|
+
},
|
|
184
|
+
"taskGraph": {
|
|
185
|
+
"requireCraftbookTask": true,
|
|
186
|
+
"requireTerminalStep": true
|
|
187
|
+
},
|
|
188
|
+
"unchangedFixtures": [
|
|
189
|
+
"source/incident.md",
|
|
190
|
+
"package.json",
|
|
191
|
+
"data/orders.json",
|
|
192
|
+
"scripts/print-receipts.mjs"
|
|
193
|
+
]
|
|
194
|
+
},
|
|
195
|
+
"rubric": {
|
|
196
|
+
"artifact": {
|
|
197
|
+
"path": "tasks/eval/fix-notes.md",
|
|
198
|
+
"kind": "markdown"
|
|
199
|
+
},
|
|
200
|
+
"axes": [
|
|
201
|
+
{
|
|
202
|
+
"name": "Minimal blast radius",
|
|
203
|
+
"description": "The change is the smallest that stops the failure at the real defect site - no refactor, rename, or cleanup rode along with the emergency patch."
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
"name": "Honest evidence under pressure",
|
|
207
|
+
"description": "Reproduction and validation quote real observed behavior, and anything that could not actually be run is labeled unverified rather than claimed."
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"name": "Deferred debt discipline",
|
|
211
|
+
"description": "Follow-up records the proper fix and the debt the patch leaves (with a backport note where relevant) instead of attempting a deeper repair mid-incident, and Rollback is a concrete, runnable path."
|
|
212
|
+
}
|
|
213
|
+
]
|
|
214
|
+
},
|
|
215
|
+
"qualityFocus": [
|
|
216
|
+
"minimal-diff discipline",
|
|
217
|
+
"honest verification",
|
|
218
|
+
"runnable rollback"
|
|
219
|
+
]
|
|
220
|
+
}
|