yadflow 4.0.0-next.3 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/CHANGELOG.md +699 -0
  2. package/README.md +85 -22
  3. package/bin/commands.mjs +3 -1
  4. package/bin/yad.mjs +183 -29
  5. package/cli/capture.mjs +4 -2
  6. package/cli/checkpoint.mjs +10 -10
  7. package/cli/claims.mjs +4 -4
  8. package/cli/commit.mjs +48 -12
  9. package/cli/docs.mjs +15 -13
  10. package/cli/doctor.mjs +557 -141
  11. package/cli/epic-state.mjs +41 -18
  12. package/cli/errors.mjs +3 -2
  13. package/cli/find-product.mjs +197 -0
  14. package/cli/fold.mjs +4 -4
  15. package/cli/gate-local.mjs +13 -13
  16. package/cli/gate.mjs +111 -103
  17. package/cli/history.mjs +13 -13
  18. package/cli/hook.mjs +201 -30
  19. package/cli/index-command.mjs +6 -6
  20. package/cli/lib.mjs +91 -29
  21. package/cli/manifest.mjs +171 -104
  22. package/cli/migrate.mjs +208 -17
  23. package/cli/mode.mjs +22 -22
  24. package/cli/next.mjs +6 -6
  25. package/cli/openpr.mjs +32 -24
  26. package/cli/people.mjs +22 -10
  27. package/cli/plan.mjs +718 -45
  28. package/cli/platform.mjs +13 -7
  29. package/cli/product-index.mjs +4 -4
  30. package/cli/{hubcommit.mjs → productcommit.mjs} +11 -7
  31. package/cli/protection.mjs +19 -9
  32. package/cli/reconcile.mjs +98 -23
  33. package/cli/repo-publish.mjs +22 -16
  34. package/cli/repo.mjs +128 -33
  35. package/cli/report.mjs +4 -2
  36. package/cli/review.mjs +26 -19
  37. package/cli/setup.mjs +105 -36
  38. package/cli/ship.mjs +1 -1
  39. package/cli/skip.mjs +4 -4
  40. package/cli/tidy.mjs +7 -7
  41. package/cli/update-commit.mjs +22 -19
  42. package/cli/workspace.mjs +495 -0
  43. package/package.json +7 -4
  44. package/skills/sdlc/config.yaml +14 -13
  45. package/skills/sdlc/module-help.csv +8 -8
  46. package/skills/yad-analysis/SKILL.md +6 -4
  47. package/skills/yad-architecture/SKILL.md +4 -3
  48. package/skills/yad-backfill/SKILL.md +11 -5
  49. package/skills/yad-backfill/references/backfill.md +33 -3
  50. package/skills/yad-backfill/templates/checks/backfill-check.sh +200 -17
  51. package/skills/yad-change/SKILL.md +1 -1
  52. package/skills/yad-checks/SKILL.md +48 -27
  53. package/skills/yad-checks/references/check-gates.md +213 -53
  54. package/skills/yad-checks/templates/checks/commit-message.sh +39 -13
  55. package/skills/yad-checks/templates/checks/contract-check.sh +472 -23
  56. package/skills/yad-checks/templates/checks/epic-open.sh +398 -8
  57. package/skills/yad-checks/templates/checks/ledger-guard.sh +75 -25
  58. package/skills/yad-checks/templates/checks/lineage-check.sh +391 -7
  59. package/skills/yad-checks/templates/checks/product-checkout.sh +141 -0
  60. package/skills/yad-checks/templates/checks/reconcile-debt-check.sh +399 -8
  61. package/skills/yad-checks/templates/checks/risk-map-check.sh +35 -3
  62. package/skills/yad-checks/templates/checks/spec-link.sh +36 -3
  63. package/skills/yad-checks/templates/checks/verified-commits.sh +26 -2
  64. package/skills/yad-checks/templates/github/yad-checks.yml +33 -13
  65. package/skills/yad-checks/templates/github/{yad-hub-checks.yml → yad-product-checks.yml} +14 -10
  66. package/skills/yad-checks/templates/github/yad-update-guard.yml +1 -1
  67. package/skills/yad-checks/templates/github/yad-verified-commits.yml +1 -1
  68. package/skills/yad-checks/templates/gitlab/yad-checks.gitlab-ci.yml +12 -0
  69. package/skills/yad-checks/templates/gitlab/{yad-hub-checks.gitlab-ci.yml → yad-product-checks.gitlab-ci.yml} +16 -16
  70. package/skills/yad-checks/templates/gitlab/yad-verified-commits.gitlab-ci.yml +2 -2
  71. package/skills/yad-checks/templates/hooks/ledger-guard-cursor.mjs +130 -0
  72. package/skills/yad-checks/templates/hooks/ledger-guard.mjs +117 -0
  73. package/skills/yad-checks/templates/hooks/yad-capture.mjs +117 -0
  74. package/skills/yad-commit/SKILL.md +18 -7
  75. package/skills/yad-connect-design/SKILL.md +1 -1
  76. package/skills/yad-connect-design/references/design-registry.md +1 -1
  77. package/skills/yad-connect-docs/SKILL.md +16 -11
  78. package/skills/yad-connect-docs/references/docs-registry.md +8 -8
  79. package/skills/yad-connect-learning/SKILL.md +1 -1
  80. package/skills/yad-connect-learning/references/learning-registry.md +1 -1
  81. package/skills/yad-connect-repos/SKILL.md +31 -8
  82. package/skills/yad-connect-repos/references/code-context.md +1 -1
  83. package/skills/yad-connect-repos/references/{hub-config.md → product-config.md} +19 -11
  84. package/skills/yad-connect-repos/references/repos-registry.md +1 -1
  85. package/skills/yad-connect-testing/SKILL.md +1 -1
  86. package/skills/yad-connect-testing/references/testing-registry.md +1 -1
  87. package/skills/yad-discovery/SKILL.md +2 -2
  88. package/skills/yad-discovery/references/discovery-schema.md +1 -1
  89. package/skills/yad-docs/SKILL.md +1 -1
  90. package/skills/yad-docs/references/data-mapping.md +1 -1
  91. package/skills/yad-docs/templates/app/package-lock.json +8 -8
  92. package/skills/yad-docs/templates/app/package.json +1 -1
  93. package/skills/yad-docs/templates/app/src/components/Canvas/FlowCanvas.tsx +2 -2
  94. package/skills/yad-docs-overview/references/pipeline-model.md +3 -3
  95. package/skills/yad-engineer-review/SKILL.md +2 -2
  96. package/skills/yad-engineer-review/references/ship-and-record.md +3 -3
  97. package/skills/yad-epic/SKILL.md +6 -4
  98. package/skills/yad-epic/references/state-schema.md +13 -12
  99. package/skills/yad-open-pr/SKILL.md +1 -1
  100. package/skills/yad-pair-review/SKILL.md +5 -5
  101. package/skills/yad-pair-review/references/session-state.md +2 -2
  102. package/skills/yad-pr-template/SKILL.md +14 -12
  103. package/skills/yad-pr-template/templates/checks/pr-template.sh +18 -16
  104. package/skills/yad-pr-template/templates/checks/pr-title.sh +15 -13
  105. package/skills/yad-pr-template/templates/{hub → product}/github/pull_request_template.md +2 -2
  106. package/skills/yad-pr-template/templates/{hub → product}/gitlab/merge_request_templates/Default.md +2 -2
  107. package/skills/{yad-hub-bridge → yad-product-bridge}/SKILL.md +15 -15
  108. package/skills/{yad-hub-bridge → yad-product-bridge}/references/bridge.md +15 -10
  109. package/skills/{yad-hub-bridge → yad-product-bridge}/references/login-roster.md +2 -2
  110. package/skills/{yad-hub-bridge/templates/checks/hub-route.sh → yad-product-bridge/templates/checks/product-route.sh} +2 -2
  111. package/skills/{yad-hub-bridge → yad-product-bridge}/templates/github/yad-gate-sync.yml +29 -16
  112. package/skills/{yad-hub-bridge → yad-product-bridge}/templates/gitlab/gitlab-ci.include-root.yml +1 -1
  113. package/skills/{yad-hub-bridge → yad-product-bridge}/templates/gitlab/yad-gate-sync.gitlab-ci.yml +5 -3
  114. package/skills/yad-report/SKILL.md +1 -1
  115. package/skills/yad-review-companion/SKILL.md +3 -3
  116. package/skills/yad-review-gate/SKILL.md +22 -23
  117. package/skills/yad-review-gate/references/gating.md +13 -13
  118. package/skills/yad-run/SKILL.md +2 -2
  119. package/skills/yad-run/references/run-loop.md +2 -2
  120. package/skills/yad-spec/SKILL.md +2 -1
  121. package/skills/yad-spec/references/spec-handoff.md +19 -10
  122. package/skills/yad-stories/SKILL.md +2 -2
  123. package/skills/yad-sync-repos/SKILL.md +19 -3
  124. package/skills/yad-test-cases/SKILL.md +2 -2
  125. package/skills/yad-ui/SKILL.md +2 -2
  126. package/skills/yad-checks/templates/hooks/ledger-guard-cursor.sh +0 -91
  127. package/skills/yad-checks/templates/hooks/ledger-guard.sh +0 -100
  128. package/skills/yad-checks/templates/hooks/yad-capture.sh +0 -53
package/CHANGELOG.md CHANGED
@@ -1,3 +1,702 @@
1
+ # [4.0.0](https://github.com/abdelrahmannasr/yadflow/compare/v3.18.1...v4.0.0) (2026-09-30)
2
+
3
+
4
+ * feat!: print Product, not hub, in output, --json and commit subjects (E124) ([b982530](https://github.com/abdelrahmannasr/yadflow/commit/b982530402dde171575407e82e72b8a2c405639a))
5
+ * feat!: read product.json first, and refuse two names that disagree (E122) ([2252296](https://github.com/abdelrahmannasr/yadflow/commit/22522969823c8a3525fa255c62a7a08c444b7450))
6
+ * feat!: rename the installed hub names to product, and name what is left (E123) ([91c62b6](https://github.com/abdelrahmannasr/yadflow/commit/91c62b6467d220a13b88970fd16b7bd42d740ffc))
7
+ * feat(checks)!: risk-route and hub-route print the approval count, not roles (E62) ([8754585](https://github.com/abdelrahmannasr/yadflow/commit/875458576c6800356980b302dd3366d0b7a5e02a))
8
+ * feat(checks)!: verified-commits checks signatures only; the author allowlist is gone (E62) ([67c0161](https://github.com/abdelrahmannasr/yadflow/commit/67c01612372f74e6c70b5af24636eae034fe34c7))
9
+ * feat(cli)!: every command answers --json in one envelope (E1) ([7862dfb](https://github.com/abdelrahmannasr/yadflow/commit/7862dfb7d496171bc5f8fa20e533ffc688c57f0e))
10
+ * feat(epic)!: shape 5 — the work-item type, and a chore may stand alone ([5eb24fb](https://github.com/abdelrahmannasr/yadflow/commit/5eb24fb04e5d6c686d92b69e4d1b8dd1ea41d46b))
11
+ * feat(gate)!: a team gate needs one approver, and approvals name the platform login (E62) ([3730b9c](https://github.com/abdelrahmannasr/yadflow/commit/3730b9cc4f58acede87f9a020ac1ded0b7cf1fdd))
12
+ * feat(gate)!: review and task PRs request no reviewers (E62) ([d9f3d76](https://github.com/abdelrahmannasr/yadflow/commit/d9f3d765cced1b50868197bf8622e891a2af0f3a))
13
+ * feat(gate)!: shape 9 — an approval's fingerprint leaves out the frontmatter status line ([226f9ec](https://github.com/abdelrahmannasr/yadflow/commit/226f9ec4b9c19bdd055a1f9094b5c95badd69864))
14
+ * feat(migrate)!: shape 8 — `yad migrate` moves the product level into foundation/ (E75) ([88e726f](https://github.com/abdelrahmannasr/yadflow/commit/88e726fe9b24737d02e2b7f32e167a60f09e6961))
15
+ * feat(setup)!: remove yad roster and stop collecting people in setup (E62) ([5eb6914](https://github.com/abdelrahmannasr/yadflow/commit/5eb69147c84aa6b83ddda2c3e394b4f183caca6a))
16
+ * feat(state)!: finish the hub to Product rename ([92a9750](https://github.com/abdelrahmannasr/yadflow/commit/92a9750e708ab130000872e09fd15ff68c4a3c00))
17
+ * feat(state)!: yad undefer re-opens a deferred step behind finished work (E41) ([518b7cc](https://github.com/abdelrahmannasr/yadflow/commit/518b7cc7c339f20cf417712b5e8da0e560312f29))
18
+ * feat(usage)!: yad usage lists people from activity, not from the roster (E62) ([0664996](https://github.com/abdelrahmannasr/yadflow/commit/0664996f4dae2f190fcd304cb259759054251a80))
19
+ * fix(docs)!: a failed docs build exits 1 and says which site failed ([381a000](https://github.com/abdelrahmannasr/yadflow/commit/381a0000754ff4eb9fec4856692d4627369d6420))
20
+
21
+
22
+ ### Bug Fixes
23
+
24
+ * a broken shared registry never stops a join, and the .git check reads names as Windows does (E79 review 4) ([160ec83](https://github.com/abdelrahmannasr/yadflow/commit/160ec83512df1f6f50245f0f0f2714e7c3588230))
25
+ * a copyable hint never prints a registry name that starts with - (E81 review 10) ([8caa29d](https://github.com/abdelrahmannasr/yadflow/commit/8caa29d752d843f0ec16c1a79a030e532076cb73))
26
+ * a monorepo subfolder is present, refresh keeps to code-context, null entries are named (E81 review 1) ([f899a0d](https://github.com/abdelrahmannasr/yadflow/commit/f899a0dcb37f4f71851802c700ba02f9d2ed39c4))
27
+ * a workspace file sends only the Product's own registered repos to it, and stops the walk when it is not used (E80 review 1) ([2a01287](https://github.com/abdelrahmannasr/yadflow/commit/2a01287bb7fc30f4d2dc604273691ba20aec97e7))
28
+ * a worktree or nested repo inside a registered repo is its own checkout, never swapped for the repo's (E80 review 3) ([de05ebd](https://github.com/abdelrahmannasr/yadflow/commit/de05ebd33b5a21fe0c0d689fd9190ab99f4293c7))
29
+ * **agents:** answer Cursor in the protocol it actually reads ([d6d6175](https://github.com/abdelrahmannasr/yadflow/commit/d6d6175e71447e6ae735979631dd74802d3f0f13))
30
+ * **agents:** close the fifteen defects the deep review found ([cc42177](https://github.com/abdelrahmannasr/yadflow/commit/cc421772bceee0513a3ca30f382cdbb606de39d6))
31
+ * **agents:** close the five defects the E11 review found ([c4ca25f](https://github.com/abdelrahmannasr/yadflow/commit/c4ca25fd66d497157d2ee37707984b02f1c500b0))
32
+ * **agents:** close the four the audit had left open ([0e5dcd8](https://github.com/abdelrahmannasr/yadflow/commit/0e5dcd80a752f263a45865b3188edf57421818eb))
33
+ * **agents:** close the last three, and stop a comment claiming something false ([292a7b1](https://github.com/abdelrahmannasr/yadflow/commit/292a7b1c2b45457f230c39fc19f3db1535beb50d))
34
+ * **agents:** let the doctor see the script Cursor actually invokes ([a070911](https://github.com/abdelrahmannasr/yadflow/commit/a0709113dfca4b94608c0519157f0157060d3999))
35
+ * allow % in a URL's user and password for https only (E81 review 7) ([b1f05e4](https://github.com/abdelrahmannasr/yadflow/commit/b1f05e42453da655b0644032503fc4b6bec59db2))
36
+ * allow the file transport per URL, not per run (E81 review 4) ([fd88947](https://github.com/abdelrahmannasr/yadflow/commit/fd889479c6c99b3dbd6ac20ad0cfbdf592ec641d))
37
+ * an unreadable record is its own gate state, and the advice reads as steps (E124 review 5) ([8608e8e](https://github.com/abdelrahmannasr/yadflow/commit/8608e8ea6994607f3da8fef65b355823da257738))
38
+ * **artifact-status:** a "$" in a frontmatter value no longer corrupts the status flip ([545123a](https://github.com/abdelrahmannasr/yadflow/commit/545123a5889cf48910507872ba45607592650cd9))
39
+ * **capture:** continue origin's branch when there is no local one; name a refused push (E43 review 2) ([8e2c07d](https://github.com/abdelrahmannasr/yadflow/commit/8e2c07d32d1b6882c7b543b9b3c65f96ca67e919))
40
+ * **capture:** every git call takes the environment runCapture was given (E43) ([c347c94](https://github.com/abdelrahmannasr/yadflow/commit/c347c9460154e6b30472a3a1aae2869354a6fce4))
41
+ * **capture:** prune deleted capture branches; read [a-z] and list brackets as GitHub does (E43 review 3) ([2322dcb](https://github.com/abdelrahmannasr/yadflow/commit/2322dcb0321ff02f0ebf22ecfe61b2979236944d))
42
+ * **capture:** subfolder Products, staged-then-deleted files, a plain push, and a truer workflow scan (E43 review) ([14f0eeb](https://github.com/abdelrahmannasr/yadflow/commit/14f0eeb6e5fe9ce21bdfe5fb168ace88a41d7ad6))
43
+ * **capture:** take design-links.json and test-links.json with the artifacts (E44) ([ad4f2cf](https://github.com/abdelrahmannasr/yadflow/commit/ad4f2cfc1f134c3b17616348081795a09939049a))
44
+ * **checks:** a C-quoted path is an artifact change; warn on a rename-blind workflow (E47 review 4) ([e6af8df](https://github.com/abdelrahmannasr/yadflow/commit/e6af8df0f4dafd3ec593da44114b07c45b67f54a))
45
+ * **checks:** a claimed Contract-Change with no lock at all now FAILS ([2008eea](https://github.com/abdelrahmannasr/yadflow/commit/2008eea518b4e20052fb277301140d33a9793182))
46
+ * **checks:** a kept Product is read only when product-repo reaches nothing (E117) ([434f0c0](https://github.com/abdelrahmannasr/yadflow/commit/434f0c03d0ade65ec90f375e95cc129b59f97571))
47
+ * **checks:** a link.md's epic must be its story's own (E118) ([4f09325](https://github.com/abdelrahmannasr/yadflow/commit/4f09325f6e168db74ccc222ba0d8fc7feea30381))
48
+ * **checks:** a Product path starting with - is still walked twice (E117) ([a823dd5](https://github.com/abdelrahmannasr/yadflow/commit/a823dd56e8c13a7d94fb6874a21539fa286d97ec))
49
+ * **checks:** accept every integrity algorithm Corepack accepts in packageManager ([367947d](https://github.com/abdelrahmannasr/yadflow/commit/367947d8d9856138b531061e4b686057ee9f715f))
50
+ * **checks:** backfill-check folds every character a Mac folds into ASCII (E116) ([e913baa](https://github.com/abdelrahmannasr/yadflow/commit/e913baaf6c68e171e2e06f139c6b25bac9732b79))
51
+ * **checks:** backfill-check folds the Kelvin sign into k (E116) ([c5152c3](https://github.com/abdelrahmannasr/yadflow/commit/c5152c350ab1dd89e6906eac9433316be5ecf261))
52
+ * **checks:** backfill-check lists go through the stream, not the environment (E116) ([f2366f0](https://github.com/abdelrahmannasr/yadflow/commit/f2366f0c1433a05bae614956b66326223f2e51ab))
53
+ * **checks:** backfill-check pairs raw records, frees twins, checks links when specs are hidden (E116) ([6544926](https://github.com/abdelrahmannasr/yadflow/commit/654492634f9f65dbe702701ddaf8af038ba2beae))
54
+ * **checks:** backfill-check reads each spec by its object id (E116) ([6e44ae5](https://github.com/abdelrahmannasr/yadflow/commit/6e44ae576d547333bc1a256a1a3e473f8ddc5e1f))
55
+ * **checks:** backfill-check reads every spelling of the verified key (E116) ([81588e6](https://github.com/abdelrahmannasr/yadflow/commit/81588e62d71c60174fe678a8756d1a0806388554))
56
+ * **checks:** backfill-check reads the last verified: key, as YAML does (E116) ([36cb5cd](https://github.com/abdelrahmannasr/yadflow/commit/36cb5cda6a817b6a4d3504052058fa26c6eefb9d))
57
+ * **checks:** backfill-check reads the spec from the base and refuses links (E116) ([b63f5ac](https://github.com/abdelrahmannasr/yadflow/commit/b63f5ac706cd6155b5db63ffaf258dcd11d4269d))
58
+ * **checks:** cache the Corepack home alongside the dependency cache ([23d92bc](https://github.com/abdelrahmannasr/yadflow/commit/23d92bc8204063bbd7754bfd038585eeb6f705bb))
59
+ * **checks:** close configurable CI review findings ([6d90018](https://github.com/abdelrahmannasr/yadflow/commit/6d900183bbee5785f4ff0d5c868a6a55ce01a9b7))
60
+ * **checks:** close the gaps review 1 found in the Product and epic reads (E117, E118) ([a8d8178](https://github.com/abdelrahmannasr/yadflow/commit/a8d81780c35a651e30e51e5dcc0e30252ac50205))
61
+ * **checks:** close the gaps review 2 found in the Product reads (E117, E118) ([dcc5ea5](https://github.com/abdelrahmannasr/yadflow/commit/dcc5ea5667be4c52676656aef5723813edce4857))
62
+ * **checks:** close the gaps review 3 found in the Product reads (E117) ([fbb0768](https://github.com/abdelrahmannasr/yadflow/commit/fbb076848e5c1ba7f67ad34ff5d7b5b7d5d094e7))
63
+ * **checks:** compare the git folder as a folder, not a spelling (E117) ([2a824a8](https://github.com/abdelrahmannasr/yadflow/commit/2a824a83b4f8eb0129b1275ec8b45832d5f22d87))
64
+ * **checks:** contract-check fails a first spec whose product-repo reaches nothing (E119) ([a4738fc](https://github.com/abdelrahmannasr/yadflow/commit/a4738fce11d4b2e87ef6d03bcea865d22feb52dc))
65
+ * **checks:** contract-check folds every character a Mac folds into ASCII (E121) ([8422e70](https://github.com/abdelrahmannasr/yadflow/commit/8422e70e192f15c26053a94ccbf2ecb8c658d720))
66
+ * **checks:** E114 review 1 — one odd name per test, split lines, full hint ([df9f4dc](https://github.com/abdelrahmannasr/yadflow/commit/df9f4dcaf5736bfbd93a49c017ffae257e2b4ef6))
67
+ * **checks:** fail with guidance when corepack is missing for a declared packageManager ([3a9f576](https://github.com/abdelrahmannasr/yadflow/commit/3a9f5760bcca050d87008e414b856d5b307f30b8))
68
+ * **checks:** fold the long s into specs; say a file is a file (E115 review 2) ([373ba16](https://github.com/abdelrahmannasr/yadflow/commit/373ba16c81bc3c0eb5c56bb7adae48441b4f07a8))
69
+ * **checks:** give the same guidance when Corepack is present but stale ([0cdf4d1](https://github.com/abdelrahmannasr/yadflow/commit/0cdf4d157946d9185bfcc286ebddcdfb5d65a6aa))
70
+ * **checks:** hub-route reads whole risk tags; route output stops claiming an author check ([53bda97](https://github.com/abdelrahmannasr/yadflow/commit/53bda9717e75367940abab8ab033f3429c274e22))
71
+ * **checks:** keep a yarn/bun-declared repo with an npm lockfile on the npm path ([713e707](https://github.com/abdelrahmannasr/yadflow/commit/713e7074b6813de0e0fd6e12e970e8372a1309eb))
72
+ * **checks:** keep the gate jobs' variables off the host GitLab pipeline ([7cb2c35](https://github.com/abdelrahmannasr/yadflow/commit/7cb2c35a3011dbd8bf8d048f7aa02578ac54a1db))
73
+ * **checks:** keep the npm path when a repo carries both lockfiles ([67fbdb4](https://github.com/abdelrahmannasr/yadflow/commit/67fbdb4e2c82188b37b1d175260b48da17d5e051))
74
+ * **checks:** let a PR of step owner files alone through on a Product (E47 review 2) ([f7ff5b0](https://github.com/abdelrahmannasr/yadflow/commit/f7ff5b062a51b455a18190a31ccbd5488fe5785f))
75
+ * **checks:** list a rename by both paths in contract-check and backfill-check (E114) ([09bb4de](https://github.com/abdelrahmannasr/yadflow/commit/09bb4de3f36e0fec0eb247565fc2364a46b482b8))
76
+ * **checks:** list renames and unquoted paths in the hub-checks diff (E47 review 3) ([bc270e0](https://github.com/abdelrahmannasr/yadflow/commit/bc270e0583a7583ffccea94b9ecaa1a11498ec46))
77
+ * **checks:** make build-test-lint fail closed on a rejected package.json ([83241ee](https://github.com/abdelrahmannasr/yadflow/commit/83241eed61e4306853151e6105c0b7c8bdd06d55))
78
+ * **checks:** pass the worker cap to jest/vitest under pnpm without npm's `--` ([55db7ee](https://github.com/abdelrahmannasr/yadflow/commit/55db7eed85173472a17e7591636d7fc830a5a5b6))
79
+ * **checks:** read every NUL list with a newline in a name as ? (E121) ([2659211](https://github.com/abdelrahmannasr/yadflow/commit/2659211c94a28d52c7a25a956d8c75bab1dd61ec))
80
+ * **checks:** read package.json the way npm does before judging it ([8021c78](https://github.com/abdelrahmannasr/yadflow/commit/8021c7850d4f7d0887923165adc585fc27da260a))
81
+ * **checks:** read specs/ without case; name a failed tree read (E115 review 1) ([a9fb725](https://github.com/abdelrahmannasr/yadflow/commit/a9fb72599a5980e9f2e8307cb87eca9ae31f17ca))
82
+ * **checks:** read the changed list as bytes; check each workflow line (E47 review 5) ([edc850b](https://github.com/abdelrahmannasr/yadflow/commit/edc850b20495a13d376b6f01dc02db61658d4e27))
83
+ * **checks:** refuse a Product path inside the repo's own .git (E117) ([b726032](https://github.com/abdelrahmannasr/yadflow/commit/b7260323e1aebab247ad6367ea2bd1c6a6d4756d))
84
+ * **checks:** refuse a second spelling of contracts/ or a story folder (E115 review 3) ([debc7b6](https://github.com/abdelrahmannasr/yadflow/commit/debc7b68f8bbddf5634322228f633327aba8c50a))
85
+ * **checks:** refuse a symlink or submodule under specs/ in contract-check (E115) ([e93387a](https://github.com/abdelrahmannasr/yadflow/commit/e93387aa036cc40b9d6741291a1ef518a0d03e1b))
86
+ * **checks:** removing a contract slice under a lockless epic is allowed ([9d0b66a](https://github.com/abdelrahmannasr/yadflow/commit/9d0b66a412d19c6b222f9e3a24dbcac1a8bde4ad))
87
+ * **checks:** require lowercase Corepack digests ([4750b8b](https://github.com/abdelrahmannasr/yadflow/commit/4750b8b597bfdd4d7d2739a0525f91a2002e41a3))
88
+ * **checks:** restore dependency caching in the GitHub quality job, for pnpm too ([21c92f0](https://github.com/abdelrahmannasr/yadflow/commit/21c92f026aa590ec464eec7152af27ad2be9a49d))
89
+ * **checks:** risk-route reads an older risk-map check as "not counted", never as "nothing is high" ([a486d7b](https://github.com/abdelrahmannasr/yadflow/commit/a486d7b7b46ae95df03f3a372b72f72cc61c0e6a))
90
+ * **checks:** run the gate's lint/build/test through the pinned npm too ([8404da3](https://github.com/abdelrahmannasr/yadflow/commit/8404da326f8a19ae807c58808b6203572aadb9b4))
91
+ * **checks:** run the risk-map awk in the C locale so every awk reads bytes ([4d0d748](https://github.com/abdelrahmannasr/yadflow/commit/4d0d748e0ce575178cfa2d1a9f42df82a40caf16))
92
+ * **checks:** say what the story-spelling rule does not catch (E115 review 4) ([3d36c93](https://github.com/abdelrahmannasr/yadflow/commit/3d36c934406b148c3601c5a6bfdacd40abccbad3))
93
+ * **checks:** support configurable CI toolchains ([30557e4](https://github.com/abdelrahmannasr/yadflow/commit/30557e419a9fec5adca06a3ecb8ca09469b2a58a))
94
+ * **checks:** the first-spec FAIL fires only when the Product is not reached (E119) ([322ffe3](https://github.com/abdelrahmannasr/yadflow/commit/322ffe39fd2654aae5022898db3d3f71bd1d4f11))
95
+ * **checks:** the PR no longer chooses where the Product is read from (E117) ([68db03b](https://github.com/abdelrahmannasr/yadflow/commit/68db03b61269346a9c540f7fa39d4b37648f627b))
96
+ * **checks:** validate Corepack integrity metadata ([a6c3fd3](https://github.com/abdelrahmannasr/yadflow/commit/a6c3fd3d84a370f81477ed9b551bc29f5765296f))
97
+ * **checks:** walk the Product path again from where it really lands (E117) ([1b0726d](https://github.com/abdelrahmannasr/yadflow/commit/1b0726d04a83544beef2bdfd3aac32f395d373bd))
98
+ * **ci:** Pages write scopes move to the job; one pin per action major (review 1) ([92a51fe](https://github.com/abdelrahmannasr/yadflow/commit/92a51febd1146c7f90528855d67cfa8d1be81255))
99
+ * **ci:** pin every workflow action by commit SHA and make the default token read-only ([43254bb](https://github.com/abdelrahmannasr/yadflow/commit/43254bba2c5606831ba7328896326c83c3dd4a3e))
100
+ * **claims:** find the first capture's base in one git call, with no cap (E46 review 2) ([e4a6fcf](https://github.com/abdelrahmannasr/yadflow/commit/e4a6fcf2a33acba0c4b76b5ba54e99d740dcd1d7))
101
+ * **claims:** keep the once-an-hour memory across a push; own edits only; over-report a missing base (E46 review 1) ([7ab038d](https://github.com/abdelrahmannasr/yadflow/commit/7ab038d436fc9d46009fd31139bd7327083ebac3))
102
+ * **claims:** pin the first-capture search against the person's git config (E46 review 3) ([80db192](https://github.com/abdelrahmannasr/yadflow/commit/80db1926695f60884a47b6a72b5a79f634ac5519))
103
+ * **claims:** read the Yad-Base trailer with a pinned separator (E46 review 4) ([c026fef](https://github.com/abdelrahmannasr/yadflow/commit/c026fef2454f6a5799b6e0f8fe5a04ee6cbbad62))
104
+ * clean every printed path, one wording for the quote, and the door works from a Product subfolder (E49 review 2) ([85ea6a4](https://github.com/abdelrahmannasr/yadflow/commit/85ea6a4f5e99942aba7dd28fdd05605319cc241c))
105
+ * **cli:** a JSON refusal keeps what was done; every warning is collected (E1 review 1) ([41fce95](https://github.com/abdelrahmannasr/yadflow/commit/41fce957954e75bb64fb0ab4271270935e7dc2fc))
106
+ * **cli:** a later failure keeps its hint; every commit row has the same keys (E1 review 3) ([188b2de](https://github.com/abdelrahmannasr/yadflow/commit/188b2dec55ce8b25a9fa8fe8e471864141c1def4))
107
+ * **cli:** answer in JSON only when the running command is history (PR review 3) ([cdc8250](https://github.com/abdelrahmannasr/yadflow/commit/cdc8250b340693b5e80d8d49a26044305ec52a4a))
108
+ * **cli:** every line that names a skill asks the project, not the catalogue ([c085218](https://github.com/abdelrahmannasr/yadflow/commit/c08521818e951faddb04c4e26fe5639a70cc0f1b))
109
+ * **cli:** every sweep failure reaches the JSON; a refusal says what was committed (E1 review 2) ([dd7ef3e](https://github.com/abdelrahmannasr/yadflow/commit/dd7ef3e00713bdeba43b0870e70ac90ee4246bf7))
110
+ * **cli:** the history JSON error is exactly the documented refusal shape ([d20c9a3](https://github.com/abdelrahmannasr/yadflow/commit/d20c9a3ab7f83ed73139c62f4eb2622d8a44440d))
111
+ * **cli:** the review round — a write that ate a user's bindings, and five more ([3c63059](https://github.com/abdelrahmannasr/yadflow/commit/3c63059686c467c5a8b29367d1e7712472835b9b))
112
+ * **cli:** two more prototype holes, and yad-run reads the binding without a lane ([3a0a114](https://github.com/abdelrahmannasr/yadflow/commit/3a0a1146e2b50154a294cd8ae0e30dc0e4a2ee58))
113
+ * clone a registered repo only from a network address (E81 review 3) ([1582784](https://github.com/abdelrahmannasr/yadflow/commit/15827845f14329d1d592a01d68b8f3a9b122e19c))
114
+ * close the last one-key product.json hints, and refuse before touching .gitignore (E122 review 3) ([2b10f5b](https://github.com/abdelrahmannasr/yadflow/commit/2b10f5bd7568c5121adf72d5ab1f6e832c1029f9))
115
+ * **codeowners:** a GitLab heading's unreadable default owners are reported (E68 review 3) ([cd9a1f1](https://github.com/abdelrahmannasr/yadflow/commit/cd9a1f1c6628040ccf3c35efad0c49185039e73e))
116
+ * **codeowners:** a path typed in another case is still the top folder; a refusal is JSON under --json (E69 review 5) ([397ccaf](https://github.com/abdelrahmannasr/yadflow/commit/397ccaf9efdf8b6807a04721a2bd726b49398863))
117
+ * **codeowners:** a pattern crosses a folder name holding a line break; no set copy per rule (E69 review 3) ([7341d79](https://github.com/abdelrahmannasr/yadflow/commit/7341d79080cc0d5558929869afbbfb812f84853e))
118
+ * **codeowners:** an exclusion's extra words are not an owner problem; describe the GitLab defaults rule ([4f50303](https://github.com/abdelrahmannasr/yadflow/commit/4f50303ac1fa9d50ad830a1c3ff7813f2a39bfc5))
119
+ * **codeowners:** exact dead-line answer for escaped characters; fast for every common shape; refuse --write= (E69 review 2) ([c52b17d](https://github.com/abdelrahmannasr/yadflow/commit/c52b17db4ba7829bd59497cd60a8e00eb52c839f))
120
+ * **codeowners:** no address in a not-read reason; fast dead-line check; exact file name; top folder only (E69 review 1) ([036f907](https://github.com/abdelrahmannasr/yadflow/commit/036f9078f09f220a45de5f10a44bb9998a3c8a9d))
121
+ * **codeowners:** read the file list only when a CODEOWNERS exists; a list git cannot produce is not known ([a2f0cc8](https://github.com/abdelrahmannasr/yadflow/commit/a2f0cc8a626be7720aaf3b7c99118a93a34ff002))
122
+ * **dial:** close the holes the E34 review found ([2038d19](https://github.com/abdelrahmannasr/yadflow/commit/2038d19bf596ae958e3b51fb2b0bc3b2fbbd4860))
123
+ * **docs:** a new yad release no longer marks every docs site stale ([bdbbff1](https://github.com/abdelrahmannasr/yadflow/commit/bdbbff1eaaf7d89e7582d43dbbc11df52de84bd4))
124
+ * **docs:** only a deploy where every site built ends on a tick (review 2) ([68251be](https://github.com/abdelrahmannasr/yadflow/commit/68251beb3d9208011481e77587ba4ffc46d923cf))
125
+ * **docs:** raise the docs shell version to 0.0.2 for the brace-expansion bump ([74498a5](https://github.com/abdelrahmannasr/yadflow/commit/74498a545b96923b5096b7adf06631e96ae7e616))
126
+ * **docs:** the review round — right site folder, a real test, no green tick after a failed deploy ([9f868d8](https://github.com/abdelrahmannasr/yadflow/commit/9f868d8332679ab437c49b8e07fc3a5d15534faf))
127
+ * **doctor:** "on every change" also when a scoped rule could not be read (E70 review 6) ([36e52ff](https://github.com/abdelrahmannasr/yadflow/commit/36e52ffd80b74a43404924f1b8aab9a0133ec8b6))
128
+ * **doctor:** a 404 on a list never means "they do not exist" (E70 review 27) ([8bdf98f](https://github.com/abdelrahmannasr/yadflow/commit/8bdf98f64dbb1924768d161d8019813e4aecf7f4))
129
+ * **doctor:** a 404 on the rules is a host without rulesets, not a permission (E70 review 28) ([f80f92d](https://github.com/abdelrahmannasr/yadflow/commit/f80f92d4c468195730ef1a9c28089fb07dfbcf28))
130
+ * **doctor:** a belief from a 404 may remove an offer, never add certainty (E70 review 30) ([a3f653d](https://github.com/abdelrahmannasr/yadflow/commit/a3f653d15514a7842cadefcd16772235df7dfee9)), closes [#7386](https://github.com/abdelrahmannasr/yadflow/issues/7386) [#29576](https://github.com/abdelrahmannasr/yadflow/issues/29576)
131
+ * **doctor:** a branch yad cannot read settles nothing (E70 review 24) ([8d9a46a](https://github.com/abdelrahmannasr/yadflow/commit/8d9a46a1a2826b09634fcfdbce4e820e94882392))
132
+ * **doctor:** a colon, not a second dash, in the GitLab sentence (E70 review 11) ([9d8c835](https://github.com/abdelrahmannasr/yadflow/commit/9d8c83525a69945753250f9acbedbe469dcc609a))
133
+ * **doctor:** a floor counts rules, not labels (E70 review 23) ([3f7d124](https://github.com/abdelrahmannasr/yadflow/commit/3f7d124d6698973d599da54bf64724f4fb8bf23a))
134
+ * **doctor:** a GitLab rule with no name reads as "an approval rule" (E70 review 12) ([5ada04a](https://github.com/abdelrahmannasr/yadflow/commit/5ada04abb6356099a81280a910bc181a09b37dae))
135
+ * **doctor:** a hint hedges wherever its own message does (E70 review 31) ([e256f06](https://github.com/abdelrahmannasr/yadflow/commit/e256f06c50db96cfbab79dda4e91a63fcf91c456))
136
+ * **doctor:** a pointer only where something was unread, and numbers that agree (E70 review 16) ([2ff23f5](https://github.com/abdelrahmannasr/yadflow/commit/2ff23f53b12d0fa3f5d5d00766a90c4333d6dd80))
137
+ * **doctor:** a protection line states only what the platform answered (E70 review 3) ([453f646](https://github.com/abdelrahmannasr/yadflow/commit/453f6463040578c297c46f4cd22ba0521860c27f))
138
+ * **doctor:** a read that answered nothing says so, and one source is named once (E70 review 22) ([25eabe8](https://github.com/abdelrahmannasr/yadflow/commit/25eabe8d02778514bafdbf25b3698caac6a4b2f5))
139
+ * **doctor:** a rule keyed on a wording must say when it stops firing (E70 review 32b) ([6beeb6f](https://github.com/abdelrahmannasr/yadflow/commit/6beeb6f8c3c1f72f30c869559b763f6e3a6097e0))
140
+ * **doctor:** a sentence for a count read beside a protection that was not (E70 review 8) ([8421b00](https://github.com/abdelrahmannasr/yadflow/commit/8421b0060e54308632bbfacaf89149eabb9da98c))
141
+ * **doctor:** an id reads as an id, and no sentence pairs two dashes (E70 review 13) ([8a07f2b](https://github.com/abdelrahmannasr/yadflow/commit/8a07f2bd8b99785ed3bcdf192269113c7ac038c4))
142
+ * **doctor:** apply round 16's fixes to their twins as well (E70 review 17) ([f99db88](https://github.com/abdelrahmannasr/yadflow/commit/f99db8823e34dce8eb84c3bde8f87c04385d0f7f))
143
+ * **doctor:** ask for --overwrite-local only when a plain --fix would not do (E120 review 8) ([5950b89](https://github.com/abdelrahmannasr/yadflow/commit/5950b89def883390bafc0c3922ce4ad65d2f3131))
144
+ * **doctor:** compare artifacts the way every reader of the field does ([75688d9](https://github.com/abdelrahmannasr/yadflow/commit/75688d9208608c1626cbfdbcb274b0e2f3960979))
145
+ * **doctor:** decide the record's ahead/behind state by git, in one table (E120 review 5) ([1739cc5](https://github.com/abdelrahmannasr/yadflow/commit/1739cc5afff34d638376215c6da90d58aaf191bb))
146
+ * **doctor:** give the missing-default hint E109's two repository actions, from one string (E110) ([2e751a9](https://github.com/abdelrahmannasr/yadflow/commit/2e751a984e18a1faa007caee0488b11454292c33))
147
+ * **doctor:** judge an off-branch clone's record as it will be after the switch (E120 review 9) ([39025bd](https://github.com/abdelrahmannasr/yadflow/commit/39025bd09c92870aacdcacca38cb3906c29da502))
148
+ * **doctor:** name `gate repair --push` for a stranded step on a verified Product (E48 review 3) ([29f0340](https://github.com/abdelrahmannasr/yadflow/commit/29f0340be0d0bef0f5e3d40a18d0da645e352b80))
149
+ * **doctor:** name a product-link record committed but never pushed (E120 review 3) ([4db532a](https://github.com/abdelrahmannasr/yadflow/commit/4db532a2712670e63f6caba85aeffd108ee63030))
150
+ * **doctor:** name folders under epics/ that are not valid epic ids ([1e0e4ac](https://github.com/abdelrahmannasr/yadflow/commit/1e0e4ac6357f03def0362ef5201e39e352b3a40b))
151
+ * **doctor:** never read a count or "not protected" the platform did not prove (E70 review 1) ([4800bff](https://github.com/abdelrahmannasr/yadflow/commit/4800bffbbeb8bebdf8a20f228992c82d88a98028))
152
+ * **doctor:** never rule a cause out and then offer it again (E70 review 29) ([aeef14b](https://github.com/abdelrahmannasr/yadflow/commit/aeef14b152e6941e7681901ce633e87339b1435a))
153
+ * **doctor:** no silence over a broken record, and hints that work off the default branch (E120 review 6) ([97c714b](https://github.com/abdelrahmannasr/yadflow/commit/97c714b66429f3a9731fd0d853ab20fcaaff75f4))
154
+ * **doctor:** one clear step per repo in the product-link hint (E120 review 7) ([c117c3d](https://github.com/abdelrahmannasr/yadflow/commit/c117c3d2aa737df27c2a3167e2001dd8454654aa))
155
+ * **doctor:** point the legacy BMAD hints at what still works (E3) ([60df2dc](https://github.com/abdelrahmannasr/yadflow/commit/60df2dc168751f27bd6a892698f211550abd18b6))
156
+ * **doctor:** read a gate one bash command at a time (E114 review 2) ([06d3f69](https://github.com/abdelrahmannasr/yadflow/commit/06d3f69113e3b19f3b9cee1cf77a637999372775))
157
+ * **doctor:** read the GitLab branch itself; a rule on an unprotected branch is no hold (E70 review 2) ([90d8df9](https://github.com/abdelrahmannasr/yadflow/commit/90d8df9581ba9c7f21b528fc119a4fb00e75a774))
158
+ * **doctor:** restore a guard I wrongly called unreachable (E70 review 18) ([dabd9a1](https://github.com/abdelrahmannasr/yadflow/commit/dabd9a1042da5db52e51c48ba5671e833269ed87))
159
+ * **doctor:** satisfy eslint — split on ** instead of a NUL placeholder; no useless assignment (E43) ([aad5822](https://github.com/abdelrahmannasr/yadflow/commit/aad582240fa0b8f4a279b0221100fba967ced20d))
160
+ * **doctor:** say GitHub's flag the same way everywhere; fill the level table (E70 review 9) ([dca372b](https://github.com/abdelrahmannasr/yadflow/commit/dca372bd289461235cab097b08e87561f5f3c0c6))
161
+ * **doctor:** say only what this read leaves possible (E70 review 15) ([328cf0a](https://github.com/abdelrahmannasr/yadflow/commit/328cf0a6a32de5805b60f6f33ff159ba1c8c5d90))
162
+ * **doctor:** say the GitLab repository could not be read, not that your login cannot (E109) ([3a8ffa5](https://github.com/abdelrahmannasr/yadflow/commit/3a8ffa583d6ac7f15270a9c217c77be5700b585c))
163
+ * **doctor:** see a step that carries ONLY the new dial name ([8ad471f](https://github.com/abdelrahmannasr/yadflow/commit/8ad471f2d90ef4d90df6016b92b4064ce867631b))
164
+ * **doctor:** stop the theme checks reporting correct files ([c6c3a0c](https://github.com/abdelrahmannasr/yadflow/commit/c6c3a0c278ccad2734061e1bd04fbb8b578431f6))
165
+ * **doctor:** tell the two reach gaps apart, and check every partly read line (E70 review 25) ([31dcf1d](https://github.com/abdelrahmannasr/yadflow/commit/31dcf1d5fd0a6e7f55dc4ee249b9c9f277b00500))
166
+ * **doctor:** tell unpushed, on another branch and behind apart (E120 review 4) ([9356748](https://github.com/abdelrahmannasr/yadflow/commit/935674881340e9c47aaba04b77196b343368cd64))
167
+ * **doctor:** test the GitLab repository 404 on the shape GitLab really sends (E109) ([81f4001](https://github.com/abdelrahmannasr/yadflow/commit/81f4001f518ea9cd65f31bb93f265176244408a9))
168
+ * **doctor:** the banner needs no rule at all, and lint is green again (E70 review 5) ([7830496](https://github.com/abdelrahmannasr/yadflow/commit/783049648722440999cde7ca079f6d61f0cff536))
169
+ * **doctor:** the clause binds to the rule, not to the branch it names (E70 review 26) ([4ea1403](https://github.com/abdelrahmannasr/yadflow/commit/4ea140368d7d71451204f49304b71fba52c4bbf7))
170
+ * **doctor:** the joined GitLab phrase reads as a sentence (E70 review 10) ([f81a423](https://github.com/abdelrahmannasr/yadflow/commit/f81a423bf0b5a672e0441ebfa04f2ac3e7fd18d3))
171
+ * **doctor:** the last paired dashes, and a limit narrower than the code (E70 review 14) ([d67ae31](https://github.com/abdelrahmannasr/yadflow/commit/d67ae3144e6735db23e73b9a9daa54e29e99a0a4))
172
+ * **doctor:** the review round — a finding whose only remedy always failed ([2783186](https://github.com/abdelrahmannasr/yadflow/commit/27831861756450ed0067271a80f08062e3c35b44))
173
+ * **doctor:** the solo line carries the same facts; hedge what is not read (E70 review 4) ([7019585](https://github.com/abdelrahmannasr/yadflow/commit/7019585ec60deaa28f4217f52a531c8e2943e8fa))
174
+ * **doctor:** the split turns on what the read proved, not where the name came from (E70 review 32) ([3930636](https://github.com/abdelrahmannasr/yadflow/commit/3930636ea87f92275c19fa6751c4a5be1ba074c5))
175
+ * **doctor:** the tier framing belongs to a refusal, and the grid reaches every branch (E70 review 21) ([c2377ef](https://github.com/abdelrahmannasr/yadflow/commit/c2377ef37fd0ae9e11f9b6d7b4454c3db23c8e4c))
176
+ * **doctor:** two answers that disagree are not known; a rule elsewhere is not "no rules" (E70 review 7) ([b002fd8](https://github.com/abdelrahmannasr/yadflow/commit/b002fd89fe9d95b402cb422e7491093b89510b4d))
177
+ * drop the exact registry path from the warning, and clean C1 control characters too (E79 review 7) ([c70911c](https://github.com/abdelrahmannasr/yadflow/commit/c70911c5e199b2433325e3a4996b3fe240be42ad))
178
+ * **e120:** a record is ok only when committed as it stands (review 2) ([f2fc7de](https://github.com/abdelrahmannasr/yadflow/commit/f2fc7dec1435d009ead6966c831d4aa409871306))
179
+ * **e120:** a record right on disk reads ok, and --push still commits it (CI) ([a5cd7f5](https://github.com/abdelrahmannasr/yadflow/commit/a5cd7f541283a6715cc012bd57194f0684e2cdc8))
180
+ * **e120:** commit the record for sure, keep secrets out, keep local runs checking ([e96ed5d](https://github.com/abdelrahmannasr/yadflow/commit/e96ed5dc8b87938097fb35270d4b677c456377e3))
181
+ * **engine:** drop the profile field nothing read, and fix the test seam ([07af526](https://github.com/abdelrahmannasr/yadflow/commit/07af526629684ee5b5c53438b13e2983ccb82bfc))
182
+ * **epic:** close the holes the E42 review found ([574870f](https://github.com/abdelrahmannasr/yadflow/commit/574870f0d6ebfe1d0c5501daa74a7927662fc13e))
183
+ * **epic:** protect the reserved front-zero id, and stop a false type clash ([871f763](https://github.com/abdelrahmannasr/yadflow/commit/871f763bbf0df4ca92f4991b1456db00bb2aecec))
184
+ * every doctor command to copy takes registry text as one plain word (E81 review 11) ([e2d147a](https://github.com/abdelrahmannasr/yadflow/commit/e2d147addb163f5397b054f1e84b506b1732668c))
185
+ * **fold:** fold a staged deletion; refuse mid-merge and on a detached HEAD (E44 review 1) ([4391b1b](https://github.com/abdelrahmannasr/yadflow/commit/4391b1b1eb6d22990b672a0d3f64b5fb5e77c5ec))
186
+ * **fold:** name a case-only rename only when git shows the new spelling (E44 review 4) ([2a6395c](https://github.com/abdelrahmannasr/yadflow/commit/2a6395c7f9ae7c7d9ee8bf1877e4cb770b2197c0))
187
+ * **fold:** never run git add with an empty list; refuse a git rm --cached path (E44 review 2) ([cfbaefc](https://github.com/abdelrahmannasr/yadflow/commit/cfbaefc9d8334a20ddbd585b9c2c25a0d31992f7))
188
+ * **fold:** tell a case-only rename from git rm --cached (E44 review 3) ([a374fc3](https://github.com/abdelrahmannasr/yadflow/commit/a374fc314f266354cdf96200b54dfa631423d4c2))
189
+ * **fold:** the Product level is seeded under either spelling; truer words (E44 review 6) ([c711326](https://github.com/abdelrahmannasr/yadflow/commit/c71132643b8c3ca1fb1d0b5c3a4739d0b18209dd))
190
+ * **fold:** the verified seed rule asks ledger-guard's own question; a change-epic's seed rides along (E44) ([f0ee36d](https://github.com/abdelrahmannasr/yadflow/commit/f0ee36d60bad06ac0920b64d97bf16e9f19a7a06))
191
+ * **foundation:** close the holes the roadmap-status review found ([69392d4](https://github.com/abdelrahmannasr/yadflow/commit/69392d441b4212448e0e3092eb74dc313e1f19b2))
192
+ * **foundation:** skills that hand-apply the gate know the Foundation, and the preview lists every moved file ([8e20897](https://github.com/abdelrahmannasr/yadflow/commit/8e20897d56c4c047d207fffdd7a644ebb81ae149))
193
+ * **foundation:** the review round — one product level in the guard, and a move that cannot strand ([5bca4ba](https://github.com/abdelrahmannasr/yadflow/commit/5bca4baded95a108018a780fd0c6ec06f1b3c62b))
194
+ * **gate:** `gate status` counts approvals the way the gate counts them ([eda7429](https://github.com/abdelrahmannasr/yadflow/commit/eda7429d6454f93c3ce034456ab61ab6b5afa3a7))
195
+ * **gate:** `gate status` prints the shortfall, and honours a skip only where the gate does ([95c9c2a](https://github.com/abdelrahmannasr/yadflow/commit/95c9c2a49adfcea6f4e8daf13932d386d4c5a75a))
196
+ * **gate:** a hand-edited cap below 1 is not printed; the inherited test says what it checks (E72) ([49dcef7](https://github.com/abdelrahmannasr/yadflow/commit/49dcef760aa00a46ec157cba2f78b90f9103b77f))
197
+ * **gate:** a malformed record in the merged review's own epic no longer stops the merge ([24eec39](https://github.com/abdelrahmannasr/yadflow/commit/24eec393e6b8ddbdefe71944c0045bbccda2dc16))
198
+ * **gate:** a round keeps the fingerprint it opened with; one spelling across approvals and comments (E112 review 2) ([d7dbe57](https://github.com/abdelrahmannasr/yadflow/commit/d7dbe57d507f5c798236715e55b70ef42f273dbe))
199
+ * **gate:** a shared roster name is never matched by name; gate open stamps the old PR (E62) ([a2b15eb](https://github.com/abdelrahmannasr/yadflow/commit/a2b15eb0d4519a05abe77ebb2ff64b6039ce9ea9))
200
+ * **gate:** a short-lane review PR does not ask for a contract re-lock it cannot do ([4855f3a](https://github.com/abdelrahmannasr/yadflow/commit/4855f3afaf90a885d3e1ae1c4d1d133857d6d142))
201
+ * **gate:** an exact submission time beats the roster name table; usage and doctor follow the simulation ([4d2c55c](https://github.com/abdelrahmannasr/yadflow/commit/4d2c55c45c7409942287a1b8834f2c58da756e5d))
202
+ * **gate:** an exact submission time continues only that review's records, never the whole name ([beaa5e3](https://github.com/abdelrahmannasr/yadflow/commit/beaa5e35a3aa77e85207b00d271885bddbd69e39))
203
+ * **gate:** approve keeps the review record; one spelling per person; a round is one version (E112 review) ([6f44c18](https://github.com/abdelrahmannasr/yadflow/commit/6f44c1887ae2c846bdcd1c14cf276624a2be91b6))
204
+ * **gate:** claim and keep older records per review, so a closed step never deletes the other person's history ([1ed2070](https://github.com/abdelrahmannasr/yadflow/commit/1ed2070779055ccf610c0ad0012978183c7b08d0))
205
+ * **gate:** close the gaps the E18 review found ([69aa2cf](https://github.com/abdelrahmannasr/yadflow/commit/69aa2cfcf88db681dfb08cc89a200ef58a23a88a))
206
+ * **gate:** close the holes the E76 review found ([e460fb2](https://github.com/abdelrahmannasr/yadflow/commit/e460fb21f8efd9eb34ef1569361973a8297f3321))
207
+ * **gate:** eighth review round — "after the cap", one dead branch, two comments (E73) ([62e47c3](https://github.com/abdelrahmannasr/yadflow/commit/62e47c3181908e49bc69407775b51ad49951f083))
208
+ * **gate:** fifth review round — an approval anywhere is evidence, and every what-if line is conditional (E73) ([5b78858](https://github.com/abdelrahmannasr/yadflow/commit/5b788587187cdce397d36bb9efdbd772cadaaefc))
209
+ * **gate:** fourth review round — the floor wording on every surface, and a cap only ever lowers (E72) ([81dc0d8](https://github.com/abdelrahmannasr/yadflow/commit/81dc0d866118b167ca18d40531abf3ba53a856e8))
210
+ * **gate:** fourth review round — two kinds of line, each said once, and the GitLab gate bot is not a person (E73) ([622c6d6](https://github.com/abdelrahmannasr/yadflow/commit/622c6d66d35df22fde619e09cd69c0dc6de97e3d))
211
+ * **gate:** keep people under a shared roster name apart; read the PR number from its own segment ([b30ba90](https://github.com/abdelrahmannasr/yadflow/commit/b30ba9051a8a4d291b70bad18f47807ac4fee21b)), closes [#2048](https://github.com/abdelrahmannasr/yadflow/issues/2048)
212
+ * **gate:** old approvals stay with their person in every platform order (E62 review) ([8379656](https://github.com/abdelrahmannasr/yadflow/commit/83796566ca4f35452e717b63b9f08c7caf081d4f))
213
+ * **gate:** recognise old approvals exactly, and never pass one that is stale (E62 review) ([58fe6d2](https://github.com/abdelrahmannasr/yadflow/commit/58fe6d295dbfaa795f771c79e1be1f6f0a052800))
214
+ * **gate:** review round — the names check needs a login, and sees a team of one that reads as two (E73) ([65512d0](https://github.com/abdelrahmannasr/yadflow/commit/65512d0decc079c0a76867b8b05065fe3baef37f))
215
+ * **gate:** round-2 review — singular in open-pr's cap, and doc/test wording that still read as enforced (E72) ([64323b0](https://github.com/abdelrahmannasr/yadflow/commit/64323b0695792c7c9e6dc6ccc97fb56f516ff76a))
216
+ * **gate:** second review round — the silent-path test compares ledgers; doc conditions stated whole (E73) ([5580624](https://github.com/abdelrahmannasr/yadflow/commit/5580624d87dcf685eba6cdb2403ffce112b28974))
217
+ * **gate:** seventh review round — the smallest team is the larger of the logins and the names (E73) ([bcbdb32](https://github.com/abdelrahmannasr/yadflow/commit/bcbdb32d3a1d8646999e183aed3b67a481a3ad7d))
218
+ * **gate:** show the capacity cap and hold on the base alone until E73 (E72) ([3da8498](https://github.com/abdelrahmannasr/yadflow/commit/3da849895011ff19d1368499d825a2b9723a5583))
219
+ * **gate:** sixth review round — "no approval" names the window, and a name is "not matched to a login" (E73) ([d592818](https://github.com/abdelrahmannasr/yadflow/commit/d592818b24d4e78d9bf3563398a45fef87447d92))
220
+ * **gate:** the login stamp merges only proven reviews and never stops a merge ([5c80ce9](https://github.com/abdelrahmannasr/yadflow/commit/5c80ce95a0852fcb2d593c0edf7aac80d54f50fd))
221
+ * **gate:** the product-level move waits for its review, a clean checkout, and the default branch ([91193be](https://github.com/abdelrahmannasr/yadflow/commit/91193be19f652db23f6229026db9d81df0f5db4b))
222
+ * **gate:** the review-PR body is the one surface where the count LASTS, so the line dates itself ([6b378fc](https://github.com/abdelrahmannasr/yadflow/commit/6b378fc28a23543da2b67bc1bf27f07f29bded46))
223
+ * **gate:** third review round — no cap on a shortcut pass, one copy of the cap's words (E72) ([81d86c8](https://github.com/abdelrahmannasr/yadflow/commit/81d86c86cea311a66c6658ac951371cc82b9e405))
224
+ * **gate:** third review round — the silent-path test compares the PR records too; one prefix on every site (E73) ([7b3d874](https://github.com/abdelrahmannasr/yadflow/commit/7b3d874c207f103479dc5df84a398cec1ca9fbf4))
225
+ * **history:** a printed [@word](https://github.com/word) is always a real login; GitLab defaults only for an ownerless entry (E68 review 4) ([cadd82b](https://github.com/abdelrahmannasr/yadflow/commit/cadd82bf43c8adecde2aa5aab1dc156f7b7bf708))
226
+ * **history:** count as the gate counts; keep a thread's root; print every field safely (E20 review 2) ([a539bfc](https://github.com/abdelrahmannasr/yadflow/commit/a539bfc595d22bd5e574e04b02d7f1fbcd2efae6))
227
+ * **history:** follow the real thread, print only safe text, judge approvals as gate status does (E20 review) ([2654480](https://github.com/abdelrahmannasr/yadflow/commit/265448010a526656ef818f710ed2e7e63e7f682c))
228
+ * **history:** name an approver by the gate's test; refuse every flag it does not take (PR review 2) ([406dce6](https://github.com/abdelrahmannasr/yadflow/commit/406dce685068993e7e187dbd76e107c6897f0468))
229
+ * **history:** second-review findings for E68, and E67's address-shaped name ([86e34c0](https://github.com/abdelrahmannasr/yadflow/commit/86e34c025dd37e397f16e22fac35485cf52ccaa6))
230
+ * **history:** the whole-PR review — strict settings, JSON refusals, shape done, exact search (E20) ([e9e13ed](https://github.com/abdelrahmannasr/yadflow/commit/e9e13ed4202c723fe3563be4cd254981ecdeb14c))
231
+ * **history:** waive a step by the gate's own test, not its final state (E20 review 3) ([dd5665e](https://github.com/abdelrahmannasr/yadflow/commit/dd5665ede9f4fec14a2b20425e5a59e12cf78009))
232
+ * **hook:** fail open under sh -e, follow no GIT_DIR, and name the repair that commits (E48 review 1) ([2991086](https://github.com/abdelrahmannasr/yadflow/commit/29910861d1c76763f765b2483ea412e8eba5d899))
233
+ * **hooks:** advice for a stuck old entry that is true in every case (E113 review 7) ([6d7fff1](https://github.com/abdelrahmannasr/yadflow/commit/6d7fff14a4a3d5bd1cb99b5bd0484cd292a0f109))
234
+ * **hooks:** give a local-ledger guard entry advice that works at apply too (E113 review 6) ([d26b241](https://github.com/abdelrahmannasr/yadflow/commit/d26b241af186961a40ca50dac289e3d6e230e1f8))
235
+ * **hooks:** judge an old hook script against the files as this run leaves them (E113 review 2) ([9a5df22](https://github.com/abdelrahmannasr/yadflow/commit/9a5df224c6e7322a6aebcc9a78b57afee1a2f59a))
236
+ * **hooks:** keep an old hook script until its new entry is committed (E113 review 1) ([c4fb5b3](https://github.com/abdelrahmannasr/yadflow/commit/c4fb5b37e3171604be7376e793cebd0eb194f14b))
237
+ * **hooks:** name what keeps an old hook script, and read HEAD once (E113 review 3) ([f1b95fc](https://github.com/abdelrahmannasr/yadflow/commit/f1b95fc2f135c5f4572d9e21b32e614a1ef77565))
238
+ * **hooks:** one sentence of advice for a stuck old hook entry, at plan and apply (E113 review 5) ([ab22b93](https://github.com/abdelrahmannasr/yadflow/commit/ab22b9348b659130fc1237786a4d6766919a580f))
239
+ * **hooks:** tell a capture-off Product to remove a stuck capture entry (E113 review 8) ([353053a](https://github.com/abdelrahmannasr/yadflow/commit/353053a017c5a0dad46c881abead93d65a9a704b))
240
+ * **hooks:** tell a local-ledger Product to remove a stuck guard entry (E113 review 4) ([0e1eaa5](https://github.com/abdelrahmannasr/yadflow/commit/0e1eaa5009f8cd06c39832faa9642ece7881e17b))
241
+ * **hook:** the agent's refusal gets the same fixes, and doctor names a hook git skips (E48 review 2) ([9551b1a](https://github.com/abdelrahmannasr/yadflow/commit/9551b1a4166bd4174a6a35f6655bbf5e805d3b90))
242
+ * **hub-bridge:** the gate-sync fragments ship the major their release publishes ([01ac858](https://github.com/abdelrahmannasr/yadflow/commit/01ac8587d5affc4e0f87c27f935b18f1342683c5))
243
+ * **index:** clean a title before unquoting it; drop bidi controls (E111 review 4) ([5ff9755](https://github.com/abdelrahmannasr/yadflow/commit/5ff97552f2af139c9634e2d398f79089ecc271a0))
244
+ * **index:** commit the index only when git holds exactly what it read (E19 review) ([1b354bc](https://github.com/abdelrahmannasr/yadflow/commit/1b354bcf4a5881aa9c74cdc028dec2562bc8418e))
245
+ * **index:** drop control characters from a title (E111 review 3) ([65ac5f7](https://github.com/abdelrahmannasr/yadflow/commit/65ac5f7c567c041c2cb027676440698ddf9e1078))
246
+ * **index:** read a double-quoted title with JSON's escapes; pin every title rule (E111 review 2) ([0a6b820](https://github.com/abdelrahmannasr/yadflow/commit/0a6b82081d63f26953c54a67af14b31ccf164674))
247
+ * **index:** read a YAML-quoted title as YAML does, keep it one line (E111 review) ([972920f](https://github.com/abdelrahmannasr/yadflow/commit/972920ffa7e462da8d79ec747060fa57d9d82b83))
248
+ * join stays inside the workspace on disk, one bad entry fails alone, and init never takes over a code repo (E79 review 1) ([56f14ae](https://github.com/abdelrahmannasr/yadflow/commit/56f14ae7f90f4eddd6618bcf6a6f7e23947e850e))
249
+ * keep every URL form's host and user to safe characters (E81 review 6) ([61370c2](https://github.com/abdelrahmannasr/yadflow/commit/61370c28a911f4d39223a6eee2df6affc27415d7))
250
+ * keep the rename's own error when writeJSON's cleanup fails (E81 review 20) ([d5b860f](https://github.com/abdelrahmannasr/yadflow/commit/d5b860f66fce3e0c99739327e8662af49ba2fed7))
251
+ * keep writeJSON's own error when the temp cleanup fails (E81 review 19) ([b8d7640](https://github.com/abdelrahmannasr/yadflow/commit/b8d7640abc5b6fde91ef0c45a05e976c134912b4))
252
+ * ledger-guard reads a missing settings file quietly, and the roster hints name the file (E122 review 5) ([d00a117](https://github.com/abdelrahmannasr/yadflow/commit/d00a117d6cd535255b44b0ec3e61a38aa1774169))
253
+ * **ledger:** the lock loop could never give up — two `continue`s skipped the cap and the sleep ([e66eab6](https://github.com/abdelrahmannasr/yadflow/commit/e66eab61910eb3b4bd7c3f9ba50f9fa9c39b5fa9))
254
+ * **lifecycle:** place an epic in Build, and keep the discovery epic off the ladder ([1c01e0c](https://github.com/abdelrahmannasr/yadflow/commit/1c01e0c8cf7aa2410b12969e43e5e45b5402edf2))
255
+ * **migrate:** name every file the apply writes, and repair a half-made pair ([a3211e3](https://github.com/abdelrahmannasr/yadflow/commit/a3211e3dfc246bbe89ef3bc322fa6be29bd735bb))
256
+ * **migrate:** the --json preview names the product config's mirror partner ([1eb4738](https://github.com/abdelrahmannasr/yadflow/commit/1eb4738c64899db78fad46036603e2fc7b71f99c))
257
+ * **mode:** close the gaps the E10 review found ([afbeca4](https://github.com/abdelrahmannasr/yadflow/commit/afbeca4599f379e0e815a3bb48e253461f9d931a))
258
+ * **mode:** only a login's approval proves a second person; one wiring for the suggestion (E74) ([0bd132f](https://github.com/abdelrahmannasr/yadflow/commit/0bd132f7664645f56dcb182c29721f7a94713245))
259
+ * name a repos.json that does not parse instead of joining with no repos (E79 review 5) ([4a952e2](https://github.com/abdelrahmannasr/yadflow/commit/4a952e2dd80ea36b33aaa37c051da1f702980585))
260
+ * name the file in the last settings hints, refuse a pair that changed, and silence a missing settings file (E122 review 4) ([5aed634](https://github.com/abdelrahmannasr/yadflow/commit/5aed63409178e36954240e37ee11e53b1ab95e04))
261
+ * name the Product from the workspace folder instead of offering a second one, and match paths as the disk stores them (E80 review 2) ([71369b3](https://github.com/abdelrahmannasr/yadflow/commit/71369b3565d273ad6a2f6eb3bd3caa8f685e75f5))
262
+ * name the settings file a person should edit, and settle all pairs or none (E122 review 2) ([ccb8de4](https://github.com/abdelrahmannasr/yadflow/commit/ccb8de49a48397c14446faebf8c3d7ef1222abd5))
263
+ * name the settings file actually read, and keep risk-map advisory (E122 review 1) ([ab4fddc](https://github.com/abdelrahmannasr/yadflow/commit/ab4fddc495433cff0d013742f02086bea94b00a9))
264
+ * name the settings file on disk, and restore the old-name fallback (E124 review 1) ([cf24871](https://github.com/abdelrahmannasr/yadflow/commit/cf248716935eaebc9961ae8e9f8d8b27a123a9d0))
265
+ * never build a login command from a host that is not a plain host name (E81 review 13) ([0a09dc1](https://github.com/abdelrahmannasr/yadflow/commit/0a09dc11e047e483ea046720a9e505078e815ae5))
266
+ * never clone or register a repo path through a .git folder, and say what --dir is for each workspace verb (E79 review 2) ([6be43a2](https://github.com/abdelrahmannasr/yadflow/commit/6be43a274b392c405454d1a09d4f49143257d100))
267
+ * never write over an edited new name, keep one workflow running, and name a gate that rejects product (E123 review 1) ([d7dc72b](https://github.com/abdelrahmannasr/yadflow/commit/d7dc72bf0857ceda09db081be1b95647a20334c2))
268
+ * **next:** an off-route step is not an unknown one, and a phase is not a passed one ([7f08da2](https://github.com/abdelrahmannasr/yadflow/commit/7f08da218463caa7f630a464ba0423bba145c746))
269
+ * one plainHost test for every login command doctor prints (E81 review 14) ([8a25d94](https://github.com/abdelrahmannasr/yadflow/commit/8a25d947353538ce7b0ffe0f399d08082e791bab))
270
+ * one samePath for a git path against a Node path, and survive a missing .git/hooks (E48 review 5) ([156ec1e](https://github.com/abdelrahmannasr/yadflow/commit/156ec1e4d9d19e5cd22e454432b1eece6fac6ced))
271
+ * one terminal cleaner for every module that prints registry text (E81 review 12) ([805a4fd](https://github.com/abdelrahmannasr/yadflow/commit/805a4fd200c2465f9a491f44e81b60ed50605946))
272
+ * only the ledger door runs from a subfolder, and the sha — not an indent — keeps :: off a line (E49 review 3) ([9878423](https://github.com/abdelrahmannasr/yadflow/commit/987842384792905cbc15db429d5d3e3da76033e4))
273
+ * **open-pr:** no address, no cross-platform join, no quiet "nobody" (E68 review) ([0d7814e](https://github.com/abdelrahmannasr/yadflow/commit/0d7814e1021dfc73845e65e7403a6ea66d2f9b6d))
274
+ * **owners:** never fold an owner file; name off-chain files in doctor (E47 review 1) ([f23f606](https://github.com/abdelrahmannasr/yadflow/commit/f23f606f220aef583500c6f2a632ee8927307b6c))
275
+ * **people:** a mistyped future approval is not proof even beside a current commit (E74) ([c1b9d7c](https://github.com/abdelrahmannasr/yadflow/commit/c1b9d7c18963133fca92e2eaaa4fdcd76676986e))
276
+ * **people:** ask git for an absolute date, so the count really does read no clock (E71) ([e065734](https://github.com/abdelrahmannasr/yadflow/commit/e0657347462310ef315068a3e9f3ba52d08b2b0a))
277
+ * **people:** close the identity question — `source: 'bridge'` is the proof, and the keyspace is namespaced ([9e055d7](https://github.com/abdelrahmannasr/yadflow/commit/9e055d711a70c2a6b6798dc5f87ec8a53be45158))
278
+ * **people:** the review round — eleven ways a partial read still became a number ([edf858e](https://github.com/abdelrahmannasr/yadflow/commit/edf858e6d3b2f5bd29877fe04517d8bcd5c4cdc8))
279
+ * **people:** validate the date git hands back — a formatter is not a validator ([dc1249a](https://github.com/abdelrahmannasr/yadflow/commit/dc1249aeae31e107eec359494b95e2230a16a4eb))
280
+ * read any spelling of the profile mapping and branch, and never a comment (E123 review 3) ([67c3a55](https://github.com/abdelrahmannasr/yadflow/commit/67c3a559ae95dae1abae8f4561d5e04b073eca02))
281
+ * record the new name a kept rename installs, and say a profile gap only when it bites (E123 review 2) ([9c99014](https://github.com/abdelrahmannasr/yadflow/commit/9c990145a68596dddfa4c2534afae18f3615efda))
282
+ * refresh never writes through a .gitignore the Product commits as a link (E81 review 16) ([5d9a982](https://github.com/abdelrahmannasr/yadflow/commit/5d9a9822d73376c5f83a6fe880dd52adf075e67a))
283
+ * refresh stops at a linked .sdlc, --push included (E81 review 18) ([e79d64c](https://github.com/abdelrahmannasr/yadflow/commit/e79d64c503d3d96e8f1005b1560d4e815ecf2820))
284
+ * refuse a clone target with a link on its way, so a committed link cannot reach .git (E79 review 3) ([667d696](https://github.com/abdelrahmannasr/yadflow/commit/667d6964e9ceed75ce0ea1fb82b03d6cf7c324ea))
285
+ * refuse a control character anywhere in a registered git_url (E81 review 8) ([6edf593](https://github.com/abdelrahmannasr/yadflow/commit/6edf5937a094a827faf02454fa2f54803b0f2cd4))
286
+ * refuse any folder holding HEAD on the way to a registered subfolder (E81 review 2) ([0471334](https://github.com/abdelrahmannasr/yadflow/commit/04713341b8b3ea5ee55d59da82b9f818d6bfe2df))
287
+ * refuse encoded C1 and bidi characters; clean the last raw registry text (E81 review 9) ([7f7721b](https://github.com/abdelrahmannasr/yadflow/commit/7f7721b636fc19ed4736c6962ae3cd67726c3007))
288
+ * **release:** install an exact npm version, not npm@latest ([0bf8981](https://github.com/abdelrahmannasr/yadflow/commit/0bf89817da64f43f91fc281d42f76883c0f1a1ef))
289
+ * **release:** let a pre-release publish past its own test suite ([70286ce](https://github.com/abdelrahmannasr/yadflow/commit/70286ce833b300d02d2781ac589d727481f5e7eb))
290
+ * **release:** refuse to ship a file-shape change as anything but a major ([173dc9a](https://github.com/abdelrahmannasr/yadflow/commit/173dc9a76453b0e5e0ec2341ad05458b71d9a085))
291
+ * **release:** the release checks ask semantic-release what a commit releases ([c5de745](https://github.com/abdelrahmannasr/yadflow/commit/c5de7453ed41bb5a6bac514652a857b6db5d7f8a))
292
+ * **risk-map:** close ten review findings in the map, its check and its command ([aafc578](https://github.com/abdelrahmannasr/yadflow/commit/aafc578c43cc2282e5aa837f3f88768cd7e5e30d))
293
+ * **risk-map:** doctor's section sat under threadChecks' comment; stale comments and help alignment ([5258b54](https://github.com/abdelrahmannasr/yadflow/commit/5258b54f352ba1d0276bec098d766e233beee77a))
294
+ * **risk-map:** every pathspec is :(literal) — a map name describes a directory, it never tells git what to do ([6a4ef28](https://github.com/abdelrahmannasr/yadflow/commit/6a4ef28bb105b3129445cef925d420863b7f271b))
295
+ * **risk-map:** first-review findings — a quoted path, a move out, an older check, and a name's own spacing ([016ad87](https://github.com/abdelrahmannasr/yadflow/commit/016ad87d050b611d69b6fb7d48a850dfac17a2a7))
296
+ * **risk-map:** first-review findings — read the base map from any subfolder, and never exit 1 on a trailing comma ([e6ac49f](https://github.com/abdelrahmannasr/yadflow/commit/e6ac49f32f5944d2beddbe3adc0b1b4ee2ca3ed7))
297
+ * **risk-map:** four second-review findings in the PR check and the file list ([c5eb332](https://github.com/abdelrahmannasr/yadflow/commit/c5eb33293b9dde0bfc0509dbcba45e94116646b0))
298
+ * **risk-map:** second-review findings — a failing git step is "not counted", and the check runs from the repo root ([c51a882](https://github.com/abdelrahmannasr/yadflow/commit/c51a882bcac73561b216e936ff495158d050782a))
299
+ * **risk-map:** second-review findings — a newline in a file name, and a merge that hid a real author ([845a341](https://github.com/abdelrahmannasr/yadflow/commit/845a341e08495cfc81dc24998e7bd80190587a62))
300
+ * **risk-map:** third-review finding — a failing git ls-tree is "not counted", not "no map" ([efeffc0](https://github.com/abdelrahmannasr/yadflow/commit/efeffc0e4bf5edfadbcc2a67fbc6b6397e1a63c5))
301
+ * **risk-map:** third-review findings — bytes for every tool in the check, and only the map itself counts as deleted ([ac4569e](https://github.com/abdelrahmannasr/yadflow/commit/ac4569ec8dba85ea39a7659e8b6038e7a1025d89))
302
+ * **setup:** compare hook folders by their long name on Windows (E48) ([8f1ac56](https://github.com/abdelrahmannasr/yadflow/commit/8f1ac5617cf50b89ca8626e5d15ec645b2ff64a5))
303
+ * **setup:** keep a team's edit to .sdlc/config.yaml through yad update (E3) ([86b2034](https://github.com/abdelrahmannasr/yadflow/commit/86b20348a08bb0a82ce5de03bad0ec5347cbc15e))
304
+ * **setup:** read a core.hooksPath typed in another case as the default folder where the disk ignores case (E48 review 6) ([997f77d](https://github.com/abdelrahmannasr/yadflow/commit/997f77d39d76c49a7e5b63845c867484fb180437))
305
+ * **skills:** teach the skill layer that `ledger` is the switch ([d4622ab](https://github.com/abdelrahmannasr/yadflow/commit/d4622ab2293cfe49a36791f6cf51472b4d5701ad)), closes [#186](https://github.com/abdelrahmannasr/yadflow/issues/186)
306
+ * **skills:** the epic.md templates were unreadable by the gates they feed ([96922de](https://github.com/abdelrahmannasr/yadflow/commit/96922de4ae3e08efe8faee2cbff5abe6c468eabc))
307
+ * **skills:** the review gate must open the gate with the engine, not by hand ([f453509](https://github.com/abdelrahmannasr/yadflow/commit/f453509cbcdd0ec7fa9156af9324eb940846efb4))
308
+ * **skills:** yad-connect-repos frontmatter parses; two descriptions fit 1024 ([d6eaf55](https://github.com/abdelrahmannasr/yadflow/commit/d6eaf558d8296dbedacab3c70f9075d497222d56))
309
+ * **skip:** close the holes the E39 review found ([33eb17a](https://github.com/abdelrahmannasr/yadflow/commit/33eb17a85f982456549b225603db04747cd27d94))
310
+ * **skip:** close the holes the verified-skip review found ([311e1ca](https://github.com/abdelrahmannasr/yadflow/commit/311e1cab3f439fc3a4752d997bdb2260ac42bf47))
311
+ * **skip:** refuse a skip on a ledger CI owns on a verified Product ([b9b2d1a](https://github.com/abdelrahmannasr/yadflow/commit/b9b2d1a54f7a31deaf75746581beb3e217611555)), closes [#162](https://github.com/abdelrahmannasr/yadflow/issues/162)
312
+ * **state:** a corrupt ledger gets an error with a hint, not a stack trace ([2cda22d](https://github.com/abdelrahmannasr/yadflow/commit/2cda22d76328e373dfc46b072385b02715529b95))
313
+ * **state:** a gate write moves the recorded shape, not just the fields ([6906c57](https://github.com/abdelrahmannasr/yadflow/commit/6906c577251d96ddf583e5fb83dfb265eb985a86))
314
+ * **state:** a short lane has no optional steps, and that is not a broken chain ([136eec8](https://github.com/abdelrahmannasr/yadflow/commit/136eec83888d5915facdf80c9dd073ff56d95513))
315
+ * **state:** close the holes the E41 review found in re-open and debt ([9b8565e](https://github.com/abdelrahmannasr/yadflow/commit/9b8565e165869f5a6b10f5c46c887bc422ce78d2))
316
+ * **state:** keep the product-level role under BOTH spellings, and report drift ([1b9ac44](https://github.com/abdelrahmannasr/yadflow/commit/1b9ac441a6055f2b17422f11c0aee0a025c7b3ba))
317
+ * **state:** make the two names one file, in both directions ([0a842c7](https://github.com/abdelrahmannasr/yadflow/commit/0a842c74560d96c47064009b3ab4714f0f00ab7f))
318
+ * **state:** one rule for "this epic's route never had that step" ([b687048](https://github.com/abdelrahmannasr/yadflow/commit/b687048e49c7bcfa4f512c7e92de31e6dce8f0d7))
319
+ * **state:** read an unstamped file as shape 1, not as the engine's shape ([6d8c608](https://github.com/abdelrahmannasr/yadflow/commit/6d8c608215175fac98933ffee6f714471454a8d9))
320
+ * **state:** shape 6 stamps against the routes that existed when it landed ([939c862](https://github.com/abdelrahmannasr/yadflow/commit/939c86228b20540ad22c621c19b63e4859899647))
321
+ * **state:** the count reports, it does not hold a gate — yet (E7 review round) ([10bc3ff](https://github.com/abdelrahmannasr/yadflow/commit/10bc3ff06816ff6430bc47b8382363d57c6b9380))
322
+ * **state:** the review round — a live writer of `blocked` this change said did not exist ([7136b93](https://github.com/abdelrahmannasr/yadflow/commit/7136b930b10bba4e8ffe03d217e706409bd5153e))
323
+ * **state:** write the work-item type at the top of state.json, not the bottom ([195c03a](https://github.com/abdelrahmannasr/yadflow/commit/195c03aa96f5c12526b22d54c4db9ad9d4a4ef63))
324
+ * **test:** strip the publisher's git identity from the whole test process ([8660f56](https://github.com/abdelrahmannasr/yadflow/commit/8660f5611f1c9f24a67eeead4302c4acca260ba3))
325
+ * the --profile hub advice names every gate in the way, in every state (E124 review 4) ([5d125ec](https://github.com/abdelrahmannasr/yadflow/commit/5d125ece69967c3c76d923da2c05decd1c500140))
326
+ * the --profile hub advice reads each gate's real state (E124 review 3) ([f00c51e](https://github.com/abdelrahmannasr/yadflow/commit/f00c51e7a4ec54bb6c126797478088c06365d746))
327
+ * the --profile hub advice waits for a gate that refuses product, and a repo named product is shown by its path (E124 review 2) ([80518c5](https://github.com/abdelrahmannasr/yadflow/commit/80518c5cbd3af2209882167bb381731190d2336a))
328
+ * the clone sets GIT_ALLOW_PROTOCOL; a local source must exist (E81 review 5) ([7963220](https://github.com/abdelrahmannasr/yadflow/commit/796322023a6bc90b541f66b3c383e34b1957c791))
329
+ * the drift advice names yad migrate --apply, and one drift lookup serves all (review 1) ([f158fa1](https://github.com/abdelrahmannasr/yadflow/commit/f158fa1f8311a71e5346dbd51ee6627a231b3dae))
330
+ * the ledger override claims only what it can see, and no control character reaches the CI log (E49 review 1) ([da7a6d9](https://github.com/abdelrahmannasr/yadflow/commit/da7a6d96cf762e7d23f5f4ae3c44c5c2e9dc195d))
331
+ * the solo people count judges each registered path before git runs (E81 review 15) ([993698a](https://github.com/abdelrahmannasr/yadflow/commit/993698a17f2496985da6b8c6160c2e9eeba83449))
332
+ * the unreadable-registry warning gives the real reason, and a null registry is named too (E79 review 6) ([9f426eb](https://github.com/abdelrahmannasr/yadflow/commit/9f426eb3697e473bde80468e0be5946de4041404))
333
+ * the unreadable-settings cell says only what is true (E124 review 6) ([5d43189](https://github.com/abdelrahmannasr/yadflow/commit/5d431894e377065ca1d26316973fd6cfabc7d3c9))
334
+ * **thread:** an epic never owns an artifact its route has no step for ([6725c5a](https://github.com/abdelrahmannasr/yadflow/commit/6725c5ae9dde8e226f34ae1e1d5888fa86811641))
335
+ * **update:** install templates newly added to a wired repo on `yad update` ([8e8d92f](https://github.com/abdelrahmannasr/yadflow/commit/8e8d92f1265e2ed375bf0a53307270a25d8c33f3))
336
+ * **update:** take only yad's own wiring as proof a repo is wired ([3c90134](https://github.com/abdelrahmannasr/yadflow/commit/3c90134985eebb3b7faa91be2c45387d54851324))
337
+ * when a file's two names disagree, the gate advice says yad migrate first (E124 follow-up) ([75d2184](https://github.com/abdelrahmannasr/yadflow/commit/75d2184480acc0d285d7718533ab9bf9d65cf723))
338
+ * writeJSON's temp file is random and exclusive (E81 review 17) ([b5cbcd9](https://github.com/abdelrahmannasr/yadflow/commit/b5cbcd935a81534b5f749eeba13c36711fb7a471))
339
+
340
+
341
+ ### Documentation
342
+
343
+ * the guides, sites and diagram say Product, and a guide to the hand changes (E124) ([883cd6f](https://github.com/abdelrahmannasr/yadflow/commit/883cd6f56378dc58bbbd1a9ebdba0048a1e35c9a))
344
+
345
+
346
+ ### Features
347
+
348
+ * .yad-workspace.json — yad finds the Product from any repo in the workspace (E80) ([27a7579](https://github.com/abdelrahmannasr/yadflow/commit/27a75793c558d597840d01c9f7986e25e7a5c42a))
349
+ * **agents:** support agents beyond Claude Code, and guard Cursor too (E11) ([8481398](https://github.com/abdelrahmannasr/yadflow/commit/848139856c5d23cdf52b601d02f7155d5756d9b4))
350
+ * **capture:** yad capture snapshots Shape artifacts onto private yad/wip branches (E43) ([58b0181](https://github.com/abdelrahmannasr/yadflow/commit/58b0181f72fd88e97d391e0e52a46e8b5cdf1183))
351
+ * **checks:** check the Product out in CI where the record says (E120) ([b288326](https://github.com/abdelrahmannasr/yadflow/commit/b288326da2a72c3475d0cfafd2f8bc9540d0670d))
352
+ * **checks:** guard the Foundation ledger in foundation/ (E75) ([0608e41](https://github.com/abdelrahmannasr/yadflow/commit/0608e41f8a203a633b4ef2e3449711de9201890c)), closes [#162](https://github.com/abdelrahmannasr/yadflow/issues/162)
353
+ * **checks:** guard the Product index as CI-owned on a verified Product (E19) ([5396827](https://github.com/abdelrahmannasr/yadflow/commit/5396827650597341cd98e935c595c73899b4a61f))
354
+ * **checks:** read where the Product lives from .sdlc/product-link.json on the base (E120) ([6b9e7b1](https://github.com/abdelrahmannasr/yadflow/commit/6b9e7b1f293183b89fda9d1aa9b748bcd62bb7f6))
355
+ * **checks:** risk-map-check.sh warns on every PR where the risk map went stale ([bc2ada8](https://github.com/abdelrahmannasr/yadflow/commit/bc2ada8707a9499d5ef8afcb1e4259be02980eef))
356
+ * **claims:** yad claims — who else is editing which artifact, read from the capture branches (E46) ([6668441](https://github.com/abdelrahmannasr/yadflow/commit/66684416b5d3c1a2a04b069cd35b0d7f13e55ddb))
357
+ * **cli:** add `yad skill` to bind, list and unbind a step's skill ([7b4c9c6](https://github.com/abdelrahmannasr/yadflow/commit/7b4c9c6cdc2e5734a5f670b805003782d877674f))
358
+ * **cli:** the project chooses which skill runs a step (E6) ([a07746e](https://github.com/abdelrahmannasr/yadflow/commit/a07746e327056448f1c3566490cf7d17aa13122d))
359
+ * **cli:** warn before any command reads a project on a newer file shape ([f5695da](https://github.com/abdelrahmannasr/yadflow/commit/f5695da00299169f3bdb34913aa7c90448501510))
360
+ * **cli:** yad epic new — the engine writes an epic's lifecycle (E17) ([92e67d6](https://github.com/abdelrahmannasr/yadflow/commit/92e67d635efddcadbd8f4399dac27b0c56402cbe))
361
+ * **codeowners:** warn when CODEOWNERS is stale (E69) ([6c35d6a](https://github.com/abdelrahmannasr/yadflow/commit/6c35d6a2d854e089561b708c6441616117816cf6))
362
+ * **commit:** yad commit --manual --reason, the door past the ledger hook (E49) ([5b4081a](https://github.com/abdelrahmannasr/yadflow/commit/5b4081a5bea4423c90b41a5ad676e0c5987bf0d9))
363
+ * **defer:** yad defer --debt marks a deferral owed back, reminded until paid (E41) ([b20d57d](https://github.com/abdelrahmannasr/yadflow/commit/b20d57dc85abbb8509a6298bb5c98bff66cd827c))
364
+ * **defer:** yad defer and yad undefer set an optional step aside (E37) ([b6f2391](https://github.com/abdelrahmannasr/yadflow/commit/b6f2391df9feb0f9a0b9cf5af74eb928de138767))
365
+ * **dial:** yad dial, yad kill and yad unkill — the advance dial set freely (E34) ([56e8300](https://github.com/abdelrahmannasr/yadflow/commit/56e8300c37839f6a688d821f52ceee9ea682f219))
366
+ * **doctor:** keep the access cause open when GitLab names no default branch (E110) ([ddb8159](https://github.com/abdelrahmannasr/yadflow/commit/ddb8159c792e5bddb42fa135b68e25ab5774a073))
367
+ * **doctor:** name a leftover _bmad/sdlc/ folder (E3) ([5d7b1ab](https://github.com/abdelrahmannasr/yadflow/commit/5d7b1ab4632b5712226057a7d41a796070512bae))
368
+ * **doctor:** name the cause behind a GitLab branch 404 from its body (E109) ([64865d7](https://github.com/abdelrahmannasr/yadflow/commit/64865d71a8449453e05942f0dac69ec413b5e4c0))
369
+ * **doctor:** people:roster-unused says when the roster can go ([eb0c012](https://github.com/abdelrahmannasr/yadflow/commit/eb0c012963af43a15b62dc3c229cd32f7c791a3a))
370
+ * **doctor:** say whether each repo's branch requires an approval (E70) ([e93dd3b](https://github.com/abdelrahmannasr/yadflow/commit/e93dd3b7cbe4ed52fc1d9a9a7b91613c2bfe0cf8))
371
+ * **doctor:** warn checks:backfill-blind for an older backfill-check (E116) ([bfb82cf](https://github.com/abdelrahmannasr/yadflow/commit/bfb82cf2e0d956165c179a92a0e09fb46e8e97f9))
372
+ * **doctor:** warn when a step owner file does nothing (E47) ([b189abd](https://github.com/abdelrahmannasr/yadflow/commit/b189abdbc94aa0a36041d501b9cd09c5577d5a62))
373
+ * **engine:** lifecycle profiles, with today's chains written down (E5) ([44564d4](https://github.com/abdelrahmannasr/yadflow/commit/44564d44d826265138d6fdc1f5feee5ab5760988))
374
+ * **engine:** the step catalogue, validated in code (E4) ([c3823bf](https://github.com/abdelrahmannasr/yadflow/commit/c3823bf4bed067a91496fe79c8cd490088c9e71c))
375
+ * **epic:** `yad foundation new` — the engine seeds the Product level (E75) ([2cf2241](https://github.com/abdelrahmannasr/yadflow/commit/2cf2241556d8bfef4e6682460c51ab86319024e7))
376
+ * **epic:** the grouping theme tag (E31) ([bf8a31c](https://github.com/abdelrahmannasr/yadflow/commit/bf8a31c880c445dedd1b4abb78f6314971c1cacb))
377
+ * **epic:** yad epic new --parent seeds a threaded change-epic (E42) ([3786ae2](https://github.com/abdelrahmannasr/yadflow/commit/3786ae246ec9b5759de590c72a928e33e2ad7d96))
378
+ * **fold:** yad fold <epic> <step> — one clean commit per authoring step (E44) ([a4a5285](https://github.com/abdelrahmannasr/yadflow/commit/a4a52857c2536b83d954e6a313863ecb16ecf01d))
379
+ * **foundation:** yad foundation status reads roadmap features from the epic ledgers ([e6a4a85](https://github.com/abdelrahmannasr/yadflow/commit/e6a4a853b2f31204ed687b16f0bdba3dd68c245c))
380
+ * **gate:** approvals record the platform's evidence; GitLab's approval time is read ([0e16728](https://github.com/abdelrahmannasr/yadflow/commit/0e167282349f832128757caeda10200617b0a2d7)), closes [#156](https://github.com/abdelrahmannasr/yadflow/issues/156)
381
+ * **gate:** cap the approval count at the active people less one, and record every cap (E72) ([f99e77d](https://github.com/abdelrahmannasr/yadflow/commit/f99e77da98484623d6ed1cb270dcc1dea3a08c1f))
382
+ * **gate:** every surface that reports a gate prints the arithmetic ([0ac5617](https://github.com/abdelrahmannasr/yadflow/commit/0ac56179cd49ab3d66ee2e8642500cd3f420e27c))
383
+ * **gate:** print how many people there are to ask, on every surface a gate reports itself (E71) ([cfabed9](https://github.com/abdelrahmannasr/yadflow/commit/cfabed9521d431b043ab356b46f9f54ec306a005))
384
+ * **gate:** record how a step closed (E18) ([a1c9050](https://github.com/abdelrahmannasr/yadflow/commit/a1c905037061437ecdf6183df26f246cb8cb049b))
385
+ * **gate:** record the platform login on older records while the roster exists ([cc7b02f](https://github.com/abdelrahmannasr/yadflow/commit/cc7b02f36658c5517fcc49b3f464ca1cfeeff048))
386
+ * **gate:** rename the PR ledger too, and guard both names ([c0b8b00](https://github.com/abdelrahmannasr/yadflow/commit/c0b8b00bdf77203346127984f67cce95206ba054))
387
+ * **gate:** say on the closing record when solo mode waived the approvals (E10) ([f733e5e](https://github.com/abdelrahmannasr/yadflow/commit/f733e5e10a9b8ae3c6255e4e724122e9346ac64b))
388
+ * **gate:** say when a gate may not be met — reported, never enforced (E73) ([444b67c](https://github.com/abdelrahmannasr/yadflow/commit/444b67c0e77087d286fab60bd853e1f3272320c0))
389
+ * **gate:** the gate bot converts a verified Product's product level to foundation/ ([ad3bc94](https://github.com/abdelrahmannasr/yadflow/commit/ad3bc94b0a373bd131bb1609afd6cac610aeeef8))
390
+ * **gate:** warn when a Foundation section still holds only its template (E76) ([8a5be38](https://github.com/abdelrahmannasr/yadflow/commit/8a5be38404bcb022cf9e98b10d529815d6bc4ad4))
391
+ * **gate:** yad gate approve, comment and advance for a Product with no platform (E112) ([50f7618](https://github.com/abdelrahmannasr/yadflow/commit/50f7618aae85fb269578055e5e12d33e58643fab))
392
+ * **history:** yad history — list, show, search, all with --json (E20) ([c37c9fe](https://github.com/abdelrahmannasr/yadflow/commit/c37c9fe8c346855c3a04d6921438ccaade336d3f))
393
+ * **hook:** refuse a hand commit to the CI-owned ledger with a git pre-commit hook (E48) ([e2258b1](https://github.com/abdelrahmannasr/yadflow/commit/e2258b14f9c35af5057e109713c6407fae50b068))
394
+ * **hooks:** run the agent hooks as Node scripts, so Windows works without WSL (E113) ([887ceea](https://github.com/abdelrahmannasr/yadflow/commit/887ceeadabdb4f20482c3f3a5d29963c5fe74cc8))
395
+ * **index:** `yad index` rebuilds the front door on the default branch (E19) ([5b6dfd6](https://github.com/abdelrahmannasr/yadflow/commit/5b6dfd6f3ae01a5f9409fb63e59f32dad5ab429d))
396
+ * **index:** a title for every work item, carried by the Product index (E111) ([7ab7833](https://github.com/abdelrahmannasr/yadflow/commit/7ab78334eab64153e5d5e7a31939416ff4224f19))
397
+ * **index:** build the Product index from every work item's own files (E19) ([5024d61](https://github.com/abdelrahmannasr/yadflow/commit/5024d61807a4354c6969dedf1d0d87aa01e318c2))
398
+ * **index:** the gate, CI and migrate keep the index; doctor says when it is behind (E19) ([97aba2b](https://github.com/abdelrahmannasr/yadflow/commit/97aba2be1d3c934548c195a5d8b6b1647ba8910b))
399
+ * **lifecycle:** name the six phases, derived from the step ([1b77249](https://github.com/abdelrahmannasr/yadflow/commit/1b77249c197ca70df7f95270004ca94a6b930d6a))
400
+ * **mode:** suggest team mode when the count disagrees with solo (E74) ([4756ef9](https://github.com/abdelrahmannasr/yadflow/commit/4756ef92ecedfe0dda0e5bfa3f2785a10ac6424a))
401
+ * **mode:** yad mode solo|team sets who must approve, and records the change (E10) ([ce4077c](https://github.com/abdelrahmannasr/yadflow/commit/ce4077c5055812f61736924c2f76c903acd6db66))
402
+ * **open-pr:** suggest reviewers from history and CODEOWNERS (E68) ([9214ed9](https://github.com/abdelrahmannasr/yadflow/commit/9214ed90123d55ea1fed59541df9148b0b322ed9))
403
+ * **owners:** assign an authoring step to one person (E47) ([f9f9bda](https://github.com/abdelrahmannasr/yadflow/commit/f9f9bdaf31206d8ac4c7d46b4d512f23b1e816d2))
404
+ * **people:** count active people live, three windows, unknown is never a small number (E71) ([1b186a0](https://github.com/abdelrahmannasr/yadflow/commit/1b186a0125f3b5a1ece5edc85521e0b58596fd59))
405
+ * **platform:** a record names the login gh/glab reports, not the roster's (E62) ([6c2ef4e](https://github.com/abdelrahmannasr/yadflow/commit/6c2ef4ee4df6da9e8f9000055e1aa32359ded0bc))
406
+ * **repos:** write each code repo's product-link record, and warn when it is missing (E120) ([54f1fe3](https://github.com/abdelrahmannasr/yadflow/commit/54f1fe382d884aa2e72bb56c26197dd3e8e3c5c0))
407
+ * **risk-map:** a directory to risk-level map per code repo, with yad risk-map check|draft and a doctor section ([f3d8115](https://github.com/abdelrahmannasr/yadflow/commit/f3d811547360381409560583cce2e601f1e73cc4))
408
+ * **risk-map:** a high directory asks for an approver who has worked there lately (E67) ([28f4e58](https://github.com/abdelrahmannasr/yadflow/commit/28f4e58903432d4bb1cfa7e45529ad65f840c9b6))
409
+ * **risk-map:** a high directory on the base branch's map adds the high step (E66) ([ad6fcac](https://github.com/abdelrahmannasr/yadflow/commit/ad6fcaca496c7dbc377268a9771bdf18b3737e91))
410
+ * **setup:** install the module config into .sdlc/, not _bmad/sdlc/ (E3) ([da18dac](https://github.com/abdelrahmannasr/yadflow/commit/da18dacc1b02c9dba9f1079aeb26c89286805137))
411
+ * **setup:** let a scripted setup choose its agent directories ([8c13a06](https://github.com/abdelrahmannasr/yadflow/commit/8c13a0672a231b70646501a8b780da85bf503ff6))
412
+ * **skills:** the epic and change templates carry a theme ([8b0c71d](https://github.com/abdelrahmannasr/yadflow/commit/8b0c71ddeaec9ea189e663644f7353a1a3c8246a))
413
+ * **skills:** the skills call the engine instead of writing state.json (E17b) ([f0e0d77](https://github.com/abdelrahmannasr/yadflow/commit/f0e0d77eb97ae20a929f04d5bb4d947546c3d4bc))
414
+ * **skip:** yad skip <epic> <story> --repo skips a whole Build lane (E39) ([261e73e](https://github.com/abdelrahmannasr/yadflow/commit/261e73e360bb31cc35272d7c4f6a06394b713515))
415
+ * **skip:** yad skip and yad unskip name no step (E36) ([abbb4e0](https://github.com/abdelrahmannasr/yadflow/commit/abbb4e080fc2c21c61776f555a5b1c66e2359b53))
416
+ * **state:** a chore lane and a spike lane (E40) ([f521c22](https://github.com/abdelrahmannasr/yadflow/commit/f521c22487e5ad44b029e977ae6716925f4ec731))
417
+ * **state:** a Shape author step is not a gate because it is locked (E34) ([298546e](https://github.com/abdelrahmannasr/yadflow/commit/298546ef6ef67ea1c42cf01178aecc494bd938ef))
418
+ * **state:** a step is optional because the epic's ROUTE says so (E35) ([1641b46](https://github.com/abdelrahmannasr/yadflow/commit/1641b46e6fd3b57526862ce4448c4506ccdce4ec))
419
+ * **state:** a step's gate says how many people it needs (E7) ([314e709](https://github.com/abdelrahmannasr/yadflow/commit/314e70982a0b61927c0a379516d4233c08260b99))
420
+ * **state:** every ledger walker finds the Foundation (E75) ([bf86753](https://github.com/abdelrahmannasr/yadflow/commit/bf867537d17150633faa5a9014df2c4b1e59238c))
421
+ * **state:** give the product settings their new name, keeping the old one beside it ([8d0cf1b](https://github.com/abdelrahmannasr/yadflow/commit/8d0cf1b500a6a15fcbb5e53b7806966bf1457a90))
422
+ * **state:** record who writes the ledger as `ledger: verified | local` ([6623199](https://github.com/abdelrahmannasr/yadflow/commit/66231997156bb1ffa446ebb5edd28d8ebf8def91)), closes [#186](https://github.com/abdelrahmannasr/yadflow/issues/186)
423
+ * **state:** the Product level — Foundation in the model (E75) ([676bbd1](https://github.com/abdelrahmannasr/yadflow/commit/676bbd1ae4557e0c4eb744f62f75ada74969b36b))
424
+ * **state:** the step-state model, and shape 7 writes it (E38) ([4064067](https://github.com/abdelrahmannasr/yadflow/commit/40640673adae5f2065041d92d431fdda522b6b32))
425
+ * tell a repo named product apart, and name --profile hub in the team's workflows (E124 review 1) ([98fc15d](https://github.com/abdelrahmannasr/yadflow/commit/98fc15d345354c0df83ceae7d7aa4db5765c02b2))
426
+ * **unblock:** yad unblock clears a recorded blocker (E37) ([5ba73f5](https://github.com/abdelrahmannasr/yadflow/commit/5ba73f560923fcf297ab460a82cca26ee2c1feeb))
427
+ * **update:** name an edited gate-sync fragment left on another major ([b33f9e6](https://github.com/abdelrahmannasr/yadflow/commit/b33f9e61c51101f2e5ebb9756e185ece3ce7de74)), closes [#164](https://github.com/abdelrahmannasr/yadflow/issues/164)
428
+ * yad new, yad init and yad join — the three ways into a workspace (E79) ([dcccf67](https://github.com/abdelrahmannasr/yadflow/commit/dcccf670ffb4cb376aba6af26e602140328c00ea))
429
+ * yad repo clone fetches registered repos missing on this machine (E81) ([8a20504](https://github.com/abdelrahmannasr/yadflow/commit/8a20504f816ec556e55ec5db41b8f4350973e283))
430
+
431
+
432
+ ### BREAKING CHANGES
433
+
434
+ * after `yad update` renames the installed CI names, a
435
+ team's own files that name the old ones must be changed by hand — GitLab
436
+ `needs:` / `dependencies:` / `extends:` / `!reference` naming a
437
+ `yad-hub-*` job, GitHub `workflow_run:` triggers naming `yad-hub-checks`,
438
+ status badges, CODEOWNERS lines, and scripts that read `--json` names or
439
+ `SDLC_HUB_CONFIG` / `.sdlc/hub.json`. Every case, with a before and
440
+ after: docs/migrations/hub-to-product.md.
441
+ * `--json` names that said `hub` now say `product`, and
442
+ `jsonVersion` is 2. `yad doctor` check ids `hub`, `hub-git-url` and
443
+ `ci-tags:hub` are `product`, `product-git-url` and `ci-tags:product`;
444
+ `yad open-pr` answers `baseSource: "product"` and `stage:
445
+ "product-shape" | "product-tooling"`; `yad check` / `yad update` answer
446
+ `items[].scope: "product"` and `commits[].label: "product"`; and
447
+ `yad history show` answers `productConfigWhy` where it answered
448
+ `hubWhy`. The audit commits are `chore(product): …`. See the
449
+ "What moved in jsonVersion 2" table in docs/CLI.md.
450
+ * `yad update` renames the Product's
451
+ .github/workflows/yad-hub-checks.yml and .gitlab/ci/yad-hub-checks.yml to
452
+ yad-product-checks.yml, the GitLab jobs yad-hub-* to yad-product-*, and
453
+ the yad-hub-bridge skill to yad-product-bridge. GitHub job names (the
454
+ required checks) do not change. Your own CI that names an old name — a
455
+ GitLab needs:/dependencies:/extends:/!reference, a GitHub workflow_run:
456
+ trigger on yad-hub-checks, a status badge, a CODEOWNERS line — must be
457
+ changed by hand; `yad doctor` lists each by file and line (renamed-ref:).
458
+ * yadflow 4 reads .sdlc/product.json (and each epic's
459
+ product-prs.json) first; .sdlc/hub.json and hub-prs.json are read only when the
460
+ new name is absent, are still written until 5.0, and are deleted in 5.0. This
461
+ corrects docs/migrations/shape-3.md and the 4.0.0-next.1 notes, which said the
462
+ old names stay the ones read for another major. When both names exist and say
463
+ different things, every command refuses (YAD-STATE-008) and the gates fail;
464
+ run `yad migrate` to see the difference and `yad migrate --apply` (or
465
+ `--apply --keep product|hub`) to choose. Edit settings by hand in
466
+ .sdlc/product.json, then run `yad migrate --apply --keep product`. Gates now
467
+ honour SDLC_PRODUCT_CONFIG before SDLC_HUB_CONFIG.
468
+ * `yad docs build`, `yad docs deploy` and
469
+ `yad docs sync --refresh` now exit 1 when a site's npm install or build
470
+ fails, or when a site named with --epic/--overview was never generated;
471
+ `yad docs build` also exits 1 when npm is not on PATH. Under --json these
472
+ are refusals (`ok: false`) naming the site. A script that ran them and
473
+ ignored build failures will now stop.
474
+ * every `--json` answer is now the E1 envelope. `yad
475
+ history --json` carries `jsonVersion` instead of `schemaVersion`; `yad
476
+ thread --json` and the review bundles gain `ok`; `yad usage --json`
477
+ wraps the model (`--format json` still prints the bare model); a refusal
478
+ always has `error`, `code` and `hint`; `warnings` is always present. The
479
+ full list is in docs/CLI.md, "--json on every command".
480
+ * the ROUTE line of risk-route.sh and hub-route.sh
481
+ changed; anything parsing it must be updated.
482
+ * in a repo whose refreshed gate has landed, a Verified
483
+ commit from an email nobody listed now passes CI.
484
+ * `yad roster` is removed, and `yad setup` no longer
485
+ collects reviewers or repo owners.
486
+ * `yad usage --json` members carry no `role` or `rostered`,
487
+ and the `dormant` and `reviewer-not-reviewing` flags are no longer raised.
488
+ * review and task PRs no longer request reviewers
489
+ automatically.
490
+ * the owner/reviewer/domain-owner rule no longer holds a
491
+ team gate; one approver does. `defaultReviewers` and the roster shape
492
+ check are gone.
493
+ * file shape 10. An older yadflow reading a chain with a
494
+ re-opened step names that step the blocker of the work after it, and
495
+ re-opens that work when its review passes. See docs/migrations/shape-10.md.
496
+ * file shape 9. An older yadflow fingerprints the whole
497
+ file, so it reads every approval this release records on a file with a
498
+ `status:` line as stale. On a local ledger with mixed versions, that
499
+ holds an open gate for the teammate on the older release. Upgrade
500
+ everyone on the project together. A verified project runs
501
+ `yad migrate --apply` and commits the result; CI brings each state.json
502
+ to shape 9 at its next write.
503
+ * file shape 8. A migrated project keeps its product level
504
+ in `foundation/`, which a 3.x yadflow does not read. Upgrade everyone on
505
+ the project together. On a verified Product, run `yad update` so the
506
+ committed checks guard `foundation/`.
507
+ * **state:** shape 7 is the first file shape that changes a value in place
508
+ rather than adding a key beside an old one, so a 3.x CLI cannot read a migrated
509
+ project: it sees `todo` as an unknown status and reads `skipped` / `satisfied` as
510
+ "not done", which makes a UI-less epic or a change-epic look stuck. This release
511
+ reads every pre-shape-7 project correctly; run `yad migrate --preview` first and
512
+ upgrade everyone on the project. See docs/migrations/shape-7.md.
513
+
514
+ Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
515
+ * file shape 5. Run `yad migrate` to preview, then
516
+ `yad migrate --apply`. See docs/migrations/shape-5.md.
517
+ * project files change shape twice in this release, and both are
518
+ handled by one command. Shape 2 records who writes the ledger as
519
+ `"ledger": "verified" | "local"` in the product settings; shape 3 renames those
520
+ settings from `.sdlc/hub.json` to `.sdlc/product.json`, renames each epic's
521
+ `hub-prs.json` to `product-prs.json`, and gives every reviewer's product-level
522
+ role a second spelling. Nothing is taken away: every old name is still written
523
+ and is still the one read, so a check gate committed in your repository keeps
524
+ working whether or not you have run `yad update`. Run `npx yadflow@<version>
525
+ migrate` to preview — it writes nothing — then `yad migrate --apply`, which backs
526
+ up every file it rewrites. docs/migrations/shape-2.md and shape-3.md explain both.
527
+
528
+ Shape 2 shipped earlier as 3.19.0-next without declaring a break, which meant the
529
+ "run yad migrate first" banner never fired for it. This footer covers both.
530
+
531
+ # [4.0.0-next.4](https://github.com/abdelrahmannasr/yadflow/compare/v4.0.0-next.3...v4.0.0-next.4) (2026-09-30)
532
+
533
+
534
+ * feat!: print Product, not hub, in output, --json and commit subjects (E124) ([b982530](https://github.com/abdelrahmannasr/yadflow/commit/b982530402dde171575407e82e72b8a2c405639a))
535
+ * feat!: read product.json first, and refuse two names that disagree (E122) ([2252296](https://github.com/abdelrahmannasr/yadflow/commit/22522969823c8a3525fa255c62a7a08c444b7450))
536
+ * feat!: rename the installed hub names to product, and name what is left (E123) ([91c62b6](https://github.com/abdelrahmannasr/yadflow/commit/91c62b6467d220a13b88970fd16b7bd42d740ffc))
537
+
538
+
539
+ ### Bug Fixes
540
+
541
+ * a broken shared registry never stops a join, and the .git check reads names as Windows does (E79 review 4) ([160ec83](https://github.com/abdelrahmannasr/yadflow/commit/160ec83512df1f6f50245f0f0f2714e7c3588230))
542
+ * a copyable hint never prints a registry name that starts with - (E81 review 10) ([8caa29d](https://github.com/abdelrahmannasr/yadflow/commit/8caa29d752d843f0ec16c1a79a030e532076cb73))
543
+ * a monorepo subfolder is present, refresh keeps to code-context, null entries are named (E81 review 1) ([f899a0d](https://github.com/abdelrahmannasr/yadflow/commit/f899a0dcb37f4f71851802c700ba02f9d2ed39c4))
544
+ * a workspace file sends only the Product's own registered repos to it, and stops the walk when it is not used (E80 review 1) ([2a01287](https://github.com/abdelrahmannasr/yadflow/commit/2a01287bb7fc30f4d2dc604273691ba20aec97e7))
545
+ * a worktree or nested repo inside a registered repo is its own checkout, never swapped for the repo's (E80 review 3) ([de05ebd](https://github.com/abdelrahmannasr/yadflow/commit/de05ebd33b5a21fe0c0d689fd9190ab99f4293c7))
546
+ * allow % in a URL's user and password for https only (E81 review 7) ([b1f05e4](https://github.com/abdelrahmannasr/yadflow/commit/b1f05e42453da655b0644032503fc4b6bec59db2))
547
+ * allow the file transport per URL, not per run (E81 review 4) ([fd88947](https://github.com/abdelrahmannasr/yadflow/commit/fd889479c6c99b3dbd6ac20ad0cfbdf592ec641d))
548
+ * an unreadable record is its own gate state, and the advice reads as steps (E124 review 5) ([8608e8e](https://github.com/abdelrahmannasr/yadflow/commit/8608e8ea6994607f3da8fef65b355823da257738))
549
+ * **checks:** a kept Product is read only when product-repo reaches nothing (E117) ([434f0c0](https://github.com/abdelrahmannasr/yadflow/commit/434f0c03d0ade65ec90f375e95cc129b59f97571))
550
+ * **checks:** a link.md's epic must be its story's own (E118) ([4f09325](https://github.com/abdelrahmannasr/yadflow/commit/4f09325f6e168db74ccc222ba0d8fc7feea30381))
551
+ * **checks:** a Product path starting with - is still walked twice (E117) ([a823dd5](https://github.com/abdelrahmannasr/yadflow/commit/a823dd56e8c13a7d94fb6874a21539fa286d97ec))
552
+ * **checks:** backfill-check folds every character a Mac folds into ASCII (E116) ([e913baa](https://github.com/abdelrahmannasr/yadflow/commit/e913baaf6c68e171e2e06f139c6b25bac9732b79))
553
+ * **checks:** backfill-check folds the Kelvin sign into k (E116) ([c5152c3](https://github.com/abdelrahmannasr/yadflow/commit/c5152c350ab1dd89e6906eac9433316be5ecf261))
554
+ * **checks:** backfill-check lists go through the stream, not the environment (E116) ([f2366f0](https://github.com/abdelrahmannasr/yadflow/commit/f2366f0c1433a05bae614956b66326223f2e51ab))
555
+ * **checks:** backfill-check pairs raw records, frees twins, checks links when specs are hidden (E116) ([6544926](https://github.com/abdelrahmannasr/yadflow/commit/654492634f9f65dbe702701ddaf8af038ba2beae))
556
+ * **checks:** backfill-check reads each spec by its object id (E116) ([6e44ae5](https://github.com/abdelrahmannasr/yadflow/commit/6e44ae576d547333bc1a256a1a3e473f8ddc5e1f))
557
+ * **checks:** backfill-check reads every spelling of the verified key (E116) ([81588e6](https://github.com/abdelrahmannasr/yadflow/commit/81588e62d71c60174fe678a8756d1a0806388554))
558
+ * **checks:** backfill-check reads the last verified: key, as YAML does (E116) ([36cb5cd](https://github.com/abdelrahmannasr/yadflow/commit/36cb5cda6a817b6a4d3504052058fa26c6eefb9d))
559
+ * **checks:** backfill-check reads the spec from the base and refuses links (E116) ([b63f5ac](https://github.com/abdelrahmannasr/yadflow/commit/b63f5ac706cd6155b5db63ffaf258dcd11d4269d))
560
+ * **checks:** close the gaps review 1 found in the Product and epic reads (E117, E118) ([a8d8178](https://github.com/abdelrahmannasr/yadflow/commit/a8d81780c35a651e30e51e5dcc0e30252ac50205))
561
+ * **checks:** close the gaps review 2 found in the Product reads (E117, E118) ([dcc5ea5](https://github.com/abdelrahmannasr/yadflow/commit/dcc5ea5667be4c52676656aef5723813edce4857))
562
+ * **checks:** close the gaps review 3 found in the Product reads (E117) ([fbb0768](https://github.com/abdelrahmannasr/yadflow/commit/fbb076848e5c1ba7f67ad34ff5d7b5b7d5d094e7))
563
+ * **checks:** compare the git folder as a folder, not a spelling (E117) ([2a824a8](https://github.com/abdelrahmannasr/yadflow/commit/2a824a83b4f8eb0129b1275ec8b45832d5f22d87))
564
+ * **checks:** contract-check fails a first spec whose product-repo reaches nothing (E119) ([a4738fc](https://github.com/abdelrahmannasr/yadflow/commit/a4738fce11d4b2e87ef6d03bcea865d22feb52dc))
565
+ * **checks:** contract-check folds every character a Mac folds into ASCII (E121) ([8422e70](https://github.com/abdelrahmannasr/yadflow/commit/8422e70e192f15c26053a94ccbf2ecb8c658d720))
566
+ * **checks:** read every NUL list with a newline in a name as ? (E121) ([2659211](https://github.com/abdelrahmannasr/yadflow/commit/2659211c94a28d52c7a25a956d8c75bab1dd61ec))
567
+ * **checks:** refuse a Product path inside the repo's own .git (E117) ([b726032](https://github.com/abdelrahmannasr/yadflow/commit/b7260323e1aebab247ad6367ea2bd1c6a6d4756d))
568
+ * **checks:** the first-spec FAIL fires only when the Product is not reached (E119) ([322ffe3](https://github.com/abdelrahmannasr/yadflow/commit/322ffe39fd2654aae5022898db3d3f71bd1d4f11))
569
+ * **checks:** the PR no longer chooses where the Product is read from (E117) ([68db03b](https://github.com/abdelrahmannasr/yadflow/commit/68db03b61269346a9c540f7fa39d4b37648f627b))
570
+ * **checks:** walk the Product path again from where it really lands (E117) ([1b0726d](https://github.com/abdelrahmannasr/yadflow/commit/1b0726d04a83544beef2bdfd3aac32f395d373bd))
571
+ * **ci:** Pages write scopes move to the job; one pin per action major (review 1) ([92a51fe](https://github.com/abdelrahmannasr/yadflow/commit/92a51febd1146c7f90528855d67cfa8d1be81255))
572
+ * **ci:** pin every workflow action by commit SHA and make the default token read-only ([43254bb](https://github.com/abdelrahmannasr/yadflow/commit/43254bba2c5606831ba7328896326c83c3dd4a3e))
573
+ * clean every printed path, one wording for the quote, and the door works from a Product subfolder (E49 review 2) ([85ea6a4](https://github.com/abdelrahmannasr/yadflow/commit/85ea6a4f5e99942aba7dd28fdd05605319cc241c))
574
+ * clone a registered repo only from a network address (E81 review 3) ([1582784](https://github.com/abdelrahmannasr/yadflow/commit/15827845f14329d1d592a01d68b8f3a9b122e19c))
575
+ * close the last one-key product.json hints, and refuse before touching .gitignore (E122 review 3) ([2b10f5b](https://github.com/abdelrahmannasr/yadflow/commit/2b10f5bd7568c5121adf72d5ab1f6e832c1029f9))
576
+ * **docs:** raise the docs shell version to 0.0.2 for the brace-expansion bump ([74498a5](https://github.com/abdelrahmannasr/yadflow/commit/74498a545b96923b5096b7adf06631e96ae7e616))
577
+ * **doctor:** ask for --overwrite-local only when a plain --fix would not do (E120 review 8) ([5950b89](https://github.com/abdelrahmannasr/yadflow/commit/5950b89def883390bafc0c3922ce4ad65d2f3131))
578
+ * **doctor:** decide the record's ahead/behind state by git, in one table (E120 review 5) ([1739cc5](https://github.com/abdelrahmannasr/yadflow/commit/1739cc5afff34d638376215c6da90d58aaf191bb))
579
+ * **doctor:** judge an off-branch clone's record as it will be after the switch (E120 review 9) ([39025bd](https://github.com/abdelrahmannasr/yadflow/commit/39025bd09c92870aacdcacca38cb3906c29da502))
580
+ * **doctor:** name `gate repair --push` for a stranded step on a verified Product (E48 review 3) ([29f0340](https://github.com/abdelrahmannasr/yadflow/commit/29f0340be0d0bef0f5e3d40a18d0da645e352b80))
581
+ * **doctor:** name a product-link record committed but never pushed (E120 review 3) ([4db532a](https://github.com/abdelrahmannasr/yadflow/commit/4db532a2712670e63f6caba85aeffd108ee63030))
582
+ * **doctor:** no silence over a broken record, and hints that work off the default branch (E120 review 6) ([97c714b](https://github.com/abdelrahmannasr/yadflow/commit/97c714b66429f3a9731fd0d853ab20fcaaff75f4))
583
+ * **doctor:** one clear step per repo in the product-link hint (E120 review 7) ([c117c3d](https://github.com/abdelrahmannasr/yadflow/commit/c117c3d2aa737df27c2a3167e2001dd8454654aa))
584
+ * **doctor:** tell unpushed, on another branch and behind apart (E120 review 4) ([9356748](https://github.com/abdelrahmannasr/yadflow/commit/935674881340e9c47aaba04b77196b343368cd64))
585
+ * drop the exact registry path from the warning, and clean C1 control characters too (E79 review 7) ([c70911c](https://github.com/abdelrahmannasr/yadflow/commit/c70911c5e199b2433325e3a4996b3fe240be42ad))
586
+ * **e120:** a record is ok only when committed as it stands (review 2) ([f2fc7de](https://github.com/abdelrahmannasr/yadflow/commit/f2fc7dec1435d009ead6966c831d4aa409871306))
587
+ * **e120:** a record right on disk reads ok, and --push still commits it (CI) ([a5cd7f5](https://github.com/abdelrahmannasr/yadflow/commit/a5cd7f541283a6715cc012bd57194f0684e2cdc8))
588
+ * **e120:** commit the record for sure, keep secrets out, keep local runs checking ([e96ed5d](https://github.com/abdelrahmannasr/yadflow/commit/e96ed5dc8b87938097fb35270d4b677c456377e3))
589
+ * every doctor command to copy takes registry text as one plain word (E81 review 11) ([e2d147a](https://github.com/abdelrahmannasr/yadflow/commit/e2d147addb163f5397b054f1e84b506b1732668c))
590
+ * **hook:** fail open under sh -e, follow no GIT_DIR, and name the repair that commits (E48 review 1) ([2991086](https://github.com/abdelrahmannasr/yadflow/commit/29910861d1c76763f765b2483ea412e8eba5d899))
591
+ * **hooks:** advice for a stuck old entry that is true in every case (E113 review 7) ([6d7fff1](https://github.com/abdelrahmannasr/yadflow/commit/6d7fff14a4a3d5bd1cb99b5bd0484cd292a0f109))
592
+ * **hooks:** give a local-ledger guard entry advice that works at apply too (E113 review 6) ([d26b241](https://github.com/abdelrahmannasr/yadflow/commit/d26b241af186961a40ca50dac289e3d6e230e1f8))
593
+ * **hooks:** judge an old hook script against the files as this run leaves them (E113 review 2) ([9a5df22](https://github.com/abdelrahmannasr/yadflow/commit/9a5df224c6e7322a6aebcc9a78b57afee1a2f59a))
594
+ * **hooks:** keep an old hook script until its new entry is committed (E113 review 1) ([c4fb5b3](https://github.com/abdelrahmannasr/yadflow/commit/c4fb5b37e3171604be7376e793cebd0eb194f14b))
595
+ * **hooks:** name what keeps an old hook script, and read HEAD once (E113 review 3) ([f1b95fc](https://github.com/abdelrahmannasr/yadflow/commit/f1b95fc2f135c5f4572d9e21b32e614a1ef77565))
596
+ * **hooks:** one sentence of advice for a stuck old hook entry, at plan and apply (E113 review 5) ([ab22b93](https://github.com/abdelrahmannasr/yadflow/commit/ab22b9348b659130fc1237786a4d6766919a580f))
597
+ * **hooks:** tell a capture-off Product to remove a stuck capture entry (E113 review 8) ([353053a](https://github.com/abdelrahmannasr/yadflow/commit/353053a017c5a0dad46c881abead93d65a9a704b))
598
+ * **hooks:** tell a local-ledger Product to remove a stuck guard entry (E113 review 4) ([0e1eaa5](https://github.com/abdelrahmannasr/yadflow/commit/0e1eaa5009f8cd06c39832faa9642ece7881e17b))
599
+ * **hook:** the agent's refusal gets the same fixes, and doctor names a hook git skips (E48 review 2) ([9551b1a](https://github.com/abdelrahmannasr/yadflow/commit/9551b1a4166bd4174a6a35f6655bbf5e805d3b90))
600
+ * join stays inside the workspace on disk, one bad entry fails alone, and init never takes over a code repo (E79 review 1) ([56f14ae](https://github.com/abdelrahmannasr/yadflow/commit/56f14ae7f90f4eddd6618bcf6a6f7e23947e850e))
601
+ * keep every URL form's host and user to safe characters (E81 review 6) ([61370c2](https://github.com/abdelrahmannasr/yadflow/commit/61370c28a911f4d39223a6eee2df6affc27415d7))
602
+ * keep the rename's own error when writeJSON's cleanup fails (E81 review 20) ([d5b860f](https://github.com/abdelrahmannasr/yadflow/commit/d5b860f66fce3e0c99739327e8662af49ba2fed7))
603
+ * keep writeJSON's own error when the temp cleanup fails (E81 review 19) ([b8d7640](https://github.com/abdelrahmannasr/yadflow/commit/b8d7640abc5b6fde91ef0c45a05e976c134912b4))
604
+ * ledger-guard reads a missing settings file quietly, and the roster hints name the file (E122 review 5) ([d00a117](https://github.com/abdelrahmannasr/yadflow/commit/d00a117d6cd535255b44b0ec3e61a38aa1774169))
605
+ * name a repos.json that does not parse instead of joining with no repos (E79 review 5) ([4a952e2](https://github.com/abdelrahmannasr/yadflow/commit/4a952e2dd80ea36b33aaa37c051da1f702980585))
606
+ * name the file in the last settings hints, refuse a pair that changed, and silence a missing settings file (E122 review 4) ([5aed634](https://github.com/abdelrahmannasr/yadflow/commit/5aed63409178e36954240e37ee11e53b1ab95e04))
607
+ * name the Product from the workspace folder instead of offering a second one, and match paths as the disk stores them (E80 review 2) ([71369b3](https://github.com/abdelrahmannasr/yadflow/commit/71369b3565d273ad6a2f6eb3bd3caa8f685e75f5))
608
+ * name the settings file a person should edit, and settle all pairs or none (E122 review 2) ([ccb8de4](https://github.com/abdelrahmannasr/yadflow/commit/ccb8de49a48397c14446faebf8c3d7ef1222abd5))
609
+ * name the settings file actually read, and keep risk-map advisory (E122 review 1) ([ab4fddc](https://github.com/abdelrahmannasr/yadflow/commit/ab4fddc495433cff0d013742f02086bea94b00a9))
610
+ * name the settings file on disk, and restore the old-name fallback (E124 review 1) ([cf24871](https://github.com/abdelrahmannasr/yadflow/commit/cf248716935eaebc9961ae8e9f8d8b27a123a9d0))
611
+ * never build a login command from a host that is not a plain host name (E81 review 13) ([0a09dc1](https://github.com/abdelrahmannasr/yadflow/commit/0a09dc11e047e483ea046720a9e505078e815ae5))
612
+ * never clone or register a repo path through a .git folder, and say what --dir is for each workspace verb (E79 review 2) ([6be43a2](https://github.com/abdelrahmannasr/yadflow/commit/6be43a274b392c405454d1a09d4f49143257d100))
613
+ * never write over an edited new name, keep one workflow running, and name a gate that rejects product (E123 review 1) ([d7dc72b](https://github.com/abdelrahmannasr/yadflow/commit/d7dc72bf0857ceda09db081be1b95647a20334c2))
614
+ * one plainHost test for every login command doctor prints (E81 review 14) ([8a25d94](https://github.com/abdelrahmannasr/yadflow/commit/8a25d947353538ce7b0ffe0f399d08082e791bab))
615
+ * one samePath for a git path against a Node path, and survive a missing .git/hooks (E48 review 5) ([156ec1e](https://github.com/abdelrahmannasr/yadflow/commit/156ec1e4d9d19e5cd22e454432b1eece6fac6ced))
616
+ * one terminal cleaner for every module that prints registry text (E81 review 12) ([805a4fd](https://github.com/abdelrahmannasr/yadflow/commit/805a4fd200c2465f9a491f44e81b60ed50605946))
617
+ * only the ledger door runs from a subfolder, and the sha — not an indent — keeps :: off a line (E49 review 3) ([9878423](https://github.com/abdelrahmannasr/yadflow/commit/987842384792905cbc15db429d5d3e3da76033e4))
618
+ * read any spelling of the profile mapping and branch, and never a comment (E123 review 3) ([67c3a55](https://github.com/abdelrahmannasr/yadflow/commit/67c3a559ae95dae1abae8f4561d5e04b073eca02))
619
+ * record the new name a kept rename installs, and say a profile gap only when it bites (E123 review 2) ([9c99014](https://github.com/abdelrahmannasr/yadflow/commit/9c990145a68596dddfa4c2534afae18f3615efda))
620
+ * refresh never writes through a .gitignore the Product commits as a link (E81 review 16) ([5d9a982](https://github.com/abdelrahmannasr/yadflow/commit/5d9a9822d73376c5f83a6fe880dd52adf075e67a))
621
+ * refresh stops at a linked .sdlc, --push included (E81 review 18) ([e79d64c](https://github.com/abdelrahmannasr/yadflow/commit/e79d64c503d3d96e8f1005b1560d4e815ecf2820))
622
+ * refuse a clone target with a link on its way, so a committed link cannot reach .git (E79 review 3) ([667d696](https://github.com/abdelrahmannasr/yadflow/commit/667d6964e9ceed75ce0ea1fb82b03d6cf7c324ea))
623
+ * refuse a control character anywhere in a registered git_url (E81 review 8) ([6edf593](https://github.com/abdelrahmannasr/yadflow/commit/6edf5937a094a827faf02454fa2f54803b0f2cd4))
624
+ * refuse any folder holding HEAD on the way to a registered subfolder (E81 review 2) ([0471334](https://github.com/abdelrahmannasr/yadflow/commit/04713341b8b3ea5ee55d59da82b9f818d6bfe2df))
625
+ * refuse encoded C1 and bidi characters; clean the last raw registry text (E81 review 9) ([7f7721b](https://github.com/abdelrahmannasr/yadflow/commit/7f7721b636fc19ed4736c6962ae3cd67726c3007))
626
+ * **release:** install an exact npm version, not npm@latest ([0bf8981](https://github.com/abdelrahmannasr/yadflow/commit/0bf89817da64f43f91fc281d42f76883c0f1a1ef))
627
+ * **setup:** compare hook folders by their long name on Windows (E48) ([8f1ac56](https://github.com/abdelrahmannasr/yadflow/commit/8f1ac5617cf50b89ca8626e5d15ec645b2ff64a5))
628
+ * **setup:** read a core.hooksPath typed in another case as the default folder where the disk ignores case (E48 review 6) ([997f77d](https://github.com/abdelrahmannasr/yadflow/commit/997f77d39d76c49a7e5b63845c867484fb180437))
629
+ * **skills:** yad-connect-repos frontmatter parses; two descriptions fit 1024 ([d6eaf55](https://github.com/abdelrahmannasr/yadflow/commit/d6eaf558d8296dbedacab3c70f9075d497222d56))
630
+ * the --profile hub advice names every gate in the way, in every state (E124 review 4) ([5d125ec](https://github.com/abdelrahmannasr/yadflow/commit/5d125ece69967c3c76d923da2c05decd1c500140))
631
+ * the --profile hub advice reads each gate's real state (E124 review 3) ([f00c51e](https://github.com/abdelrahmannasr/yadflow/commit/f00c51e7a4ec54bb6c126797478088c06365d746))
632
+ * the --profile hub advice waits for a gate that refuses product, and a repo named product is shown by its path (E124 review 2) ([80518c5](https://github.com/abdelrahmannasr/yadflow/commit/80518c5cbd3af2209882167bb381731190d2336a))
633
+ * the clone sets GIT_ALLOW_PROTOCOL; a local source must exist (E81 review 5) ([7963220](https://github.com/abdelrahmannasr/yadflow/commit/796322023a6bc90b541f66b3c383e34b1957c791))
634
+ * the drift advice names yad migrate --apply, and one drift lookup serves all (review 1) ([f158fa1](https://github.com/abdelrahmannasr/yadflow/commit/f158fa1f8311a71e5346dbd51ee6627a231b3dae))
635
+ * the ledger override claims only what it can see, and no control character reaches the CI log (E49 review 1) ([da7a6d9](https://github.com/abdelrahmannasr/yadflow/commit/da7a6d96cf762e7d23f5f4ae3c44c5c2e9dc195d))
636
+ * the solo people count judges each registered path before git runs (E81 review 15) ([993698a](https://github.com/abdelrahmannasr/yadflow/commit/993698a17f2496985da6b8c6160c2e9eeba83449))
637
+ * the unreadable-registry warning gives the real reason, and a null registry is named too (E79 review 6) ([9f426eb](https://github.com/abdelrahmannasr/yadflow/commit/9f426eb3697e473bde80468e0be5946de4041404))
638
+ * the unreadable-settings cell says only what is true (E124 review 6) ([5d43189](https://github.com/abdelrahmannasr/yadflow/commit/5d431894e377065ca1d26316973fd6cfabc7d3c9))
639
+ * when a file's two names disagree, the gate advice says yad migrate first (E124 follow-up) ([75d2184](https://github.com/abdelrahmannasr/yadflow/commit/75d2184480acc0d285d7718533ab9bf9d65cf723))
640
+ * writeJSON's temp file is random and exclusive (E81 review 17) ([b5cbcd9](https://github.com/abdelrahmannasr/yadflow/commit/b5cbcd935a81534b5f749eeba13c36711fb7a471))
641
+
642
+
643
+ ### Documentation
644
+
645
+ * the guides, sites and diagram say Product, and a guide to the hand changes (E124) ([883cd6f](https://github.com/abdelrahmannasr/yadflow/commit/883cd6f56378dc58bbbd1a9ebdba0048a1e35c9a))
646
+
647
+
648
+ ### Features
649
+
650
+ * .yad-workspace.json — yad finds the Product from any repo in the workspace (E80) ([27a7579](https://github.com/abdelrahmannasr/yadflow/commit/27a75793c558d597840d01c9f7986e25e7a5c42a))
651
+ * **checks:** check the Product out in CI where the record says (E120) ([b288326](https://github.com/abdelrahmannasr/yadflow/commit/b288326da2a72c3475d0cfafd2f8bc9540d0670d))
652
+ * **checks:** read where the Product lives from .sdlc/product-link.json on the base (E120) ([6b9e7b1](https://github.com/abdelrahmannasr/yadflow/commit/6b9e7b1f293183b89fda9d1aa9b748bcd62bb7f6))
653
+ * **commit:** yad commit --manual --reason, the door past the ledger hook (E49) ([5b4081a](https://github.com/abdelrahmannasr/yadflow/commit/5b4081a5bea4423c90b41a5ad676e0c5987bf0d9))
654
+ * **doctor:** warn checks:backfill-blind for an older backfill-check (E116) ([bfb82cf](https://github.com/abdelrahmannasr/yadflow/commit/bfb82cf2e0d956165c179a92a0e09fb46e8e97f9))
655
+ * **hook:** refuse a hand commit to the CI-owned ledger with a git pre-commit hook (E48) ([e2258b1](https://github.com/abdelrahmannasr/yadflow/commit/e2258b14f9c35af5057e109713c6407fae50b068))
656
+ * **hooks:** run the agent hooks as Node scripts, so Windows works without WSL (E113) ([887ceea](https://github.com/abdelrahmannasr/yadflow/commit/887ceeadabdb4f20482c3f3a5d29963c5fe74cc8))
657
+ * **repos:** write each code repo's product-link record, and warn when it is missing (E120) ([54f1fe3](https://github.com/abdelrahmannasr/yadflow/commit/54f1fe382d884aa2e72bb56c26197dd3e8e3c5c0))
658
+ * tell a repo named product apart, and name --profile hub in the team's workflows (E124 review 1) ([98fc15d](https://github.com/abdelrahmannasr/yadflow/commit/98fc15d345354c0df83ceae7d7aa4db5765c02b2))
659
+ * yad new, yad init and yad join — the three ways into a workspace (E79) ([dcccf67](https://github.com/abdelrahmannasr/yadflow/commit/dcccf670ffb4cb376aba6af26e602140328c00ea))
660
+ * yad repo clone fetches registered repos missing on this machine (E81) ([8a20504](https://github.com/abdelrahmannasr/yadflow/commit/8a20504f816ec556e55ec5db41b8f4350973e283))
661
+
662
+
663
+ ### BREAKING CHANGES
664
+
665
+ * after `yad update` renames the installed CI names, a
666
+ team's own files that name the old ones must be changed by hand — GitLab
667
+ `needs:` / `dependencies:` / `extends:` / `!reference` naming a
668
+ `yad-hub-*` job, GitHub `workflow_run:` triggers naming `yad-hub-checks`,
669
+ status badges, CODEOWNERS lines, and scripts that read `--json` names or
670
+ `SDLC_HUB_CONFIG` / `.sdlc/hub.json`. Every case, with a before and
671
+ after: docs/migrations/hub-to-product.md.
672
+ * `--json` names that said `hub` now say `product`, and
673
+ `jsonVersion` is 2. `yad doctor` check ids `hub`, `hub-git-url` and
674
+ `ci-tags:hub` are `product`, `product-git-url` and `ci-tags:product`;
675
+ `yad open-pr` answers `baseSource: "product"` and `stage:
676
+ "product-shape" | "product-tooling"`; `yad check` / `yad update` answer
677
+ `items[].scope: "product"` and `commits[].label: "product"`; and
678
+ `yad history show` answers `productConfigWhy` where it answered
679
+ `hubWhy`. The audit commits are `chore(product): …`. See the
680
+ "What moved in jsonVersion 2" table in docs/CLI.md.
681
+ * `yad update` renames the Product's
682
+ .github/workflows/yad-hub-checks.yml and .gitlab/ci/yad-hub-checks.yml to
683
+ yad-product-checks.yml, the GitLab jobs yad-hub-* to yad-product-*, and
684
+ the yad-hub-bridge skill to yad-product-bridge. GitHub job names (the
685
+ required checks) do not change. Your own CI that names an old name — a
686
+ GitLab needs:/dependencies:/extends:/!reference, a GitHub workflow_run:
687
+ trigger on yad-hub-checks, a status badge, a CODEOWNERS line — must be
688
+ changed by hand; `yad doctor` lists each by file and line (renamed-ref:).
689
+ * yadflow 4 reads .sdlc/product.json (and each epic's
690
+ product-prs.json) first; .sdlc/hub.json and hub-prs.json are read only when the
691
+ new name is absent, are still written until 5.0, and are deleted in 5.0. This
692
+ corrects docs/migrations/shape-3.md and the 4.0.0-next.1 notes, which said the
693
+ old names stay the ones read for another major. When both names exist and say
694
+ different things, every command refuses (YAD-STATE-008) and the gates fail;
695
+ run `yad migrate` to see the difference and `yad migrate --apply` (or
696
+ `--apply --keep product|hub`) to choose. Edit settings by hand in
697
+ .sdlc/product.json, then run `yad migrate --apply --keep product`. Gates now
698
+ honour SDLC_PRODUCT_CONFIG before SDLC_HUB_CONFIG.
699
+
1
700
  # [4.0.0-next.3](https://github.com/abdelrahmannasr/yadflow/compare/v4.0.0-next.2...v4.0.0-next.3) (2026-09-26)
2
701
 
3
702