llm-wb 0.1.0-beta.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 (170) hide show
  1. package/.agentic/00.chat/README.md +78 -0
  2. package/.agentic/00.chat/checklists/before-commit.md +195 -0
  3. package/.agentic/00.chat/checklists/llm-workbench-public-beta.md +94 -0
  4. package/.agentic/00.chat/commands/README.md +108 -0
  5. package/.agentic/00.chat/migration-plan.md +132 -0
  6. package/.agentic/00.chat/skills/session-summary.md +48 -0
  7. package/.agentic/00.chat/standards/llm-workbench-public-beta-contract.md +216 -0
  8. package/.agentic/00.chat/standards/main-refresh-conflict-types.md +358 -0
  9. package/.agentic/00.chat/workflows/README.md +40 -0
  10. package/.agentic/00.chat/workflows/bootstrap-chat-workbench-repo.md +212 -0
  11. package/.agentic/00.chat/workflows/chat-cleanup.md +102 -0
  12. package/.agentic/00.chat/workflows/chat-commit.md +56 -0
  13. package/.agentic/00.chat/workflows/chat-promote-to-main.md +169 -0
  14. package/.agentic/00.chat/workflows/chat-refresh-from-main.md +242 -0
  15. package/.agentic/00.chat/workflows/chat-reporting.md +69 -0
  16. package/.agentic/00.chat/workflows/chat-start.md +173 -0
  17. package/.agentic/00.chat/workflows/chat-upstream-reusable-lesson.md +123 -0
  18. package/.agentic/shared/standards/README.md +32 -0
  19. package/.agentic/shared/standards/upstream-repo-bootstrap.md +131 -0
  20. package/.agentic/shared/workflows/README.md +35 -0
  21. package/.agentic/shared/workflows/capability-resolution-workflow.md +189 -0
  22. package/.agentic/shared/workflows/change-shared-process.md +92 -0
  23. package/.cursor/rules/llm-workbench.mdc +17 -0
  24. package/.github/copilot-instructions.md +16 -0
  25. package/AGENTS.md +63 -0
  26. package/CLAUDE.md +16 -0
  27. package/CONTRIBUTING.md +57 -0
  28. package/LICENSE +21 -0
  29. package/LLM_WORKBENCH.md +17 -0
  30. package/README.md +98 -0
  31. package/SECURITY.md +44 -0
  32. package/bin/llm-workbench.js +672 -0
  33. package/docs/00.chat/README.md +47 -0
  34. package/docs/00.chat/llm-workbench-acceptance-matrix.md +55 -0
  35. package/docs/00.chat/script-layout.md +107 -0
  36. package/docs/adapting-to-your-repo.md +29 -0
  37. package/docs/concepts.md +38 -0
  38. package/docs/install.md +114 -0
  39. package/docs/public-beta-contract.md +45 -0
  40. package/docs/workflows.md +103 -0
  41. package/examples/minimal-repo/README.md +13 -0
  42. package/package.json +93 -0
  43. package/scripts/00.chat/README.md +46 -0
  44. package/scripts/00.chat/bootstrap/README.md +35 -0
  45. package/scripts/00.chat/bootstrap/audit-chat-bootstrap-file-set/README.md +39 -0
  46. package/scripts/00.chat/bootstrap/audit-chat-bootstrap-file-set/script.sh +213 -0
  47. package/scripts/00.chat/closeout/README.md +30 -0
  48. package/scripts/00.chat/closeout/build-closeout-prompt/README.md +35 -0
  49. package/scripts/00.chat/closeout/build-closeout-prompt/script.sh +124 -0
  50. package/scripts/00.chat/command/README.md +31 -0
  51. package/scripts/00.chat/command/close/README.md +30 -0
  52. package/scripts/00.chat/command/close/script.sh +25 -0
  53. package/scripts/00.chat/command/dispatcher/README.md +46 -0
  54. package/scripts/00.chat/command/dispatcher/script.sh +91 -0
  55. package/scripts/00.chat/command/dispatcher/smoke-test.sh +168 -0
  56. package/scripts/00.chat/command/new/README.md +32 -0
  57. package/scripts/00.chat/command/new/script.sh +28 -0
  58. package/scripts/00.chat/command/open-window/README.md +38 -0
  59. package/scripts/00.chat/command/open-window/script.sh +25 -0
  60. package/scripts/00.chat/command/package-scripts/README.md +34 -0
  61. package/scripts/00.chat/command/package-scripts/smoke-test.sh +113 -0
  62. package/scripts/00.chat/git/README.md +30 -0
  63. package/scripts/00.chat/git/cleanup-empty-chat-branches/README.md +36 -0
  64. package/scripts/00.chat/git/cleanup-empty-chat-branches/script.sh +243 -0
  65. package/scripts/00.chat/git/cleanup-empty-chat-branches/smoke-test.sh +136 -0
  66. package/scripts/00.chat/local-merge/README.md +30 -0
  67. package/scripts/00.chat/local-merge/list-active-chat-branches/README.md +29 -0
  68. package/scripts/00.chat/local-merge/list-active-chat-branches/script.sh +109 -0
  69. package/scripts/00.chat/local-merge/report-chat-branch-overlaps/README.md +29 -0
  70. package/scripts/00.chat/local-merge/report-chat-branch-overlaps/script.sh +142 -0
  71. package/scripts/00.chat/local-merge/verify-chat-ready-to-merge-local-main/README.md +33 -0
  72. package/scripts/00.chat/local-merge/verify-chat-ready-to-merge-local-main/script.sh +345 -0
  73. package/scripts/00.chat/local-merge/verify-chat-ready-to-merge-local-main/smoke-test.sh +244 -0
  74. package/scripts/00.chat/main-refresh/README.md +39 -0
  75. package/scripts/00.chat/main-refresh/apply-rehearsed-refresh/README.md +32 -0
  76. package/scripts/00.chat/main-refresh/apply-rehearsed-refresh/script.sh +198 -0
  77. package/scripts/00.chat/main-refresh/check-chat-is-current-with-main/README.md +30 -0
  78. package/scripts/00.chat/main-refresh/check-chat-is-current-with-main/script.sh +121 -0
  79. package/scripts/00.chat/main-refresh/classify-conflict/README.md +39 -0
  80. package/scripts/00.chat/main-refresh/classify-conflict/script.sh +169 -0
  81. package/scripts/00.chat/main-refresh/classify-conflict/smoke-test.sh +137 -0
  82. package/scripts/00.chat/main-refresh/classify-refresh-readiness/README.md +35 -0
  83. package/scripts/00.chat/main-refresh/classify-refresh-readiness/script.sh +171 -0
  84. package/scripts/00.chat/main-refresh/classify-refresh-readiness/smoke-test.sh +132 -0
  85. package/scripts/00.chat/main-refresh/rehearse-refresh-from-main/README.md +34 -0
  86. package/scripts/00.chat/main-refresh/rehearse-refresh-from-main/script.sh +124 -0
  87. package/scripts/00.chat/main-refresh/rehearse-refresh-from-main/smoke-test.sh +257 -0
  88. package/scripts/00.chat/main-refresh/show-main-update-status/README.md +31 -0
  89. package/scripts/00.chat/main-refresh/show-main-update-status/script.sh +73 -0
  90. package/scripts/00.chat/main-refresh/verify-conflict-audit/README.md +37 -0
  91. package/scripts/00.chat/main-refresh/verify-conflict-audit/script.sh +154 -0
  92. package/scripts/00.chat/main-refresh/verify-conflict-audit/smoke-test.sh +99 -0
  93. package/scripts/00.chat/metrics/README.md +35 -0
  94. package/scripts/00.chat/metrics/data/chat-pricing.json +107 -0
  95. package/scripts/00.chat/metrics/data/chat-pricing.schema.json +63 -0
  96. package/scripts/00.chat/metrics/estimate-chat-cost/README.md +40 -0
  97. package/scripts/00.chat/metrics/estimate-chat-cost/script.js +130 -0
  98. package/scripts/00.chat/migration/README.md +30 -0
  99. package/scripts/00.chat/migration/audit-chat-layer-migration/README.md +33 -0
  100. package/scripts/00.chat/migration/audit-chat-layer-migration/script.sh +127 -0
  101. package/scripts/00.chat/recovery/README.md +30 -0
  102. package/scripts/00.chat/recovery/import-active-paths-to-chat-worktree/README.md +76 -0
  103. package/scripts/00.chat/recovery/import-active-paths-to-chat-worktree/script.sh +212 -0
  104. package/scripts/00.chat/recovery/import-active-paths-to-chat-worktree/smoke-test.sh +162 -0
  105. package/scripts/00.chat/reporting/README.md +30 -0
  106. package/scripts/00.chat/reporting/generate-commit-log-summary/README.md +35 -0
  107. package/scripts/00.chat/reporting/generate-commit-log-summary/script.sh +299 -0
  108. package/scripts/00.chat/reporting/generate-commit-log-summary/smoke-test.sh +93 -0
  109. package/scripts/00.chat/reporting/report-chat-workspaces/README.md +32 -0
  110. package/scripts/00.chat/reporting/report-chat-workspaces/script.sh +82 -0
  111. package/scripts/00.chat/session-log/README.md +33 -0
  112. package/scripts/00.chat/session-log/check-commit-prerequisites/README.md +89 -0
  113. package/scripts/00.chat/session-log/check-commit-prerequisites/script.sh +121 -0
  114. package/scripts/00.chat/session-log/check-commit-prerequisites/smoke-test.sh +119 -0
  115. package/scripts/00.chat/session-log/check-commitlog-deletions/README.md +90 -0
  116. package/scripts/00.chat/session-log/check-commitlog-deletions/script.sh +131 -0
  117. package/scripts/00.chat/session-log/check-commitlog-deletions/smoke-test.sh +123 -0
  118. package/scripts/00.chat/session-log/checkpoint-chat-session-log/README.md +98 -0
  119. package/scripts/00.chat/session-log/checkpoint-chat-session-log/script.sh +126 -0
  120. package/scripts/00.chat/session-log/paths/README.md +38 -0
  121. package/scripts/00.chat/session-log/paths/lib.sh +133 -0
  122. package/scripts/00.chat/session-log/prepare-chat-session-before-commit/README.md +90 -0
  123. package/scripts/00.chat/session-log/prepare-chat-session-before-commit/script.sh +145 -0
  124. package/scripts/00.chat/session-log/read-current-chat-log/README.md +44 -0
  125. package/scripts/00.chat/session-log/read-current-chat-log/script.sh +92 -0
  126. package/scripts/00.chat/session-log/read-current-chat-log/smoke-test.sh +127 -0
  127. package/scripts/00.chat/session-log/record-chat-commit/README.md +133 -0
  128. package/scripts/00.chat/session-log/record-chat-commit/script.sh +394 -0
  129. package/scripts/00.chat/session-log/record-chat-commit/smoke-test.sh +227 -0
  130. package/scripts/00.chat/session-log/record-main-refresh-conflict/README.md +34 -0
  131. package/scripts/00.chat/session-log/record-main-refresh-conflict/script.sh +239 -0
  132. package/scripts/00.chat/session-log/rename-current-chat-log-folder/README.md +32 -0
  133. package/scripts/00.chat/session-log/rename-current-chat-log-folder/script.sh +112 -0
  134. package/scripts/00.chat/session-log/update-chat-log/README.md +32 -0
  135. package/scripts/00.chat/session-log/update-chat-log/script.sh +294 -0
  136. package/scripts/00.chat/startup/README.md +37 -0
  137. package/scripts/00.chat/startup/auto-start-missing-session/README.md +113 -0
  138. package/scripts/00.chat/startup/auto-start-missing-session/script.sh +54 -0
  139. package/scripts/00.chat/startup/resolve-current-chat-session/README.md +57 -0
  140. package/scripts/00.chat/startup/resolve-current-chat-session/script.sh +47 -0
  141. package/scripts/00.chat/startup/resolve-current-chat-session/smoke-test.sh +130 -0
  142. package/scripts/00.chat/startup/start-chat-session/README.md +197 -0
  143. package/scripts/00.chat/startup/start-chat-session/script.sh +330 -0
  144. package/scripts/00.chat/startup/start-chat-session/smoke-test.sh +182 -0
  145. package/scripts/00.chat/startup/start-new-chat/README.md +31 -0
  146. package/scripts/00.chat/startup/start-new-chat/script.sh +29 -0
  147. package/scripts/00.chat/transcript/README.md +36 -0
  148. package/scripts/00.chat/transcript/discover-codex-session-log/README.md +32 -0
  149. package/scripts/00.chat/transcript/discover-codex-session-log/script.sh +106 -0
  150. package/scripts/00.chat/transcript/register-codex-session-log/README.md +32 -0
  151. package/scripts/00.chat/transcript/register-codex-session-log/script.sh +115 -0
  152. package/scripts/00.chat/worktree/README.md +32 -0
  153. package/scripts/00.chat/worktree/check-write-location/README.md +87 -0
  154. package/scripts/00.chat/worktree/check-write-location/script.sh +95 -0
  155. package/scripts/00.chat/worktree/dirty-worktree-check/README.md +77 -0
  156. package/scripts/00.chat/worktree/dirty-worktree-check/script.sh +93 -0
  157. package/scripts/00.chat/worktree/ensure-chat-worktree/README.md +33 -0
  158. package/scripts/00.chat/worktree/ensure-chat-worktree/script.sh +132 -0
  159. package/scripts/00.chat/worktree/open-window/README.md +34 -0
  160. package/scripts/00.chat/worktree/open-window/script.sh +131 -0
  161. package/scripts/00.chat/worktree/paths/README.md +32 -0
  162. package/scripts/00.chat/worktree/paths/lib.sh +71 -0
  163. package/scripts/01.harness/artifact-metadata/check-headers/script.sh +522 -0
  164. package/scripts/01.harness/artifact-metadata/check-headers/smoke-test.sh +48 -0
  165. package/scripts/01.harness/check-deterministic-process-drift.sh +416 -0
  166. package/scripts/01.harness/check-governed-script-command-drift.sh +184 -0
  167. package/scripts/01.harness/run-governed-script.sh +178 -0
  168. package/scripts/install.sh +503 -0
  169. package/scripts/uninstall.sh +199 -0
  170. package/tests/smoke-test-install.sh +70 -0
@@ -0,0 +1,244 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # agentic-artifact:
5
+ # schema: agentic-artifact/v2
6
+ # id: chat.script.local-merge.verify-chat-ready-to-merge-local-main.smoke-test
7
+ # version: 1
8
+ # status: active
9
+ # layer: 00.chat
10
+ # domain: local-merge
11
+ # disciplines:
12
+ # - agentic
13
+ # kind: script
14
+ # purpose: Smoke test local-main merge readiness verifier classifications.
15
+ # portability:
16
+ # class: reusable
17
+ # targets:
18
+ # - llm-workbench
19
+ # used_by:
20
+ # - id: chat.workflows.chat-promote-to-main
21
+ # path: .agentic/00.chat/workflows/chat-promote-to-main.md
22
+ # - id: chat.script.local-merge.verify-chat-ready-to-merge-local-main
23
+ # path: scripts/00.chat/local-merge/verify-chat-ready-to-merge-local-main/script.sh
24
+ # effects:
25
+ # - branches
26
+ # - commits
27
+ # - worktrees
28
+ # - writes-files
29
+
30
+ SOURCE_ROOT="$(git rev-parse --show-toplevel)"
31
+ TMP_ROOT="$(mktemp -d "${TMPDIR:-/tmp}/local-convergence-verifier-smoke.XXXXXX")"
32
+
33
+ cleanup() {
34
+ rm -rf "$TMP_ROOT"
35
+ }
36
+
37
+ trap cleanup EXIT
38
+
39
+ fail() {
40
+ echo "ERROR: $*" >&2
41
+ exit 1
42
+ }
43
+
44
+ copy_verifier_scripts() {
45
+ local repo="$1"
46
+
47
+ mkdir -p "$repo/scripts/00.chat/local-merge/verify-chat-ready-to-merge-local-main" "$repo/scripts/00.chat/session-log/paths" "$repo/scripts/00.chat/worktree/paths"
48
+ cp "$SOURCE_ROOT/scripts/00.chat/local-merge/verify-chat-ready-to-merge-local-main/script.sh" "$repo/scripts/00.chat/local-merge/verify-chat-ready-to-merge-local-main/script.sh"
49
+ cp "$SOURCE_ROOT/scripts/00.chat/worktree/paths/lib.sh" "$repo/scripts/00.chat/worktree/paths/lib.sh"
50
+ cp "$SOURCE_ROOT/scripts/00.chat/session-log/paths/lib.sh" "$repo/scripts/00.chat/session-log/paths/lib.sh"
51
+ }
52
+
53
+ init_repo() {
54
+ local name="$1"
55
+ local repo="$TMP_ROOT/$name/repo"
56
+
57
+ mkdir -p "$repo"
58
+ copy_verifier_scripts "$repo"
59
+
60
+ git -C "$repo" init -q -b main
61
+ git -C "$repo" config user.name "Smoke Test"
62
+ git -C "$repo" config user.email "smoke@example.invalid"
63
+
64
+ printf 'base\n' > "$repo/base.txt"
65
+ git -C "$repo" add base.txt scripts
66
+ git -C "$repo" commit -q -m "initial"
67
+
68
+ printf '%s\n' "$repo"
69
+ }
70
+
71
+ canonical_worktree_path() {
72
+ local repo="$1"
73
+ local branch="$2"
74
+
75
+ (
76
+ cd "$repo"
77
+ # shellcheck source=../worktree/paths/lib.sh
78
+ source scripts/00.chat/worktree/paths/lib.sh
79
+ chat_worktree_path_for_branch "$repo" "$branch"
80
+ )
81
+ }
82
+
83
+ write_session_log() {
84
+ local repo="$1"
85
+ local session="$2"
86
+ local branch="$3"
87
+ local worktree="$4"
88
+ local latest_sha="$5"
89
+ local log_path="$repo/commitLogs/2026/jun/16/$session/README.md"
90
+
91
+ mkdir -p "$(dirname "$log_path")"
92
+ cat > "$log_path" <<EOF
93
+ # Chat Session: $session
94
+
95
+ <!-- agentic-session
96
+ id: $session
97
+ task: smoke test local convergence
98
+ branch: $branch
99
+ worktree: $worktree
100
+ layer: shared
101
+ mode: implementation
102
+ workflow: .agentic/shared/workflows/change-shared-process.md
103
+ status: ready
104
+ latest_commit_sha: $latest_sha
105
+ -->
106
+
107
+ ## Commits
108
+
109
+ - Commit: \`$latest_sha\`
110
+ EOF
111
+ }
112
+
113
+ create_chat_branch_with_log() {
114
+ local repo="$1"
115
+ local session="$2"
116
+ local latest_sha="${3:-}"
117
+ local branch="chat/$session"
118
+ local worktree
119
+ local task_sha
120
+
121
+ worktree="$(canonical_worktree_path "$repo" "$branch")"
122
+
123
+ git -C "$repo" switch -q -c "$branch"
124
+ printf 'work\n' > "$repo/work-$session.txt"
125
+ git -C "$repo" add "work-$session.txt"
126
+ git -C "$repo" commit -q -m "task work"
127
+ task_sha="$(git -C "$repo" rev-parse HEAD)"
128
+
129
+ if [ -z "$latest_sha" ]; then
130
+ latest_sha="$task_sha"
131
+ fi
132
+
133
+ write_session_log "$repo" "$session" "$branch" "$worktree" "$latest_sha"
134
+ git -C "$repo" add "commitLogs/2026/jun/16/$session/README.md"
135
+ git -C "$repo" commit -q -m "record session log"
136
+ git -C "$repo" switch -q main
137
+ mkdir -p "${worktree%/*}"
138
+ git -C "$repo" worktree add -q "$worktree" "$branch"
139
+ }
140
+
141
+ run_expect_state() {
142
+ local repo="$1"
143
+ local branch="$2"
144
+ local state="$3"
145
+ local should_succeed="$4"
146
+ local out="$TMP_ROOT/output"
147
+ local err="$TMP_ROOT/error"
148
+
149
+ if [ "$should_succeed" = "yes" ]; then
150
+ (
151
+ cd "$repo"
152
+ bash scripts/00.chat/local-merge/verify-chat-ready-to-merge-local-main/script.sh "$branch"
153
+ ) > "$out" 2> "$err" || {
154
+ cat "$out" >&2
155
+ cat "$err" >&2
156
+ fail "expected verifier success for $state"
157
+ }
158
+ else
159
+ if (
160
+ cd "$repo"
161
+ bash scripts/00.chat/local-merge/verify-chat-ready-to-merge-local-main/script.sh "$branch"
162
+ ) > "$out" 2> "$err"; then
163
+ cat "$out" >&2
164
+ fail "expected verifier failure for $state"
165
+ fi
166
+ fi
167
+
168
+ if ! grep -q "State: $state" "$out"; then
169
+ cat "$out" >&2
170
+ cat "$err" >&2
171
+ fail "expected state $state"
172
+ fi
173
+ }
174
+
175
+ repo="$(init_repo eligible)"
176
+ session="2026-06-16-22-32-eligible"
177
+ branch="chat/$session"
178
+ create_chat_branch_with_log "$repo" "$session"
179
+ run_expect_state "$repo" "$branch" "eligible" "yes"
180
+
181
+ repo="$(init_repo renamed-log)"
182
+ session="2026-06-16-22-32-renamed-log"
183
+ branch="chat/$session"
184
+ create_chat_branch_with_log "$repo" "$session"
185
+ worktree="$(canonical_worktree_path "$repo" "$branch")"
186
+ git -C "$worktree" mv \
187
+ "commitLogs/2026/jun/16/$session" \
188
+ "commitLogs/2026/jun/16/2026-06-16-22-32-short-log-name"
189
+ git -C "$worktree" commit -q -m "rename session log folder"
190
+ run_expect_state "$repo" "$branch" "eligible" "yes"
191
+
192
+ repo="$(init_repo behind)"
193
+ session="2026-06-16-22-33-behind"
194
+ branch="chat/$session"
195
+ worktree="$(canonical_worktree_path "$repo" "$branch")"
196
+ write_session_log "$repo" "$session" "$branch" "$worktree" "$(git -C "$repo" rev-parse HEAD)"
197
+ git -C "$repo" add "commitLogs/2026/jun/16/$session/README.md"
198
+ git -C "$repo" commit -q -m "record shared session log"
199
+ git -C "$repo" branch "$branch"
200
+ printf 'main update\n' > "$repo/main-update.txt"
201
+ git -C "$repo" add main-update.txt
202
+ git -C "$repo" commit -q -m "main update"
203
+ mkdir -p "${worktree%/*}"
204
+ git -C "$repo" worktree add -q "$worktree" "$branch"
205
+ run_expect_state "$repo" "$branch" "blocked-behind" "no"
206
+
207
+ repo="$(init_repo diverged)"
208
+ session="2026-06-16-22-34-diverged"
209
+ branch="chat/$session"
210
+ create_chat_branch_with_log "$repo" "$session"
211
+ printf 'main update\n' > "$repo/main-update.txt"
212
+ git -C "$repo" add main-update.txt
213
+ git -C "$repo" commit -q -m "main update"
214
+ run_expect_state "$repo" "$branch" "blocked-diverged" "no"
215
+
216
+ repo="$(init_repo dirty-chat)"
217
+ session="2026-06-16-22-35-dirty-chat"
218
+ branch="chat/$session"
219
+ create_chat_branch_with_log "$repo" "$session"
220
+ worktree="$(canonical_worktree_path "$repo" "$branch")"
221
+ printf 'dirty\n' > "$worktree/dirty.txt"
222
+ run_expect_state "$repo" "$branch" "blocked-dirty-chat-worktree" "no"
223
+
224
+ repo="$(init_repo missing-log)"
225
+ session="2026-06-16-22-36-missing-log"
226
+ branch="chat/$session"
227
+ git -C "$repo" branch "$branch"
228
+ run_expect_state "$repo" "$branch" "blocked-missing-log" "no"
229
+
230
+ repo="$(init_repo missing-worktree)"
231
+ session="2026-06-16-22-37-missing-worktree"
232
+ branch="chat/$session"
233
+ create_chat_branch_with_log "$repo" "$session"
234
+ worktree="$(canonical_worktree_path "$repo" "$branch")"
235
+ git -C "$repo" worktree remove "$worktree" >/dev/null
236
+ run_expect_state "$repo" "$branch" "blocked-missing-worktree" "no"
237
+
238
+ repo="$(init_repo log-mismatch)"
239
+ session="2026-06-16-22-38-log-mismatch"
240
+ branch="chat/$session"
241
+ create_chat_branch_with_log "$repo" "$session" "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
242
+ run_expect_state "$repo" "$branch" "blocked-log-head-mismatch" "no"
243
+
244
+ echo "local merge readiness verifier smoke test passed."
@@ -0,0 +1,39 @@
1
+ <!-- agentic-artifact:
2
+ schema: agentic-artifact/v2
3
+ id: chat.script.main-refresh.readme
4
+ version: 1
5
+ status: active
6
+ layer: 00.chat
7
+ domain: main-refresh
8
+ disciplines:
9
+ - agentic
10
+ kind: script-domain-readme
11
+ purpose: Explain scripts for refreshing chat branches from local main.
12
+ portability:
13
+ class: required
14
+ targets:
15
+ - llm-workbench
16
+ used_by:
17
+ - id: chat.workflows.chat-refresh-from-main
18
+ path: .agentic/00.chat/workflows/chat-refresh-from-main.md
19
+ - id: chat.script.main-refresh.rehearse-refresh-from-main.readme
20
+ path: scripts/00.chat/main-refresh/rehearse-refresh-from-main/README.md
21
+ -->
22
+ # Main Refresh Scripts
23
+
24
+ Main-refresh scripts help a chat branch catch up with local `main` without
25
+ rewriting history or hiding conflicts.
26
+
27
+ The domain is split into inspection, readiness classification, rehearsal, and
28
+ apply steps. Rehearsal lets the harness discover conflicts in a disposable
29
+ preflight branch/worktree before the real chat branch is changed.
30
+
31
+ Conflict capabilities in this domain:
32
+
33
+ - `classify-conflict/` classifies known main-refresh conflict shapes using the
34
+ governed conflict type standard.
35
+ - `verify-conflict-audit/` checks that conflicted paths have matching
36
+ `## Main Refresh Conflicts` session-log entries before a resolved preflight
37
+ is applied or promoted.
38
+
39
+ These scripts do not push. They coordinate local chat branch refresh behavior.
@@ -0,0 +1,32 @@
1
+ <!-- agentic-artifact:
2
+ schema: agentic-artifact/v2
3
+ id: chat.script.main-refresh.apply-rehearsed-refresh.readme
4
+ version: 1
5
+ status: active
6
+ layer: 00.chat
7
+ domain: main-refresh
8
+ disciplines:
9
+ - agentic
10
+ kind: guide
11
+ purpose: Explain how the harness applies a rehearsed main refresh to a chat branch.
12
+ portability:
13
+ class: required
14
+ targets:
15
+ - llm-workbench
16
+ used_by:
17
+ - id: chat.script.main-refresh.apply-rehearsed-refresh
18
+ path: scripts/00.chat/main-refresh/apply-rehearsed-refresh/script.sh
19
+ -->
20
+ # Apply Rehearsed Refresh
21
+
22
+ This capability answers: the refresh rehearsal worked, so how do we apply that
23
+ tested result to the real chat branch?
24
+
25
+ It fast-forwards the current chat branch to the tested preflight branch, checks
26
+ that the expected commit was applied, removes the temporary preflight worktree,
27
+ deletes the preflight branch, and cleans up stale sibling preflight branches
28
+ when they are already ancestors of the promoted chat branch.
29
+
30
+ It refuses to run if the active chat worktree is dirty, the preflight worktree
31
+ is dirty, the branch is not a preflight branch, or the preflight branch no
32
+ longer descends from the current chat branch.
@@ -0,0 +1,198 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # agentic-artifact:
5
+ # schema: agentic-artifact/v2
6
+ # id: chat.script.main-refresh.apply-rehearsed-refresh
7
+ # version: 1
8
+ # status: active
9
+ # layer: 00.chat
10
+ # domain: main-refresh
11
+ # disciplines:
12
+ # - agentic
13
+ # kind: script
14
+ # purpose: Apply a rehearsed main-refresh branch to the active chat branch.
15
+ # portability:
16
+ # class: required
17
+ # targets:
18
+ # - llm-workbench
19
+ # used_by:
20
+ # - id: chat.workflows.chat-refresh-from-main
21
+ # path: .agentic/00.chat/workflows/chat-refresh-from-main.md
22
+ # - id: chat.standards.main-refresh-conflict-types
23
+ # path: .agentic/00.chat/standards/main-refresh-conflict-types.md
24
+ # effects:
25
+ # - branches
26
+ # - destructive
27
+ # - worktrees
28
+
29
+ usage() {
30
+ cat <<'EOF'
31
+ Usage:
32
+ script.sh <preflight-branch>
33
+
34
+ Fast-forwards the current chat branch to a tested preflight refresh branch,
35
+ then removes the temporary preflight worktree and deletes the preflight branch.
36
+ The current worktree and preflight worktree must both be clean.
37
+ EOF
38
+ }
39
+
40
+ if [ $# -ne 1 ]; then
41
+ usage >&2
42
+ exit 2
43
+ fi
44
+
45
+ PREFLIGHT_BRANCH="$1"
46
+
47
+ case "$PREFLIGHT_BRANCH" in
48
+ agentic/preflight/*/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])
49
+ ;;
50
+ *)
51
+ echo "ERROR: refusing non-preflight branch: ${PREFLIGHT_BRANCH}" >&2
52
+ echo "Expected branch created by rehearse-refresh-from-main." >&2
53
+ exit 1
54
+ ;;
55
+ esac
56
+
57
+ if ! git show-ref --verify --quiet "refs/heads/${PREFLIGHT_BRANCH}"; then
58
+ echo "ERROR: preflight branch does not exist: ${PREFLIGHT_BRANCH}" >&2
59
+ exit 1
60
+ fi
61
+
62
+ preflight_worktrees_for_branch() {
63
+ local branch="$1"
64
+
65
+ git worktree list --porcelain \
66
+ | awk -v branch="refs/heads/${branch}" '
67
+ /^worktree / { path = substr($0, 10) }
68
+ /^branch / && substr($0, 8) == branch { print path }
69
+ '
70
+ }
71
+
72
+ worktree_count() {
73
+ awk 'NF { count += 1 } END { print count + 0 }'
74
+ }
75
+
76
+ cleanup_stale_preflight_siblings() {
77
+ local promoted_branch="$1"
78
+ local prefix="${promoted_branch%/*}/"
79
+ local sibling sibling_worktrees sibling_worktree_count sibling_worktree
80
+
81
+ while IFS= read -r sibling; do
82
+ if [ -z "$sibling" ] || [ "$sibling" = "$promoted_branch" ]; then
83
+ continue
84
+ fi
85
+
86
+ case "$sibling" in
87
+ "$prefix"*)
88
+ ;;
89
+ *)
90
+ continue
91
+ ;;
92
+ esac
93
+
94
+ if ! git merge-base --is-ancestor "$sibling" HEAD; then
95
+ echo "stale_preflight_skipped=${sibling} reason=unique-commits-not-in-promoted-head"
96
+ continue
97
+ fi
98
+
99
+ sibling_worktrees="$(preflight_worktrees_for_branch "$sibling")"
100
+ sibling_worktree_count="$(printf '%s\n' "$sibling_worktrees" | worktree_count)"
101
+
102
+ if [ "$sibling_worktree_count" -gt 1 ]; then
103
+ echo "stale_preflight_skipped=${sibling} reason=multiple-worktrees"
104
+ continue
105
+ fi
106
+
107
+ if [ "$sibling_worktree_count" = "1" ]; then
108
+ sibling_worktree="$(printf '%s\n' "$sibling_worktrees" | awk 'NF { print; exit }')"
109
+ sibling_worktree="$(cd "$sibling_worktree" && pwd -P)"
110
+
111
+ if [ "$sibling_worktree" = "$CURRENT_WORKTREE" ]; then
112
+ echo "stale_preflight_skipped=${sibling} reason=active-worktree"
113
+ continue
114
+ fi
115
+
116
+ if [ -n "$(git -C "$sibling_worktree" status --porcelain)" ]; then
117
+ echo "stale_preflight_skipped=${sibling} reason=dirty-worktree"
118
+ continue
119
+ fi
120
+
121
+ git worktree remove "$sibling_worktree"
122
+ echo "stale_preflight_removed=${sibling} worktree=${sibling_worktree}"
123
+ else
124
+ echo "stale_preflight_removed=${sibling} worktree="
125
+ fi
126
+
127
+ git branch -d "$sibling" >/dev/null
128
+ done < <(git branch --format='%(refname:short)')
129
+ }
130
+
131
+ CURRENT_BRANCH="$(git branch --show-current)"
132
+
133
+ case "$CURRENT_BRANCH" in
134
+ chat/*)
135
+ ;;
136
+ *)
137
+ echo "ERROR: current branch is not a chat branch: ${CURRENT_BRANCH}" >&2
138
+ exit 1
139
+ ;;
140
+ esac
141
+
142
+ if [ -n "$(git status --porcelain)" ]; then
143
+ echo "ERROR: refusing to promote into a dirty chat worktree." >&2
144
+ git status --short >&2
145
+ exit 1
146
+ fi
147
+
148
+ PREFLIGHT_HEAD="$(git rev-parse "$PREFLIGHT_BRANCH")"
149
+
150
+ if ! git merge-base --is-ancestor HEAD "$PREFLIGHT_BRANCH"; then
151
+ echo "ERROR: preflight branch does not descend from current HEAD." >&2
152
+ echo "Current branch may have moved since preflight." >&2
153
+ exit 1
154
+ fi
155
+
156
+ PREFLIGHT_WORKTREES="$(preflight_worktrees_for_branch "$PREFLIGHT_BRANCH")"
157
+
158
+ PREFLIGHT_WORKTREE_COUNT="$(printf '%s\n' "$PREFLIGHT_WORKTREES" | worktree_count)"
159
+
160
+ if [ "$PREFLIGHT_WORKTREE_COUNT" != "1" ]; then
161
+ echo "ERROR: expected exactly one preflight worktree for ${PREFLIGHT_BRANCH}; found ${PREFLIGHT_WORKTREE_COUNT}." >&2
162
+ exit 1
163
+ fi
164
+
165
+ PREFLIGHT_WORKTREE="$(printf '%s\n' "$PREFLIGHT_WORKTREES" | awk 'NF { print; exit }')"
166
+ CURRENT_WORKTREE="$(pwd -P)"
167
+ PREFLIGHT_WORKTREE="$(cd "$PREFLIGHT_WORKTREE" && pwd -P)"
168
+
169
+ if [ "$PREFLIGHT_WORKTREE" = "$CURRENT_WORKTREE" ]; then
170
+ echo "ERROR: refusing to remove the active chat worktree as preflight cleanup." >&2
171
+ exit 1
172
+ fi
173
+
174
+ if [ -n "$(git -C "$PREFLIGHT_WORKTREE" status --porcelain)" ]; then
175
+ echo "ERROR: refusing to clean dirty preflight worktree: ${PREFLIGHT_WORKTREE}" >&2
176
+ git -C "$PREFLIGHT_WORKTREE" status --short >&2
177
+ exit 1
178
+ fi
179
+
180
+ git merge --ff-only "$PREFLIGHT_BRANCH"
181
+
182
+ PROMOTED_COMMIT="$(git rev-parse HEAD)"
183
+
184
+ if [ "$PROMOTED_COMMIT" != "$PREFLIGHT_HEAD" ]; then
185
+ echo "ERROR: apply ended at ${PROMOTED_COMMIT}, expected ${PREFLIGHT_HEAD}." >&2
186
+ exit 1
187
+ fi
188
+
189
+ git worktree remove "$PREFLIGHT_WORKTREE"
190
+ git branch -d "$PREFLIGHT_BRANCH" >/dev/null
191
+ cleanup_stale_preflight_siblings "$PREFLIGHT_BRANCH"
192
+
193
+ echo "Applied rehearsed refresh:"
194
+ echo "current_branch=${CURRENT_BRANCH}"
195
+ echo "preflight_branch=${PREFLIGHT_BRANCH}"
196
+ echo "preflight_worktree=${PREFLIGHT_WORKTREE}"
197
+ echo "applied_commit=${PROMOTED_COMMIT}"
198
+ echo "cleanup_result=removed-worktree-and-deleted-branch"
@@ -0,0 +1,30 @@
1
+ <!-- agentic-artifact:
2
+ schema: agentic-artifact/v2
3
+ id: chat.script.main-refresh.check-chat-is-current-with-main.readme
4
+ version: 1
5
+ status: active
6
+ layer: 00.chat
7
+ domain: main-refresh
8
+ disciplines:
9
+ - agentic
10
+ kind: guide
11
+ purpose: Explain the check that decides whether a chat branch includes local main.
12
+ portability:
13
+ class: required
14
+ targets:
15
+ - llm-workbench
16
+ used_by:
17
+ - id: chat.script.main-refresh.check-chat-is-current-with-main
18
+ path: scripts/00.chat/main-refresh/check-chat-is-current-with-main/script.sh
19
+ -->
20
+ # Check Chat Is Current With Main
21
+
22
+ This read-only capability answers: does this chat branch already include the
23
+ latest local `main`?
24
+
25
+ It reports whether the chat branch is even, fresh-ahead, behind, or diverged
26
+ relative to a base branch, defaulting to `main`. With `--require-fresh`, it
27
+ exits non-zero when the chat branch is behind or diverged.
28
+
29
+ Use this when a workflow needs a simple freshness gate before continuing chat
30
+ work or before local merge/promotion decisions.
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # agentic-artifact:
5
+ # schema: agentic-artifact/v2
6
+ # id: chat.script.main-refresh.check-chat-is-current-with-main
7
+ # version: 1
8
+ # status: active
9
+ # layer: 00.chat
10
+ # domain: main-refresh
11
+ # disciplines:
12
+ # - agentic
13
+ # kind: script
14
+ # purpose: Check whether a chat branch is current with the local base branch.
15
+ # portability:
16
+ # class: required
17
+ # targets:
18
+ # - llm-workbench
19
+ # used_by:
20
+ # - id: harness.architecture.adr.0011-use-chat-owned-worktrees-for-local-convergence
21
+ # - id: harness.script.run-governed-script
22
+ # path: scripts/01.harness/run-governed-script.sh
23
+ # effects:
24
+ # - read-only
25
+
26
+ usage() {
27
+ cat <<'EOF'
28
+ Usage:
29
+ script.sh [--base <branch>] [--require-fresh] [<branch>]
30
+
31
+ Reports whether a chat branch includes the latest local base branch. With
32
+ --require-fresh, exits non-zero when the branch is behind or diverged.
33
+ EOF
34
+ }
35
+
36
+ BASE_BRANCH="main"
37
+ REQUIRE_FRESH="no"
38
+ TARGET_BRANCH=""
39
+
40
+ while [ $# -gt 0 ]; do
41
+ case "$1" in
42
+ --base)
43
+ if [ $# -lt 2 ]; then
44
+ usage >&2
45
+ exit 2
46
+ fi
47
+ BASE_BRANCH="$2"
48
+ shift 2
49
+ ;;
50
+ --require-fresh)
51
+ REQUIRE_FRESH="yes"
52
+ shift
53
+ ;;
54
+ -h|--help)
55
+ usage
56
+ exit 0
57
+ ;;
58
+ *)
59
+ if [ -n "$TARGET_BRANCH" ]; then
60
+ usage >&2
61
+ exit 2
62
+ fi
63
+ TARGET_BRANCH="$1"
64
+ shift
65
+ ;;
66
+ esac
67
+ done
68
+
69
+ if [ -z "$TARGET_BRANCH" ]; then
70
+ TARGET_BRANCH="$(git branch --show-current)"
71
+ fi
72
+
73
+ if [ -z "$TARGET_BRANCH" ]; then
74
+ echo "ERROR: target branch is empty or HEAD is detached." >&2
75
+ exit 1
76
+ fi
77
+
78
+ case "$TARGET_BRANCH" in
79
+ chat/*) ;;
80
+ *)
81
+ echo "ERROR: target branch is not a chat branch: $TARGET_BRANCH" >&2
82
+ exit 1
83
+ ;;
84
+ esac
85
+
86
+ if ! git show-ref --verify --quiet "refs/heads/${BASE_BRANCH}"; then
87
+ echo "ERROR: base branch does not exist: $BASE_BRANCH" >&2
88
+ exit 1
89
+ fi
90
+
91
+ if ! git show-ref --verify --quiet "refs/heads/${TARGET_BRANCH}"; then
92
+ echo "ERROR: target branch does not exist: $TARGET_BRANCH" >&2
93
+ exit 1
94
+ fi
95
+
96
+ ahead="$(git rev-list --count "${BASE_BRANCH}..${TARGET_BRANCH}")"
97
+ behind="$(git rev-list --count "${TARGET_BRANCH}..${BASE_BRANCH}")"
98
+
99
+ echo "Base branch: $BASE_BRANCH"
100
+ echo "Chat branch: $TARGET_BRANCH"
101
+ echo "Ahead of base: $ahead"
102
+ echo "Behind base: $behind"
103
+
104
+ if [ "$behind" = "0" ]; then
105
+ if [ "$ahead" = "0" ]; then
106
+ echo "Freshness: even"
107
+ else
108
+ echo "Freshness: fresh-ahead"
109
+ fi
110
+ exit 0
111
+ fi
112
+
113
+ if [ "$ahead" = "0" ]; then
114
+ echo "Freshness: behind"
115
+ else
116
+ echo "Freshness: diverged"
117
+ fi
118
+
119
+ if [ "$REQUIRE_FRESH" = "yes" ]; then
120
+ exit 1
121
+ fi