devlyn-cli 4.3.30 → 4.3.32

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 (43) hide show
  1. package/AGENTS.md +1 -1
  2. package/CLAUDE.md +1 -1
  3. package/README.md +3 -1
  4. package/bin/devlyn.js +33 -8
  5. package/bin/harness-activation.js +4 -1
  6. package/bin/harness-status.js +15 -8
  7. package/bin/instruction-templates.json +2 -0
  8. package/bin/skill-history.json +12 -1
  9. package/config/skills/_shared/bring-in.py +10 -0
  10. package/config/skills/_shared/runtime-principles.md +1 -1
  11. package/config/skills/_shared/task-complete.py +319 -54
  12. package/config/skills/_shared/task-completion.md +5 -5
  13. package/config/skills/_shared/warm-build-dirs.py +13 -0
  14. package/config/skills/devlyn-ideate/references/executor.md +1 -1
  15. package/config/skills/devlyn-ideate/references/loop.md +1 -1
  16. package/config/skills/devlyn-ideate/scripts/acceptance.py +11 -0
  17. package/config/skills/devlyn-ideate/scripts/queue.py +17 -1
  18. package/harness/AGENTS.md +2 -2
  19. package/harness/CLAUDE.md +2 -2
  20. package/native/claude/.claude-plugin/plugin.json +1 -1
  21. package/native/claude/skills/_shared/bring-in.py +10 -0
  22. package/native/claude/skills/_shared/runtime-principles.md +1 -1
  23. package/native/claude/skills/_shared/task-complete.py +319 -54
  24. package/native/claude/skills/_shared/task-completion.md +5 -5
  25. package/native/claude/skills/_shared/warm-build-dirs.py +13 -0
  26. package/native/claude/skills/devlyn-ideate/references/executor.md +1 -1
  27. package/native/claude/skills/devlyn-ideate/references/loop.md +1 -1
  28. package/native/claude/skills/devlyn-ideate/scripts/acceptance.py +11 -0
  29. package/native/claude/skills/devlyn-ideate/scripts/queue.py +17 -1
  30. package/native/codex/.agents/plugins/marketplace.json +1 -1
  31. package/native/codex/plugins/devlyn/.codex-plugin/plugin.json +1 -1
  32. package/native/codex/plugins/devlyn/skills/_shared/bring-in.py +10 -0
  33. package/native/codex/plugins/devlyn/skills/_shared/runtime-principles.md +1 -1
  34. package/native/codex/plugins/devlyn/skills/_shared/task-complete.py +319 -54
  35. package/native/codex/plugins/devlyn/skills/_shared/task-completion.md +5 -5
  36. package/native/codex/plugins/devlyn/skills/_shared/warm-build-dirs.py +13 -0
  37. package/native/codex/plugins/devlyn/skills/devlyn-ideate/references/executor.md +1 -1
  38. package/native/codex/plugins/devlyn/skills/devlyn-ideate/references/loop.md +1 -1
  39. package/native/codex/plugins/devlyn/skills/devlyn-ideate/scripts/acceptance.py +11 -0
  40. package/native/codex/plugins/devlyn/skills/devlyn-ideate/scripts/queue.py +17 -1
  41. package/optional-skills/code-review-standards/SKILL.md +10 -6
  42. package/package.json +1 -1
  43. package/release.json +45 -45
package/AGENTS.md CHANGED
@@ -13,7 +13,7 @@ Seven rules govern every change. Cite them by name when a decision touches one.
13
13
  1. **No workaround** — fix the root cause, never the symptom. No `any`, no `@ts-ignore`, no silent `catch`, no hardcoded fallback that hides a broken contract. No config bypasses.
14
14
  2. **No overengineering** — smallest sufficient change, one responsibility per module. New abstractions need an observed failure. Subtractive-first: ask "what can I delete instead?" before writing anything new. Remove code your change makes unused; only report unrelated pre-existing dead code.
15
15
  3. **No guesswork** — verify with the actual files, logs, diffs, and run output before forming conclusions. State the falsifiable prediction BEFORE the experiment; record raw results AFTER. Retroactive prediction edits are dishonest.
16
- 4. **Worldclass** — zero CRITICAL, zero HIGH security/design findings on the shippable path. Any review is one pass in which every reviewer, including each one the user requires, reads the source the checks ran on; fix each finding or reject it with a reason, re-check the fixes and the invariants they touch, and repeat the full review only while a CRITICAL or HIGH finding remains.
16
+ 4. **Worldclass** — zero CRITICAL, zero HIGH findings on the shippable path; each must name a concrete case of wrong behavior or results, a security hole, or lost or corrupted data. A review is one pass on the source the checks ran on, by the reviewers the user requires, else by one reviewer who has not seen the author's reasoning. Fix each finding or reject it with a reason, and verify every edit and the invariants it touches. Only a CRITICAL or HIGH calls for another reviewer pass, which reads the fixes, the rejections and the invariants they touch. If one survives that pass, or its fix caused a new one, repair once more; if the next pass finds either again, stop: the work does not ship and is reported blocked.
17
17
  5. **Best practice** — idiomatic for the language and framework. Use standard primitives; do not hand-roll what the library already provides.
18
18
  6. **Optimized** — efficient on the resource that matters (the user's time, tokens, attention, runtime) without weakening correctness or requirements. An extra check or process step must beat the simpler path.
19
19
  7. **Production ready** — error states are explicit and visible; behavior under failure is what the user expects, not silent corruption.
package/CLAUDE.md CHANGED
@@ -13,7 +13,7 @@ Seven rules govern every change. Cite them by name when a decision touches one.
13
13
  1. **No workaround** — fix the root cause, never the symptom. No `any`, no `@ts-ignore`, no silent `catch`, no hardcoded fallback that hides a broken contract. No config bypasses.
14
14
  2. **No overengineering** — smallest sufficient change, one responsibility per module. New abstractions need an observed failure. Subtractive-first: ask "what can I delete instead?" before writing anything new. Remove code your change makes unused; only report unrelated pre-existing dead code.
15
15
  3. **No guesswork** — verify with the actual files, logs, diffs, and run output before forming conclusions. State the falsifiable prediction BEFORE the experiment; record raw results AFTER. Retroactive prediction edits are dishonest.
16
- 4. **Worldclass** — zero CRITICAL, zero HIGH security/design findings on the shippable path. Any review is one pass in which every reviewer, including each one the user requires, reads the source the checks ran on; fix each finding or reject it with a reason, re-check the fixes and the invariants they touch, and repeat the full review only while a CRITICAL or HIGH finding remains.
16
+ 4. **Worldclass** — zero CRITICAL, zero HIGH findings on the shippable path; each must name a concrete case of wrong behavior or results, a security hole, or lost or corrupted data. A review is one pass on the source the checks ran on, by the reviewers the user requires, else by one reviewer who has not seen the author's reasoning. Fix each finding or reject it with a reason, and verify every edit and the invariants it touches. Only a CRITICAL or HIGH calls for another reviewer pass, which reads the fixes, the rejections and the invariants they touch. If one survives that pass, or its fix caused a new one, repair once more; if the next pass finds either again, stop: the work does not ship and is reported blocked.
17
17
  5. **Best practice** — idiomatic for the language and framework. Use standard primitives; do not hand-roll what the library already provides.
18
18
  6. **Optimized** — efficient on the resource that matters (the user's time, tokens, attention, runtime) without weakening correctness or requirements. An extra check or process step must beat the simpler path.
19
19
  7. **Production ready** — error states are explicit and visible; behavior under failure is what the user expects, not silent corruption.
package/README.md CHANGED
@@ -72,7 +72,9 @@ A bare intent is planned and, when your request authorizes the work, added and d
72
72
 
73
73
  Direct work edits your current checkout; run parallel sessions in separate worktrees (for example `claude -w`). Completed, verified direct requests with changes, and
74
74
  every drained task, are delivered by project policy from their own linked worktrees. A commit request stays local and a PR request stops at the PR; otherwise accepted tasks default to
75
- scoped commit → push → PR → merge when the repository allows it (otherwise the PR waits for a person). After the
75
+ scoped commit → push → PR → merge when the repository allows it (otherwise the PR waits for a person; while required
76
+ checks or reviews have not passed it stays pending, and running the printed resume after they pass merges it, or a person
77
+ merges it; with GitHub's Allow auto-merge on, delivery requests the merge, so it lands by itself). After the
76
78
  PR merges, the worktree and branch its session released are cleaned; anything in use is
77
79
  kept. Set `git config --local devlyn.completionMode pr` to stop at the PR; `task-complete.py complete --mode auto|pr`
78
80
  overrides one task. Local-only/no-push instructions take precedence: nothing is pushed or merged;
package/bin/devlyn.js CHANGED
@@ -616,23 +616,46 @@ function installLocalSkill(skillName, roots, installedSkills = new Map()) {
616
616
  return true;
617
617
  }
618
618
 
619
- // One skill from `source` into one skill-loader directory. The copy is staged and checked first, so
620
- // a failed copy leaves any older copy of it in place for a plain rerun. A copy under its name
619
+ // One skill from `source` into one skill-loader directory. The copy is staged and checked first, and
620
+ // the older copy is moved aside into the stage before the new one is renamed in, and back if that
621
+ // fails, so a failed copy or swap leaves the older copy in place for a plain rerun. If moving it back
622
+ // or removing it after the swap fails, the error names where it is kept. A copy under its name
621
623
  // before the 4.0.0 rename goes only once the new one is complete.
622
624
  function installSkillInto(source, target, skillName, installedSkills) {
623
625
  const dest = path.join(target, skillName);
624
626
  const stage = fs.mkdtempSync(path.join(target, '.devlyn-skill-'));
625
627
  const stagedSkill = path.join(stage, skillName);
628
+ const previous = path.join(stage, 'previous');
629
+ let files;
630
+ let moved = false;
626
631
  try {
627
- const files = copyRecursive(path.join(source, skillName), stagedSkill, stage);
632
+ files = copyRecursive(path.join(source, skillName), stagedSkill, stage);
628
633
  assertCompleteSkillInstall(source, stage, [skillName]);
629
- fs.rmSync(dest, { recursive: true, force: true });
634
+ if (fs.lstatSync(dest, { throwIfNoEntry: false })) {
635
+ fs.renameSync(dest, previous);
636
+ moved = true;
637
+ }
630
638
  fs.renameSync(stagedSkill, dest);
631
- installedSkills.set(dest, files.map((file) => path.join(dest, path.relative(stagedSkill, file))));
632
- } finally {
639
+ } catch (error) {
640
+ if (moved) {
641
+ try { fs.renameSync(previous, dest); }
642
+ catch (rollback) {
643
+ throw new AggregateError([error, rollback], `${error.message}; ${rollback.message}; the previous copy is kept at ${previous}`);
644
+ }
645
+ }
646
+ try { fs.rmSync(stage, { recursive: true, force: true }); }
647
+ catch (cleanup) {
648
+ throw new AggregateError([error, cleanup], `${error.message}; ${dest} is as it was, but ${stage} could not be removed: ${cleanup.message}`);
649
+ }
650
+ throw new Error(`${error.message}; ${dest} is as it was`, { cause: error });
651
+ }
652
+ installedSkills.set(dest, files.map((file) => path.join(dest, path.relative(stagedSkill, file))));
653
+ try {
633
654
  fs.rmSync(stage, { recursive: true, force: true });
655
+ } catch (error) {
656
+ const kept = fs.lstatSync(previous, { throwIfNoEntry: false }) ? `its previous copy at ${previous}` : stage;
657
+ throw new Error(`${dest} is installed, but ${kept} could not be removed: ${error.message}`);
634
658
  }
635
-
636
659
  }
637
660
 
638
661
  // A 0.6.0-0.7.1 copy is one SKILL.md, the file that identifies it. A failed swap leaves
@@ -2256,7 +2279,9 @@ function cleanupDeliver(scope, items, current) {
2256
2279
  if (!prepared.acceptance) return cleanupUpdateCheckout(scope);
2257
2280
  const completed = lastJson(run(['complete', '--receipt', allocated.receipt, '--acceptance', prepared.acceptance, '--writers-stopped'], scope.root).stdout);
2258
2281
  const status = completed?.delivery_status || completed?.status;
2259
- if (status === 'COMPLETE' || status === 'MERGED') return { ...cleanupUpdateCheckout(scope), delivery: { state: 'merged', url: completed.pr || null } };
2282
+ // A merge whose workspace or scratch the helper retained (CLEANUP_PENDING) is not a clean merge: report its resume.
2283
+ if (status === 'COMPLETE' || status === 'MERGED') return { ...cleanupUpdateCheckout(scope), delivery: completed.status === 'CLEANUP_PENDING'
2284
+ ? { state: 'cleanup-pending', url: completed.pr || null, resume: completed.resume } : { state: 'merged', url: completed.pr || null } };
2260
2285
  if (completed?.pr) return { delivery: { state: 'pr-open', url: completed.pr } };
2261
2286
  const reason = completed?.reason || 'delivery did not complete';
2262
2287
  return { error: cleanupReason(failureCode(reason), { detail: reason, ...(completed?.resume ? { resume: completed.resume } : {}) }) };
@@ -380,7 +380,10 @@ function inspectSkills(context, release, env, config, active) {
380
380
  for (const name of SKILLS) {
381
381
  const dir = path.join(root, name);
382
382
  try {
383
- if (!fs.lstatSync(dir, { throwIfNoEntry: false })) continue;
383
+ // A lookup through a file finds no entry: POSIX says ENOTDIR where Windows says "not found".
384
+ let entry;
385
+ try { entry = fs.lstatSync(dir, { throwIfNoEntry: false }); } catch (error) { if (error.code !== 'ENOTDIR') throw error; }
386
+ if (!entry) continue;
384
387
  const hash = fingerprint(dir);
385
388
  if (!hashes.has(name)) hashes.set(name, fingerprint(path.join(release.root, 'config/skills', name)));
386
389
  found.push({ name, path: path.join(dir, 'SKILL.md'), owned: hash === hashes.get(name) || (history.skills[name] || []).includes(hash) });
@@ -70,16 +70,23 @@ function requirements() {
70
70
  const probes = [
71
71
  ['python', true, 'python3', ['-B', '--version']],
72
72
  ['git', true, 'git', ['--version']],
73
- ['git-bash', process.platform === 'win32', 'bash', ['--version']],
74
- ['gh', false, 'gh', ['--version']],
73
+ // Git Bash is a bash whose builtin `pwd -W` (an MSYS2 patch) prints a Windows path; its version label no longer
74
+ // tells it from Cygwin's. -p reads no BASH_ENV or ENV file; --norc no ~/.bashrc, which a bash at shell level 1
75
+ // otherwise reads when SSH_CLIENT is set or stdin is a socket (Node's pipes are). Long options come first. macOS
76
+ // and Linux bashes refuse -W, so there this row (never required) is unavailable.
77
+ ['git-bash', process.platform === 'win32', 'bash', ['--norc', '-p', '-c', 'echo "$BASH_VERSION"; cd / && pwd -W']],
78
+ // gh 2.91 and later writes a telemetry device id into its state folder on every command unless this is off.
79
+ ['gh', false, 'gh', ['--version'], { GH_TELEMETRY: 'false' }],
75
80
  ];
76
- return [node, ...probes.map(([name, required, binary, argv]) => {
77
- const result = spawnSync(binary, argv, { encoding: 'utf8', timeout: 5000, env: { ...process.env, PYTHONDONTWRITEBYTECODE: '1' } });
81
+ return [node, ...probes.map(([name, required, binary, argv, env]) => {
82
+ const result = spawnSync(binary, argv, { encoding: 'utf8', timeout: 5000, env: { ...process.env, PYTHONDONTWRITEBYTECODE: '1', ...env } });
78
83
  const output = (result.stdout || result.stderr || '').trim();
79
- const match = output.match(/\b(\d+)\.(\d+)(?:\.\d+)?/);
80
- let available = !result.error && result.status === 0 && Boolean(match);
84
+ const bash = name === 'git-bash';
85
+ // A bash's version is its $BASH_VERSION line, never digits in the path line after it.
86
+ const match = output.match(bash ? /^\d+\.\d+\.\d+(?=(?:\(\d+\)-\w+)?\r?$)/m : /\b(\d+)\.(\d+)(?:\.\d+)?/);
87
+ let available = !result.error && result.status === 0
88
+ && (bash ? /^(?:[A-Za-z]:\/|\/\/)/.test(output.split('\n').pop()) : Boolean(match));
81
89
  if (name === 'python' && available) available = Number(match[1]) > 3 || (Number(match[1]) === 3 && Number(match[2]) >= 11);
82
- if (name === 'git-bash' && required && available) available = /mingw|msys/i.test(output);
83
90
  return { name, required, available, version: match?.[0] || null,
84
91
  reasons: available ? [] : [{ code: 'requirement-unavailable', params: { name } }] };
85
92
  })];
@@ -168,4 +175,4 @@ function statusCommand(args) {
168
175
  return status;
169
176
  }
170
177
 
171
- module.exports = { harnessStatus, statusCommand, repositoryIdentity, inspectInstruction };
178
+ module.exports = { harnessStatus, statusCommand, repositoryIdentity, inspectInstruction, requirements };
@@ -469,6 +469,7 @@
469
469
  "bddb4f88a0c11165b9cafe7a31027e9769313e1aee7c0a9ed9dad490e4fe1bcc",
470
470
  "be11c198a50be2884c4c1efec52bbddff55c7547a5daf0ec2ef046279c95dc45",
471
471
  "bfdb7c7e4db21e1c452e730cecadc8e97abd317c6e54ae58c298f4288b1f1354",
472
+ "c1970e6a96f0c4241907d29fb4cdf831ad255b2bbfdb5270fe0aefc32cb91f0d",
472
473
  "c1a1e9722a0f3c13c693eeaacdac8cc3d13d36d242f2bab58311170496ea4e2e",
473
474
  "c236da36a45d4013ffb7e131575229b605f662a30b5174f14754f519acc24252",
474
475
  "c276962617888c5ac2d352c5e2ed018c5ce9d00f199c73e1dd61438ec4a914fb",
@@ -997,6 +998,7 @@
997
998
  "c115b2ba9ec7abe2fa5261a5894e3c4899794b527f01ec682ae7fd2479199c08",
998
999
  "c150c40a04099d7b726eb8aecc8eec8e92f9f9248a6a5c15556c08000c4bd231",
999
1000
  "c16ff4fe013ee2cef905d767a09305d9c1b2f778a06b439f0bc4645ac05bc82b",
1001
+ "c1970e6a96f0c4241907d29fb4cdf831ad255b2bbfdb5270fe0aefc32cb91f0d",
1000
1002
  "c1c7e45fedafb97770b6726539694eb0668c70677c2031fe2db2bc8b5339423a",
1001
1003
  "c227759474dc46ec6df00fe7baf8ba4b6b0adc71f5068ef522ff46526c861a48",
1002
1004
  "c27b13c3ae4e6fb34d9b28b8f4e899e29bfbf606a69207b9532d0e44e6078a2e",
@@ -12,6 +12,7 @@
12
12
  "08c91060cfec04518de582599d1892ad50f6e6cec69aecd8678760c3e0039fa0",
13
13
  "0a60dd9b96442be24a571dd5fe6cac426bba7dd7a06ad17f3211f4f9fd9b1741",
14
14
  "0b5c3f72d18f8eea538bfef7192b207ff5cbac25c7e0d2ce080cc725bfdaa2e2",
15
+ "0d7e8097f36623f68b7cdc26e9c2eb80d9792b3776edf308d306febdfd9f26ae",
15
16
  "0f397a4edd6b1b3063d27f6205dc6b3d069fa616624bccf661539b174535fc7e",
16
17
  "110005e3c7052d35502186d907b169c9fc7c85d558ab7c7ad0ba2f0308aa7a5d",
17
18
  "11ac38b21ecc139211af1b335bb3acc4f0f1bc4b5c133e81a80cafebcaaca298",
@@ -56,6 +57,7 @@
56
57
  "406b982f6ca0b9f5c0faa6cb50749b52aaf23545e06174ec39f831929dc929bd",
57
58
  "40f50f3c3c0d030d1efeb6955c0c6f32f518e737d8dd3bec6610ff02badebbdb",
58
59
  "430d156eb8c62c7edba3d660050f90b267f928976c3a3688e95d54f00dc34747",
60
+ "446e47fc34c81ed4cb9f4332d446a93025ae3dc1791155a4b80d6f195255958e",
59
61
  "450d578ef177a9e8f0b693940ad64b41c1d9719975ba6305f62a7c82ac3a892f",
60
62
  "45ef27af9ec27089e2861c13b882521fc6bf073dc6b7a356b326b4a27c5e6e24",
61
63
  "4685be6a94ad5587ce53785c14a60cccf9a852d9d23391dba0a5bcd0c64931cf",
@@ -119,6 +121,7 @@
119
121
  "8c80926ab03b2477e52264495b35c2116f65fc51b02e8c56e441b5705872392a",
120
122
  "8fb73c0d2472b3643ac6e3f0ad87d818694afebaf68fcad596496e703893c43d",
121
123
  "9162fc2fed6f4a611d299485be3a397080beb3304865ce59b95576ba7d00650e",
124
+ "92ffe78e156d8f11f666a92b26d21ae52e147ed9cad7eb79efbef334a9373281",
122
125
  "94a14a1b87df1d7297d12949a24e47a0d6c16a8fe30495ee759fcabb2e1aa398",
123
126
  "978e4210e49b42827c98cf6e40c868c87dc6e3533a2b779ca2fa05abfc16ad0f",
124
127
  "97e7ad89c74c609b15dfbf6f9f7ac61df8b50e97e4bc318f72922e058ecffba4",
@@ -196,6 +199,7 @@
196
199
  "f2bcfa0471aba81a10e3d0e6fd43bd6ec670601a4ba3a7d719e595edf9ab032a",
197
200
  "f958bfabd2e056fea911526fba2196d2ed5a48828f576e5ce1657100b466db20",
198
201
  "f9617e1034543f31ae2a3820301fbac6e4674e5d6fbc0d4b76751fe87b8e013e",
202
+ "fbca65e47854425acd80087e89024fb9d2f44f853d88abe582fbee107a3e8de3",
199
203
  "fd68c7a74272929a14e685e447a51058ffcdd4c1d6bef83cbba18045c07aee55",
200
204
  "fdb608b34a8600b4ce209d7f645ec5ad4475948be6ad95c941cc7ef02b5959df",
201
205
  "fe357defe8ac6efd6bbd15b3bf35f79d79761c0f56d507488d9428536d4fb5f7",
@@ -224,7 +228,8 @@
224
228
  "3fe0742825aff05fa6fda49d3e3e0fbf5457307af944eb90f2771cbf611edd69",
225
229
  "4a8bed603191eeb6834a5008691bb3942e77462abd2818340b808a752ee5a224",
226
230
  "57c2481f9ae36623f59b365eae82f22d54253f8ba0fd690949a12858b5f6e308",
227
- "b352d21d2a86def2997d89ae1ffa35b0fe428781f75cfa9e1b69a3384416ec31"
231
+ "b352d21d2a86def2997d89ae1ffa35b0fe428781f75cfa9e1b69a3384416ec31",
232
+ "be2562b5541d754c34e42b4242751bbaf3b3b2780f4314552ebb63a350e23170"
228
233
  ],
229
234
  "devlyn-auto-resolve": [
230
235
  "0740bb91fb99953631b0c2c273f00210544576f9497af5eecfdd5fe1e58349e2",
@@ -363,6 +368,8 @@
363
368
  "36b58dbdc26e51abc05a60872c4582faeebd67e9fe5626a3933467ba07c68dc4",
364
369
  "40237cd5259dbcf7c490f130e844a9e32eea48a8edabd50800edee5029bf95a4",
365
370
  "4213143689f7e7fe62ab8743c256a45492fafffc1757d64901b7b02725aee5c3",
371
+ "437659470cb978840f503c7d4a2af75c78beb2752cc3eed413bb33de346bd561",
372
+ "472d2ad853c96651324aa9a3de00cb61c0cecacb389e850ab1b380d535d22922",
366
373
  "49d6e024b343dd77e4c0cea0e513e40fe679a7a8192953190d042b3a21bbf69c",
367
374
  "5536f8391ec4442f1b793dba8dd5d7820d45f4b6dadf1111cbac9d54469a01ca",
368
375
  "573a6059a7383b37affd9c2e8bc6c88a4fb54117628a5a0746406cc32111e9aa",
@@ -381,6 +388,7 @@
381
388
  "6e2b54571bfbc1fab571b81564fb0625ed83333fc12277c473fdf5a231f7d40c",
382
389
  "6e7228610628fc4bca31dc0b0aaf5eb4445e1f123f2c54bd13921c5cd01129fe",
383
390
  "75cecbce4d1f4adbba608cef498ae7e421ea75512c6bf9282b66cd94d821f672",
391
+ "78be1509ca8cf797f8c6e790d0d49ab608e50e0b828916c8c6ee790165ce792b",
384
392
  "7f451e48e391643b34f6249244bc47d93d6303875e7b092771e3af0718343bc1",
385
393
  "7fb3ceaf835230e1a75e510b046f4fe26e79815760354bec1949fa55515c6316",
386
394
  "83e9de10d3c439af17dc4d7a603109d35136c5c8bd468ab2be962e1fad064c3c",
@@ -404,6 +412,7 @@
404
412
  "db8d921aabf0d04811b55465a3757c62c4b39631aebaf6eecc994ca241cfbe56",
405
413
  "e25da746dc37b2e82c658a28d9481fd69741151045683eee2119582ddaf731cd",
406
414
  "e47a2ce766ae81fa0870e0a8dfbfe737311de69ce620e92217abbe4c532e3c8b",
415
+ "e67d3662836adf13c2e7177553bba6e7695484bd40438e8188cb9dd6d956cd2f",
407
416
  "e929f76c15349f1b9bc1e84e0a3e9e48e916168d79270e0f4a36ea8eab9b5388",
408
417
  "ebc693658da0b260c876f29cd6dfc2b12ae6690e3532622fa9c1cd4481162bd8",
409
418
  "f2243cc4150e225961825f6097b0cf38166c291dcf58127516ceee841f7ed4c8",
@@ -825,6 +834,8 @@
825
834
  "4.3.29",
826
835
  "4.3.3",
827
836
  "4.3.30",
837
+ "4.3.31",
838
+ "4.3.32",
828
839
  "4.3.4",
829
840
  "4.3.5",
830
841
  "4.3.6",
@@ -363,6 +363,8 @@ class BringInTests(unittest.TestCase):
363
363
  self.env = {key: value for key, value in os.environ.items()
364
364
  if not key.startswith("GIT_")}
365
365
  self.env.update(GIT_CONFIG_NOSYSTEM="1", GIT_CONFIG_GLOBAL=str(self.root / "no-global"),
366
+ # A commit's detached automatic maintenance would still write into .git while a test copies it.
367
+ GIT_CONFIG_COUNT="1", GIT_CONFIG_KEY_0="maintenance.auto", GIT_CONFIG_VALUE_0="false",
366
368
  GIT_AUTHOR_NAME="Fixture", GIT_AUTHOR_EMAIL="fixture@example.invalid",
367
369
  GIT_COMMITTER_NAME="Fixture", GIT_COMMITTER_EMAIL="fixture@example.invalid",
368
370
  LC_ALL="C", GIT_EDITOR=":", GIT_MERGE_AUTOEDIT="no")
@@ -415,6 +417,14 @@ class BringInTests(unittest.TestCase):
415
417
  path.write_bytes(("#!/bin/sh\n" + body).encode("utf-8"))
416
418
  path.chmod(0o755)
417
419
 
420
+ def test_fixture_commit_starts_no_automatic_maintenance(self):
421
+ # Its detached child would still write .git/objects/maintenance.lock while copytree or cleanup reads the tree.
422
+ trace = self.root / "trace.json"
423
+ self.env["GIT_TRACE2_EVENT"] = str(trace)
424
+ self.commit("traced", "traced\n")
425
+ children = [line for line in trace.read_text(encoding="utf-8").splitlines() if '"event":"child_start"' in line]
426
+ self.assertEqual(children, [])
427
+
418
428
  def test_fast_forward_and_paths_with_spaces(self):
419
429
  self.cli()
420
430
  self.assertEqual(self.g("rev-parse", "HEAD").strip(), self.target)
@@ -15,7 +15,7 @@ Seven rules govern every change. Cite them by name when a decision touches one.
15
15
  1. **No workaround** — fix the root cause, never the symptom. No `any`, no `@ts-ignore`, no silent `catch`, no hardcoded fallback that hides a broken contract. No config bypasses.
16
16
  2. **No overengineering** — smallest sufficient change, one responsibility per module. New abstractions need an observed failure. Subtractive-first: ask "what can I delete instead?" before writing anything new. Remove code your change makes unused; only report unrelated pre-existing dead code.
17
17
  3. **No guesswork** — verify with the actual files, logs, diffs, and run output before forming conclusions. State the falsifiable prediction BEFORE the experiment; record raw results AFTER. Retroactive prediction edits are dishonest.
18
- 4. **Worldclass** — zero CRITICAL, zero HIGH security/design findings on the shippable path. Any review is one pass in which every reviewer, including each one the user requires, reads the source the checks ran on; fix each finding or reject it with a reason, re-check the fixes and the invariants they touch, and repeat the full review only while a CRITICAL or HIGH finding remains.
18
+ 4. **Worldclass** — zero CRITICAL, zero HIGH findings on the shippable path; each must name a concrete case of wrong behavior or results, a security hole, or lost or corrupted data. A review is one pass on the source the checks ran on, by the reviewers the user requires, else by one reviewer who has not seen the author's reasoning. Fix each finding or reject it with a reason, and verify every edit and the invariants it touches. Only a CRITICAL or HIGH calls for another reviewer pass, which reads the fixes, the rejections and the invariants they touch. If one survives that pass, or its fix caused a new one, repair once more; if the next pass finds either again, stop: the work does not ship and is reported blocked.
19
19
  5. **Best practice** — idiomatic for the language and framework. Use standard primitives; do not hand-roll what the library already provides.
20
20
  6. **Optimized** — efficient on the resource that matters (the user's time, tokens, attention, runtime) without weakening correctness or requirements. An extra check or process step must beat the simpler path.
21
21
  7. **Production ready** — error states are explicit and visible; behavior under failure is what the user expects, not silent corruption.