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,299 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # agentic-artifact:
5
+ # schema: agentic-artifact/v2
6
+ # id: chat.script.reporting.generate-commit-log-summary
7
+ # version: 1
8
+ # status: active
9
+ # layer: 00.chat
10
+ # domain: reporting
11
+ # disciplines:
12
+ # - agentic
13
+ # kind: script
14
+ # purpose: Generate on-demand aggregate summaries from chat session logs.
15
+ # portability:
16
+ # class: required
17
+ # targets:
18
+ # - llm-workbench
19
+ # used_by:
20
+ # - id: chat.skills.session-summary
21
+ # path: .agentic/00.chat/skills/session-summary.md
22
+ # - id: chat.workflows.chat-reporting
23
+ # path: .agentic/00.chat/workflows/chat-reporting.md
24
+ # effects:
25
+ # - read-only
26
+ # - writes-files
27
+
28
+ usage() {
29
+ cat <<'EOF'
30
+ Usage:
31
+ generate-commit-log-summary.sh [--print|--output <path>]
32
+
33
+ Prints an aggregate summary from individual chat session logs.
34
+ Use --output to write the summary to an explicit on-demand artifact path.
35
+ Do not write commitLogs/README.md.
36
+ EOF
37
+ }
38
+
39
+ OUTPUT_PATH=""
40
+ MODE="print"
41
+
42
+ while [ $# -gt 0 ]; do
43
+ case "$1" in
44
+ --print)
45
+ MODE="print"
46
+ shift
47
+ ;;
48
+ --output)
49
+ if [ $# -lt 2 ]; then
50
+ usage >&2
51
+ exit 2
52
+ fi
53
+ MODE="output"
54
+ OUTPUT_PATH="$2"
55
+ shift 2
56
+ ;;
57
+ -h|--help)
58
+ usage
59
+ exit 0
60
+ ;;
61
+ *)
62
+ usage >&2
63
+ exit 2
64
+ ;;
65
+ esac
66
+ done
67
+
68
+ if [ "$OUTPUT_PATH" = "commitLogs/README.md" ]; then
69
+ echo "ERROR: commitLogs/README.md is not maintained as an aggregate artifact." >&2
70
+ echo "Write on-demand summaries somewhere else, such as /tmp/chat-summary.md." >&2
71
+ exit 1
72
+ fi
73
+
74
+ node - "$MODE" "$OUTPUT_PATH" <<'NODE'
75
+ const fs = require('fs');
76
+ const path = require('path');
77
+
78
+ const mode = process.argv[2];
79
+ const outputPath = process.argv[3];
80
+ const root = 'commitLogs';
81
+ const retiredOutputPath = path.join(root, 'README.md');
82
+
83
+ function walk(dir) {
84
+ if (!fs.existsSync(dir)) {
85
+ return [];
86
+ }
87
+
88
+ return fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
89
+ const entryPath = path.join(dir, entry.name);
90
+ if (entry.isDirectory()) {
91
+ return walk(entryPath);
92
+ }
93
+ if (entry.isFile() && entry.name === 'README.md' && entryPath !== retiredOutputPath) {
94
+ return [entryPath];
95
+ }
96
+ return [];
97
+ });
98
+ }
99
+
100
+ function metadata(content) {
101
+ const match = content.match(/<!-- agentic-session\n([\s\S]*?)\n-->/);
102
+ if (!match) {
103
+ return {};
104
+ }
105
+
106
+ return Object.fromEntries(
107
+ match[1].split('\n').map((line) => {
108
+ const separator = line.indexOf(':');
109
+ if (separator === -1) {
110
+ return null;
111
+ }
112
+ return [
113
+ line.slice(0, separator).trim(),
114
+ line.slice(separator + 1).trim(),
115
+ ];
116
+ }).filter(Boolean),
117
+ );
118
+ }
119
+
120
+ function parseDurationSeconds(value) {
121
+ const match = String(value || '').match(/(\d+)s\b/);
122
+ return match ? Number(match[1]) : null;
123
+ }
124
+
125
+ function parseTokenCount(value) {
126
+ const match = String(value || '').match(/^(\d+)\b/);
127
+ return match ? Number(match[1]) : null;
128
+ }
129
+
130
+ function parseUsdCost(value) {
131
+ const match = String(value || '').match(/^USD\s+(\d+(?:\.\d+)?)\b/);
132
+ return match ? Number(match[1]) : null;
133
+ }
134
+
135
+ function mean(values) {
136
+ return values.reduce((sum, value) => sum + value, 0) / values.length;
137
+ }
138
+
139
+ function standardDeviation(values, average) {
140
+ const variance = values.reduce((sum, value) => {
141
+ return sum + ((value - average) ** 2);
142
+ }, 0) / values.length;
143
+ return Math.sqrt(variance);
144
+ }
145
+
146
+ function quantile(sortedValues, q) {
147
+ if (sortedValues.length === 0) {
148
+ return null;
149
+ }
150
+ if (sortedValues.length === 1) {
151
+ return sortedValues[0];
152
+ }
153
+
154
+ const position = (sortedValues.length - 1) * q;
155
+ const lower = Math.floor(position);
156
+ const upper = Math.ceil(position);
157
+ const weight = position - lower;
158
+
159
+ return sortedValues[lower] * (1 - weight) + sortedValues[upper] * weight;
160
+ }
161
+
162
+ function metricStats(values) {
163
+ const valid = values.filter((value) => Number.isFinite(value));
164
+ if (valid.length === 0) {
165
+ return {
166
+ validCount: 0,
167
+ includedCount: 0,
168
+ outlierCount: 0,
169
+ total: null,
170
+ min: null,
171
+ max: null,
172
+ average: null,
173
+ q1: null,
174
+ median: null,
175
+ q3: null,
176
+ };
177
+ }
178
+
179
+ const average = mean(valid);
180
+ const sd = standardDeviation(valid, average);
181
+ const included = sd === 0
182
+ ? valid
183
+ : valid.filter((value) => Math.abs(value - average) <= 3 * sd);
184
+ const sorted = [...included].sort((a, b) => a - b);
185
+
186
+ return {
187
+ validCount: valid.length,
188
+ includedCount: included.length,
189
+ outlierCount: valid.length - included.length,
190
+ total: included.reduce((sum, value) => sum + value, 0),
191
+ min: sorted[0],
192
+ max: sorted[sorted.length - 1],
193
+ average: mean(included),
194
+ q1: quantile(sorted, 0.25),
195
+ median: quantile(sorted, 0.5),
196
+ q3: quantile(sorted, 0.75),
197
+ };
198
+ }
199
+
200
+ function formatNumber(value) {
201
+ if (value === null || value === undefined || Number.isNaN(value)) {
202
+ return 'n/a';
203
+ }
204
+ return Number.isInteger(value) ? String(value) : value.toFixed(2);
205
+ }
206
+
207
+ function formatUsd(value) {
208
+ if (value === null || value === undefined || Number.isNaN(value)) {
209
+ return 'n/a';
210
+ }
211
+ if (value > 0 && value < 1) {
212
+ return `USD ${value.toFixed(4)}`;
213
+ }
214
+ return `USD ${value.toFixed(2)}`;
215
+ }
216
+
217
+ function formatDuration(value) {
218
+ if (value === null || value === undefined || Number.isNaN(value)) {
219
+ return 'n/a';
220
+ }
221
+
222
+ const rounded = Math.round(value);
223
+ const days = Math.floor(rounded / 86400);
224
+ const hours = Math.floor((rounded % 86400) / 3600);
225
+ const minutes = Math.floor((rounded % 3600) / 60);
226
+ const seconds = rounded % 60;
227
+
228
+ return `${rounded}s (${String(days).padStart(2, '0')}:` +
229
+ `${String(hours).padStart(2, '0')}:` +
230
+ `${String(minutes).padStart(2, '0')}:` +
231
+ `${String(seconds).padStart(2, '0')})`;
232
+ }
233
+
234
+ function metricTable(stats, formatter) {
235
+ return [
236
+ '| Metric | Value |',
237
+ '| --- | ---: |',
238
+ `| Valid chats | ${stats.validCount} |`,
239
+ `| Included chats | ${stats.includedCount} |`,
240
+ `| Outliers excluded | ${stats.outlierCount} |`,
241
+ `| Total | ${formatter(stats.total)} |`,
242
+ `| Min | ${formatter(stats.min)} |`,
243
+ `| Max | ${formatter(stats.max)} |`,
244
+ `| Average | ${formatter(stats.average)} |`,
245
+ `| Q1 | ${formatter(stats.q1)} |`,
246
+ `| Median | ${formatter(stats.median)} |`,
247
+ `| Q3 | ${formatter(stats.q3)} |`,
248
+ ].join('\n');
249
+ }
250
+
251
+ const logs = walk(root).sort();
252
+ const records = logs.map((filePath) => {
253
+ const content = fs.readFileSync(filePath, 'utf8');
254
+ const data = metadata(content);
255
+ return {
256
+ filePath,
257
+ id: data.id || path.basename(path.dirname(filePath)),
258
+ durationSeconds: parseDurationSeconds(data.chat_duration),
259
+ tokens: parseTokenCount(data.estimated_chat_tokens),
260
+ cost: parseUsdCost(data.estimated_chat_cost),
261
+ };
262
+ });
263
+
264
+ const durationStats = metricStats(records.map((record) => record.durationSeconds));
265
+ const tokenStats = metricStats(records.map((record) => record.tokens));
266
+ const costStats = metricStats(records.map((record) => record.cost));
267
+
268
+ const lines = [
269
+ '# Commit Log Summary',
270
+ '',
271
+ `Total chats: ${records.length}`,
272
+ '',
273
+ 'Outliers are values more than 3 standard deviations from the mean for each metric.',
274
+ '',
275
+ '## Chat Duration',
276
+ '',
277
+ metricTable(durationStats, formatDuration),
278
+ '',
279
+ '## Estimated Chat Tokens',
280
+ '',
281
+ metricTable(tokenStats, formatNumber),
282
+ '',
283
+ '## Estimated Chat Cost',
284
+ '',
285
+ metricTable(costStats, formatUsd),
286
+ '',
287
+ ];
288
+
289
+ const output = lines.join('\n');
290
+
291
+ if (mode === 'print') {
292
+ process.stdout.write(output);
293
+ process.exit(0);
294
+ }
295
+
296
+ fs.mkdirSync(path.dirname(outputPath), { recursive: true });
297
+ fs.writeFileSync(outputPath, output);
298
+ console.log(`Wrote ${outputPath}`);
299
+ NODE
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # agentic-artifact:
5
+ # schema: agentic-artifact/v2
6
+ # id: chat.script.reporting.generate-commit-log-summary.smoke-test
7
+ # version: 1
8
+ # status: active
9
+ # layer: 00.chat
10
+ # domain: validation
11
+ # disciplines:
12
+ # - agentic
13
+ # kind: script
14
+ # purpose: Smoke test on-demand chat commit log summary generation.
15
+ # portability:
16
+ # class: reusable
17
+ # targets:
18
+ # - llm-workbench
19
+ # used_by:
20
+ # - id: chat.workflows.chat-reporting
21
+ # path: .agentic/00.chat/workflows/chat-reporting.md
22
+ # effects:
23
+ # - writes-files
24
+
25
+ fail() {
26
+ echo "FAIL: $*" >&2
27
+ exit 1
28
+ }
29
+
30
+ SOURCE_ROOT="$(git rev-parse --show-toplevel)"
31
+ TMP_ROOT="$(mktemp -d "${TMPDIR:-/tmp}/commit-log-summary-smoke.XXXXXX")"
32
+
33
+ cleanup() {
34
+ rm -rf "$TMP_ROOT"
35
+ }
36
+
37
+ trap cleanup EXIT
38
+
39
+ REPO="$TMP_ROOT/repo"
40
+ mkdir -p "$REPO/scripts/00.chat/reporting/generate-commit-log-summary" "$REPO/commitLogs/2026/jun/17/test-chat"
41
+ cp "$SOURCE_ROOT/scripts/00.chat/reporting/generate-commit-log-summary/script.sh" \
42
+ "$REPO/scripts/00.chat/reporting/generate-commit-log-summary/script.sh"
43
+
44
+ cat > "$REPO/commitLogs/2026/jun/17/test-chat/README.md" <<'EOF'
45
+ # Chat Session: test-chat
46
+
47
+ <!-- agentic-session
48
+ id: test-chat
49
+ chat_duration: 42s
50
+ estimated_chat_tokens: 100 tokens
51
+ estimated_chat_cost: USD 0.0030 estimated from estimated_chat_tokens
52
+ -->
53
+ EOF
54
+
55
+ (
56
+ cd "$REPO"
57
+ bash scripts/00.chat/reporting/generate-commit-log-summary/script.sh > "$TMP_ROOT/printed.md"
58
+ bash scripts/00.chat/reporting/generate-commit-log-summary/script.sh --output "$TMP_ROOT/written.md" >/dev/null
59
+ )
60
+
61
+ if ! cmp -s "$TMP_ROOT/written.md" "$TMP_ROOT/printed.md"; then
62
+ fail "printed output did not match explicit output file"
63
+ fi
64
+
65
+ set +e
66
+ (
67
+ cd "$REPO"
68
+ bash scripts/00.chat/reporting/generate-commit-log-summary/script.sh --output commitLogs/README.md
69
+ ) >/dev/null 2>"$TMP_ROOT/blocked.err"
70
+ BLOCKED_STATUS="$?"
71
+ set -e
72
+
73
+ if [ "$BLOCKED_STATUS" -eq 0 ]; then
74
+ fail "script allowed writing commitLogs/README.md"
75
+ fi
76
+
77
+ if ! grep -q "not maintained" "$TMP_ROOT/blocked.err"; then
78
+ fail "script did not explain retired aggregate path"
79
+ fi
80
+
81
+ if ! grep -q "Estimated Chat Tokens" "$TMP_ROOT/printed.md"; then
82
+ fail "summary did not use estimated chat token heading"
83
+ fi
84
+
85
+ if ! grep -q "Estimated Chat Cost" "$TMP_ROOT/printed.md"; then
86
+ fail "summary did not use estimated chat cost heading"
87
+ fi
88
+
89
+ if ! grep -q '| Total | USD 0.0030 |' "$TMP_ROOT/printed.md"; then
90
+ fail "summary did not aggregate estimated chat cost"
91
+ fi
92
+
93
+ echo "commit log summary smoke test passed."
@@ -0,0 +1,32 @@
1
+ <!-- agentic-artifact:
2
+ schema: agentic-artifact/v2
3
+ id: chat.script.reporting.report-chat-workspaces.readme
4
+ version: 1
5
+ status: active
6
+ layer: 00.chat
7
+ domain: reporting
8
+ disciplines:
9
+ - agentic
10
+ kind: capability-readme
11
+ purpose: Explain chat branch and worktree status reporting.
12
+ portability:
13
+ class: required
14
+ targets:
15
+ - llm-workbench
16
+ used_by:
17
+ - id: chat.workflows.chat-cleanup
18
+ path: .agentic/00.chat/workflows/chat-cleanup.md
19
+ - id: chat.script.reporting.report-chat-workspaces
20
+ path: scripts/00.chat/reporting/report-chat-workspaces/script.sh
21
+ -->
22
+ # Report Chat Workspaces
23
+
24
+ `script.sh` prints a table of local `chat/*` branches, ahead/behind state,
25
+ recorded log head state, and worktree path.
26
+
27
+ Use this before cleanup or promotion when a human needs to understand which
28
+ chat branches are active, stale, missing logs, or checked out elsewhere.
29
+
30
+ The script is read-only. It does not delete branches, clean worktrees, merge,
31
+ or push.
32
+
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # agentic-artifact:
5
+ # schema: agentic-artifact/v2
6
+ # id: chat.script.reporting.report-chat-workspaces
7
+ # version: 1
8
+ # status: active
9
+ # layer: 00.chat
10
+ # domain: reporting
11
+ # disciplines:
12
+ # - agentic
13
+ # kind: script
14
+ # purpose: Report chat branches, log head state, and worktree status.
15
+ # portability:
16
+ # class: required
17
+ # targets:
18
+ # - llm-workbench
19
+ # used_by:
20
+ # - id: chat.workflows.chat-cleanup
21
+ # path: .agentic/00.chat/workflows/chat-cleanup.md
22
+ # - id: chat.workflows.chat-promote-to-main
23
+ # path: .agentic/00.chat/workflows/chat-promote-to-main.md
24
+ # effects:
25
+ # - read-only
26
+
27
+ BASE_BRANCH="${1:-main}"
28
+
29
+ REPO_ROOT="$(git rev-parse --show-toplevel)"
30
+ REPO_ROOT="$(cd "$REPO_ROOT" && pwd -P)"
31
+
32
+ # shellcheck source=../../worktree/paths/lib.sh
33
+ source "$REPO_ROOT/scripts/00.chat/worktree/paths/lib.sh"
34
+ # shellcheck source=../../session-log/paths/lib.sh
35
+ source "$REPO_ROOT/scripts/00.chat/session-log/paths/lib.sh"
36
+
37
+ if ! git -C "$REPO_ROOT" show-ref --verify --quiet "refs/heads/${BASE_BRANCH}"; then
38
+ echo "ERROR: base branch does not exist: $BASE_BRANCH" >&2
39
+ exit 1
40
+ fi
41
+
42
+ printf 'Base branch: %s\n' "$BASE_BRANCH"
43
+ printf '%-64s %-8s %-8s %-8s %-10s %s\n' "branch" "ahead" "behind" "status" "log-head" "worktree"
44
+
45
+ git -C "$REPO_ROOT" branch --format='%(refname:short)' | while IFS= read -r branch; do
46
+ case "$branch" in
47
+ chat/*) ;;
48
+ *) continue ;;
49
+ esac
50
+
51
+ session_id="${branch#chat/}"
52
+ log_file="$(chat_log_file_for_session "$session_id")"
53
+ branch_head="$(git -C "$REPO_ROOT" rev-parse --short "$branch")"
54
+ recorded_head=""
55
+ log_head_state="missing"
56
+
57
+ if [ -f "$log_file" ]; then
58
+ recorded_head="$(chat_worktree_metadata_value "$log_file" "latest_commit_sha")"
59
+ if [ -z "${recorded_head// }" ]; then
60
+ log_head_state="unrecorded"
61
+ elif [ "${recorded_head:0:7}" = "$branch_head" ]; then
62
+ log_head_state="matches"
63
+ else
64
+ log_head_state="differs"
65
+ fi
66
+ fi
67
+
68
+ ahead="$(git -C "$REPO_ROOT" rev-list --count "${BASE_BRANCH}..${branch}")"
69
+ behind="$(git -C "$REPO_ROOT" rev-list --count "${branch}..${BASE_BRANCH}")"
70
+ worktree_path="$(chat_worktree_path_for_branch "$REPO_ROOT" "$branch")"
71
+ status="absent"
72
+
73
+ if [ -d "$worktree_path/.git" ] || git -C "$worktree_path" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
74
+ if [ -z "$(git -C "$worktree_path" status --porcelain)" ]; then
75
+ status="clean"
76
+ else
77
+ status="dirty"
78
+ fi
79
+ fi
80
+
81
+ printf '%-64s %-8s %-8s %-8s %-10s %s\n' "$branch" "$ahead" "$behind" "$status" "$log_head_state" "$worktree_path"
82
+ done
@@ -0,0 +1,33 @@
1
+ <!-- agentic-artifact:
2
+ schema: agentic-artifact/v2
3
+ id: chat.script.session-log.readme
4
+ version: 1
5
+ status: active
6
+ layer: 00.chat
7
+ domain: session-log
8
+ disciplines:
9
+ - agentic
10
+ kind: script-domain-readme
11
+ purpose: Explain session-log scripts for durable chat evidence.
12
+ portability:
13
+ class: required
14
+ targets:
15
+ - llm-workbench
16
+ used_by:
17
+ - id: chat.checklists.before-commit
18
+ path: .agentic/00.chat/checklists/before-commit.md
19
+ - id: chat.script.session-log.record-chat-commit.readme
20
+ path: scripts/00.chat/session-log/record-chat-commit/README.md
21
+ -->
22
+ # Session Log Scripts
23
+
24
+ Session-log scripts read and update the durable evidence for a chat. The
25
+ session log records task intent, branch/worktree metadata, workflow routing,
26
+ activity, decisions, issues, commits, conflicts, and metrics.
27
+
28
+ These scripts are part of why chats are auditable. They should update only the
29
+ current chat's log unless a workflow explicitly says otherwise.
30
+
31
+ The helper libraries in this domain provide shared path and metadata parsing
32
+ for other chat capabilities.
33
+
@@ -0,0 +1,89 @@
1
+ <!-- agentic-artifact:
2
+ schema: agentic-artifact/v2
3
+ id: chat.script.session-log.check-commit-prerequisites.readme
4
+ version: 1
5
+ status: active
6
+ layer: 00.chat
7
+ domain: session-log
8
+ disciplines:
9
+ - agentic
10
+ kind: capability-readme
11
+ purpose: Explain how commit prerequisite checks verify workflow and gate references
12
+ before chat commits.
13
+ portability:
14
+ class: required
15
+ targets:
16
+ - llm-workbench
17
+ used_by:
18
+ - id: chat.script.session-log.check-commit-prerequisites
19
+ path: scripts/00.chat/session-log/check-commit-prerequisites/script.sh
20
+ - id: chat.script.session-log.check-commit-prerequisites.smoke-test
21
+ path: scripts/00.chat/session-log/check-commit-prerequisites/smoke-test.sh
22
+ - id: harness.architecture.adr.0017-organize-scripts-by-owner-domain-and-capability
23
+ -->
24
+ # Check Commit Prerequisites
25
+
26
+ `script.sh` verifies that the current chat session points at real governance
27
+ artifacts before a task commit proceeds.
28
+
29
+ It is a structural readiness check. It does not decide whether the code change
30
+ is good. It checks that the session log, declared workflow, canonical checklist,
31
+ and referenced gate scripts are present so the commit boundary is governed by
32
+ real files rather than stale documentation.
33
+
34
+ ## Mental Model
35
+
36
+ A chat session is only committable if its process map still resolves.
37
+
38
+ The session log names a workflow. The workflow and before-commit checklist name
39
+ scripts that should exist. If any of those links are broken, the agent might be
40
+ following a workflow that cannot actually run.
41
+
42
+ This gate catches that problem before the task commit.
43
+
44
+ ## Checks
45
+
46
+ The script verifies:
47
+
48
+ - current branch is a `chat/*` branch
49
+ - matching session log exists
50
+ - session metadata includes a `workflow`
51
+ - declared workflow file exists
52
+ - canonical `.agentic/00.chat/checklists/before-commit.md` exists
53
+ - executable script references in the workflow and checklist point to real
54
+ `.sh` files
55
+
56
+ Directory prose such as `scripts/00.chat/` is ignored; only script-looking
57
+ references ending in `.sh` are treated as gate references.
58
+
59
+ ## What This Does Not Do
60
+
61
+ - It does not run every referenced gate.
62
+ - It does not inspect code quality.
63
+ - It does not stage, commit, merge, or push.
64
+ - It does not validate ADR disposition content.
65
+ - It does not replace `prepare-chat-session-before-commit`; it is one gate that
66
+ the readiness coordinator runs.
67
+
68
+ ## Validation
69
+
70
+ `smoke-test.sh` builds a throwaway chat repo and verifies that:
71
+
72
+ - a valid workflow/checklist setup passes
73
+ - prose directory references are not mistaken for missing scripts
74
+
75
+ Run the canonical smoke test with:
76
+
77
+ ```bash
78
+ bash scripts/00.chat/session-log/check-commit-prerequisites/smoke-test.sh
79
+ ```
80
+
81
+ ## Compatibility
82
+
83
+ The old shared path remains available:
84
+
85
+ ```bash
86
+ scripts/00.chat/session-log/check-commit-prerequisites/script.sh
87
+ ```
88
+
89
+ That file is now a compatibility wrapper around the canonical implementation.