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.
- package/.agentic/00.chat/README.md +78 -0
- package/.agentic/00.chat/checklists/before-commit.md +195 -0
- package/.agentic/00.chat/checklists/llm-workbench-public-beta.md +94 -0
- package/.agentic/00.chat/commands/README.md +108 -0
- package/.agentic/00.chat/migration-plan.md +132 -0
- package/.agentic/00.chat/skills/session-summary.md +48 -0
- package/.agentic/00.chat/standards/llm-workbench-public-beta-contract.md +216 -0
- package/.agentic/00.chat/standards/main-refresh-conflict-types.md +358 -0
- package/.agentic/00.chat/workflows/README.md +40 -0
- package/.agentic/00.chat/workflows/bootstrap-chat-workbench-repo.md +212 -0
- package/.agentic/00.chat/workflows/chat-cleanup.md +102 -0
- package/.agentic/00.chat/workflows/chat-commit.md +56 -0
- package/.agentic/00.chat/workflows/chat-promote-to-main.md +169 -0
- package/.agentic/00.chat/workflows/chat-refresh-from-main.md +242 -0
- package/.agentic/00.chat/workflows/chat-reporting.md +69 -0
- package/.agentic/00.chat/workflows/chat-start.md +173 -0
- package/.agentic/00.chat/workflows/chat-upstream-reusable-lesson.md +123 -0
- package/.agentic/shared/standards/README.md +32 -0
- package/.agentic/shared/standards/upstream-repo-bootstrap.md +131 -0
- package/.agentic/shared/workflows/README.md +35 -0
- package/.agentic/shared/workflows/capability-resolution-workflow.md +189 -0
- package/.agentic/shared/workflows/change-shared-process.md +92 -0
- package/.cursor/rules/llm-workbench.mdc +17 -0
- package/.github/copilot-instructions.md +16 -0
- package/AGENTS.md +63 -0
- package/CLAUDE.md +16 -0
- package/CONTRIBUTING.md +57 -0
- package/LICENSE +21 -0
- package/LLM_WORKBENCH.md +17 -0
- package/README.md +98 -0
- package/SECURITY.md +44 -0
- package/bin/llm-workbench.js +672 -0
- package/docs/00.chat/README.md +47 -0
- package/docs/00.chat/llm-workbench-acceptance-matrix.md +55 -0
- package/docs/00.chat/script-layout.md +107 -0
- package/docs/adapting-to-your-repo.md +29 -0
- package/docs/concepts.md +38 -0
- package/docs/install.md +114 -0
- package/docs/public-beta-contract.md +45 -0
- package/docs/workflows.md +103 -0
- package/examples/minimal-repo/README.md +13 -0
- package/package.json +93 -0
- package/scripts/00.chat/README.md +46 -0
- package/scripts/00.chat/bootstrap/README.md +35 -0
- package/scripts/00.chat/bootstrap/audit-chat-bootstrap-file-set/README.md +39 -0
- package/scripts/00.chat/bootstrap/audit-chat-bootstrap-file-set/script.sh +213 -0
- package/scripts/00.chat/closeout/README.md +30 -0
- package/scripts/00.chat/closeout/build-closeout-prompt/README.md +35 -0
- package/scripts/00.chat/closeout/build-closeout-prompt/script.sh +124 -0
- package/scripts/00.chat/command/README.md +31 -0
- package/scripts/00.chat/command/close/README.md +30 -0
- package/scripts/00.chat/command/close/script.sh +25 -0
- package/scripts/00.chat/command/dispatcher/README.md +46 -0
- package/scripts/00.chat/command/dispatcher/script.sh +91 -0
- package/scripts/00.chat/command/dispatcher/smoke-test.sh +168 -0
- package/scripts/00.chat/command/new/README.md +32 -0
- package/scripts/00.chat/command/new/script.sh +28 -0
- package/scripts/00.chat/command/open-window/README.md +38 -0
- package/scripts/00.chat/command/open-window/script.sh +25 -0
- package/scripts/00.chat/command/package-scripts/README.md +34 -0
- package/scripts/00.chat/command/package-scripts/smoke-test.sh +113 -0
- package/scripts/00.chat/git/README.md +30 -0
- package/scripts/00.chat/git/cleanup-empty-chat-branches/README.md +36 -0
- package/scripts/00.chat/git/cleanup-empty-chat-branches/script.sh +243 -0
- package/scripts/00.chat/git/cleanup-empty-chat-branches/smoke-test.sh +136 -0
- package/scripts/00.chat/local-merge/README.md +30 -0
- package/scripts/00.chat/local-merge/list-active-chat-branches/README.md +29 -0
- package/scripts/00.chat/local-merge/list-active-chat-branches/script.sh +109 -0
- package/scripts/00.chat/local-merge/report-chat-branch-overlaps/README.md +29 -0
- package/scripts/00.chat/local-merge/report-chat-branch-overlaps/script.sh +142 -0
- package/scripts/00.chat/local-merge/verify-chat-ready-to-merge-local-main/README.md +33 -0
- package/scripts/00.chat/local-merge/verify-chat-ready-to-merge-local-main/script.sh +345 -0
- package/scripts/00.chat/local-merge/verify-chat-ready-to-merge-local-main/smoke-test.sh +244 -0
- package/scripts/00.chat/main-refresh/README.md +39 -0
- package/scripts/00.chat/main-refresh/apply-rehearsed-refresh/README.md +32 -0
- package/scripts/00.chat/main-refresh/apply-rehearsed-refresh/script.sh +198 -0
- package/scripts/00.chat/main-refresh/check-chat-is-current-with-main/README.md +30 -0
- package/scripts/00.chat/main-refresh/check-chat-is-current-with-main/script.sh +121 -0
- package/scripts/00.chat/main-refresh/classify-conflict/README.md +39 -0
- package/scripts/00.chat/main-refresh/classify-conflict/script.sh +169 -0
- package/scripts/00.chat/main-refresh/classify-conflict/smoke-test.sh +137 -0
- package/scripts/00.chat/main-refresh/classify-refresh-readiness/README.md +35 -0
- package/scripts/00.chat/main-refresh/classify-refresh-readiness/script.sh +171 -0
- package/scripts/00.chat/main-refresh/classify-refresh-readiness/smoke-test.sh +132 -0
- package/scripts/00.chat/main-refresh/rehearse-refresh-from-main/README.md +34 -0
- package/scripts/00.chat/main-refresh/rehearse-refresh-from-main/script.sh +124 -0
- package/scripts/00.chat/main-refresh/rehearse-refresh-from-main/smoke-test.sh +257 -0
- package/scripts/00.chat/main-refresh/show-main-update-status/README.md +31 -0
- package/scripts/00.chat/main-refresh/show-main-update-status/script.sh +73 -0
- package/scripts/00.chat/main-refresh/verify-conflict-audit/README.md +37 -0
- package/scripts/00.chat/main-refresh/verify-conflict-audit/script.sh +154 -0
- package/scripts/00.chat/main-refresh/verify-conflict-audit/smoke-test.sh +99 -0
- package/scripts/00.chat/metrics/README.md +35 -0
- package/scripts/00.chat/metrics/data/chat-pricing.json +107 -0
- package/scripts/00.chat/metrics/data/chat-pricing.schema.json +63 -0
- package/scripts/00.chat/metrics/estimate-chat-cost/README.md +40 -0
- package/scripts/00.chat/metrics/estimate-chat-cost/script.js +130 -0
- package/scripts/00.chat/migration/README.md +30 -0
- package/scripts/00.chat/migration/audit-chat-layer-migration/README.md +33 -0
- package/scripts/00.chat/migration/audit-chat-layer-migration/script.sh +127 -0
- package/scripts/00.chat/recovery/README.md +30 -0
- package/scripts/00.chat/recovery/import-active-paths-to-chat-worktree/README.md +76 -0
- package/scripts/00.chat/recovery/import-active-paths-to-chat-worktree/script.sh +212 -0
- package/scripts/00.chat/recovery/import-active-paths-to-chat-worktree/smoke-test.sh +162 -0
- package/scripts/00.chat/reporting/README.md +30 -0
- package/scripts/00.chat/reporting/generate-commit-log-summary/README.md +35 -0
- package/scripts/00.chat/reporting/generate-commit-log-summary/script.sh +299 -0
- package/scripts/00.chat/reporting/generate-commit-log-summary/smoke-test.sh +93 -0
- package/scripts/00.chat/reporting/report-chat-workspaces/README.md +32 -0
- package/scripts/00.chat/reporting/report-chat-workspaces/script.sh +82 -0
- package/scripts/00.chat/session-log/README.md +33 -0
- package/scripts/00.chat/session-log/check-commit-prerequisites/README.md +89 -0
- package/scripts/00.chat/session-log/check-commit-prerequisites/script.sh +121 -0
- package/scripts/00.chat/session-log/check-commit-prerequisites/smoke-test.sh +119 -0
- package/scripts/00.chat/session-log/check-commitlog-deletions/README.md +90 -0
- package/scripts/00.chat/session-log/check-commitlog-deletions/script.sh +131 -0
- package/scripts/00.chat/session-log/check-commitlog-deletions/smoke-test.sh +123 -0
- package/scripts/00.chat/session-log/checkpoint-chat-session-log/README.md +98 -0
- package/scripts/00.chat/session-log/checkpoint-chat-session-log/script.sh +126 -0
- package/scripts/00.chat/session-log/paths/README.md +38 -0
- package/scripts/00.chat/session-log/paths/lib.sh +133 -0
- package/scripts/00.chat/session-log/prepare-chat-session-before-commit/README.md +90 -0
- package/scripts/00.chat/session-log/prepare-chat-session-before-commit/script.sh +145 -0
- package/scripts/00.chat/session-log/read-current-chat-log/README.md +44 -0
- package/scripts/00.chat/session-log/read-current-chat-log/script.sh +92 -0
- package/scripts/00.chat/session-log/read-current-chat-log/smoke-test.sh +127 -0
- package/scripts/00.chat/session-log/record-chat-commit/README.md +133 -0
- package/scripts/00.chat/session-log/record-chat-commit/script.sh +394 -0
- package/scripts/00.chat/session-log/record-chat-commit/smoke-test.sh +227 -0
- package/scripts/00.chat/session-log/record-main-refresh-conflict/README.md +34 -0
- package/scripts/00.chat/session-log/record-main-refresh-conflict/script.sh +239 -0
- package/scripts/00.chat/session-log/rename-current-chat-log-folder/README.md +32 -0
- package/scripts/00.chat/session-log/rename-current-chat-log-folder/script.sh +112 -0
- package/scripts/00.chat/session-log/update-chat-log/README.md +32 -0
- package/scripts/00.chat/session-log/update-chat-log/script.sh +294 -0
- package/scripts/00.chat/startup/README.md +37 -0
- package/scripts/00.chat/startup/auto-start-missing-session/README.md +113 -0
- package/scripts/00.chat/startup/auto-start-missing-session/script.sh +54 -0
- package/scripts/00.chat/startup/resolve-current-chat-session/README.md +57 -0
- package/scripts/00.chat/startup/resolve-current-chat-session/script.sh +47 -0
- package/scripts/00.chat/startup/resolve-current-chat-session/smoke-test.sh +130 -0
- package/scripts/00.chat/startup/start-chat-session/README.md +197 -0
- package/scripts/00.chat/startup/start-chat-session/script.sh +330 -0
- package/scripts/00.chat/startup/start-chat-session/smoke-test.sh +182 -0
- package/scripts/00.chat/startup/start-new-chat/README.md +31 -0
- package/scripts/00.chat/startup/start-new-chat/script.sh +29 -0
- package/scripts/00.chat/transcript/README.md +36 -0
- package/scripts/00.chat/transcript/discover-codex-session-log/README.md +32 -0
- package/scripts/00.chat/transcript/discover-codex-session-log/script.sh +106 -0
- package/scripts/00.chat/transcript/register-codex-session-log/README.md +32 -0
- package/scripts/00.chat/transcript/register-codex-session-log/script.sh +115 -0
- package/scripts/00.chat/worktree/README.md +32 -0
- package/scripts/00.chat/worktree/check-write-location/README.md +87 -0
- package/scripts/00.chat/worktree/check-write-location/script.sh +95 -0
- package/scripts/00.chat/worktree/dirty-worktree-check/README.md +77 -0
- package/scripts/00.chat/worktree/dirty-worktree-check/script.sh +93 -0
- package/scripts/00.chat/worktree/ensure-chat-worktree/README.md +33 -0
- package/scripts/00.chat/worktree/ensure-chat-worktree/script.sh +132 -0
- package/scripts/00.chat/worktree/open-window/README.md +34 -0
- package/scripts/00.chat/worktree/open-window/script.sh +131 -0
- package/scripts/00.chat/worktree/paths/README.md +32 -0
- package/scripts/00.chat/worktree/paths/lib.sh +71 -0
- package/scripts/01.harness/artifact-metadata/check-headers/script.sh +522 -0
- package/scripts/01.harness/artifact-metadata/check-headers/smoke-test.sh +48 -0
- package/scripts/01.harness/check-deterministic-process-drift.sh +416 -0
- package/scripts/01.harness/check-governed-script-command-drift.sh +184 -0
- package/scripts/01.harness/run-governed-script.sh +178 -0
- package/scripts/install.sh +503 -0
- package/scripts/uninstall.sh +199 -0
- package/tests/smoke-test-install.sh +70 -0
|
@@ -0,0 +1,672 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('node:fs');
|
|
5
|
+
const path = require('node:path');
|
|
6
|
+
const { spawnSync } = require('node:child_process');
|
|
7
|
+
|
|
8
|
+
const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
9
|
+
const INSTALL_SCRIPT = path.join(PACKAGE_ROOT, 'scripts', 'install.sh');
|
|
10
|
+
|
|
11
|
+
const INSTALLED_MANIFEST = path.join('.llm-workbench', 'install-manifest.tsv');
|
|
12
|
+
const DISPATCHER_SCRIPT = path.join('scripts', '00.chat', 'command', 'dispatcher', 'script.sh');
|
|
13
|
+
const NEW_COMMAND_SCRIPT = path.join('scripts', '00.chat', 'command', 'new', 'script.sh');
|
|
14
|
+
const START_NEW_CHAT_SCRIPT = path.join('scripts', '00.chat', 'startup', 'start-new-chat', 'script.sh');
|
|
15
|
+
const START_CHAT_SESSION_SCRIPT = path.join('scripts', '00.chat', 'startup', 'start-chat-session', 'script.sh');
|
|
16
|
+
const CHECK_WRITE_LOCATION_SCRIPT = path.join('scripts', '00.chat', 'worktree', 'check-write-location', 'script.sh');
|
|
17
|
+
const CHECK_COMMIT_PREREQUISITES_SCRIPT = path.join('scripts', '00.chat', 'session-log', 'check-commit-prerequisites', 'script.sh');
|
|
18
|
+
const PREPARE_COMMIT_SCRIPT = path.join('scripts', '00.chat', 'session-log', 'prepare-chat-session-before-commit', 'script.sh');
|
|
19
|
+
const RECORD_CHAT_COMMIT_SCRIPT = path.join('scripts', '00.chat', 'session-log', 'record-chat-commit', 'script.sh');
|
|
20
|
+
const CHECKPOINT_CHAT_SESSION_LOG_SCRIPT = path.join('scripts', '00.chat', 'session-log', 'checkpoint-chat-session-log', 'script.sh');
|
|
21
|
+
const VERIFY_MERGE_READY_SCRIPT = path.join('scripts', '00.chat', 'local-merge', 'verify-chat-ready-to-merge-local-main', 'script.sh');
|
|
22
|
+
const LIST_ACTIVE_CHAT_BRANCHES_SCRIPT = path.join('scripts', '00.chat', 'local-merge', 'list-active-chat-branches', 'script.sh');
|
|
23
|
+
|
|
24
|
+
function printHelp(stream = process.stdout) {
|
|
25
|
+
stream.write(`llm-wb
|
|
26
|
+
|
|
27
|
+
Usage:
|
|
28
|
+
llm-wb <command> [options]
|
|
29
|
+
|
|
30
|
+
Commands:
|
|
31
|
+
init [--target <repo>] [--dry-run|--apply] [--init-commit]
|
|
32
|
+
Install the workbench harness into a Git repo. Defaults to the current repo.
|
|
33
|
+
|
|
34
|
+
list
|
|
35
|
+
List available installed chat commands from the current Git repo.
|
|
36
|
+
|
|
37
|
+
new [--json] "prompt"
|
|
38
|
+
Start a new governed chat session using the installed chat:new flow.
|
|
39
|
+
|
|
40
|
+
sessions list [--base <branch>]
|
|
41
|
+
List active chat sessions/branches using the current Git repo.
|
|
42
|
+
|
|
43
|
+
commit -m "message" [--summary <text>] [--adr-impact <text>]
|
|
44
|
+
Safely commit current chat work, record it, and checkpoint session evidence.
|
|
45
|
+
|
|
46
|
+
merge-main [--base <branch>] [chat-branch]
|
|
47
|
+
Verify and locally merge a completed chat branch into local main.
|
|
48
|
+
|
|
49
|
+
help
|
|
50
|
+
Show this help.
|
|
51
|
+
|
|
52
|
+
Examples:
|
|
53
|
+
llm-wb init --dry-run
|
|
54
|
+
llm-wb init --target /path/to/repo
|
|
55
|
+
llm-wb new "implement the checkout flow"
|
|
56
|
+
llm-wb sessions list
|
|
57
|
+
llm-wb commit -m "Implement checkout flow"
|
|
58
|
+
llm-wb merge-main
|
|
59
|
+
llm-wb list
|
|
60
|
+
`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function printSessionsHelp(stream = process.stdout) {
|
|
64
|
+
stream.write(`llm-wb sessions
|
|
65
|
+
|
|
66
|
+
Usage:
|
|
67
|
+
llm-wb sessions list [--base <branch>]
|
|
68
|
+
|
|
69
|
+
Commands:
|
|
70
|
+
list
|
|
71
|
+
List active chat sessions/branches using the existing local-merge report.
|
|
72
|
+
`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function fail(message, exitCode = 1, showHelp = false) {
|
|
76
|
+
console.error(`ERROR: ${message}`);
|
|
77
|
+
if (showHelp) {
|
|
78
|
+
console.error('');
|
|
79
|
+
printHelp(process.stderr);
|
|
80
|
+
}
|
|
81
|
+
process.exit(exitCode);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function relativeMissing(paths) {
|
|
85
|
+
return paths.map((filePath) => ` ${filePath}`).join('\n');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function run(command, args, options = {}) {
|
|
89
|
+
const result = spawnSync(command, args, {
|
|
90
|
+
cwd: options.cwd || process.cwd(),
|
|
91
|
+
env: options.env || process.env,
|
|
92
|
+
stdio: 'inherit',
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
if (result.error) {
|
|
96
|
+
fail(`failed to run ${command}: ${result.error.message}`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (result.signal) {
|
|
100
|
+
fail(`${command} exited after signal ${result.signal}`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
process.exit(result.status === null ? 1 : result.status);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function runChecked(command, args, options = {}) {
|
|
107
|
+
const result = spawnSync(command, args, {
|
|
108
|
+
cwd: options.cwd || process.cwd(),
|
|
109
|
+
env: options.env || process.env,
|
|
110
|
+
stdio: options.stdio || 'inherit',
|
|
111
|
+
encoding: options.encoding,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
if (result.error) {
|
|
115
|
+
fail(`failed to run ${command}: ${result.error.message}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (result.signal) {
|
|
119
|
+
fail(`${command} exited after signal ${result.signal}`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (result.status !== 0) {
|
|
123
|
+
process.exit(result.status === null ? 1 : result.status);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function capture(command, args, options = {}) {
|
|
130
|
+
const result = spawnSync(command, args, {
|
|
131
|
+
cwd: options.cwd || process.cwd(),
|
|
132
|
+
env: options.env || process.env,
|
|
133
|
+
encoding: 'utf8',
|
|
134
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
if (result.error) {
|
|
138
|
+
fail(`failed to run ${command}: ${result.error.message}`);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (result.status !== 0) {
|
|
142
|
+
const detail = (result.stderr || result.stdout || '').trim();
|
|
143
|
+
fail(detail || `${command} exited with status ${result.status}`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return result.stdout.trim();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function gitRoot(startPath) {
|
|
150
|
+
const result = spawnSync('git', ['-C', startPath, 'rev-parse', '--show-toplevel'], {
|
|
151
|
+
encoding: 'utf8',
|
|
152
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
if (result.status !== 0) {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return path.resolve(result.stdout.trim());
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function requireGitRepo(targetPath) {
|
|
163
|
+
const root = gitRoot(targetPath);
|
|
164
|
+
if (!root) {
|
|
165
|
+
fail(`target repo is not a git repo: ${targetPath}`);
|
|
166
|
+
}
|
|
167
|
+
return root;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function requirePackageScript(relativePath) {
|
|
171
|
+
const absolutePath = path.join(PACKAGE_ROOT, relativePath);
|
|
172
|
+
if (!fs.existsSync(absolutePath)) {
|
|
173
|
+
fail(`required llm-workbench package script is missing: ${relativePath}`);
|
|
174
|
+
}
|
|
175
|
+
return absolutePath;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function requireInstalledWorkbench(repoRoot) {
|
|
179
|
+
if (!fs.existsSync(path.join(repoRoot, INSTALLED_MANIFEST))) {
|
|
180
|
+
fail(`llm-workbench install has not been run in this repo: ${repoRoot}\nRun: llm-wb init`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function requireTargetScripts(repoRoot, relativePaths) {
|
|
185
|
+
const missing = relativePaths.filter((relativePath) => {
|
|
186
|
+
return !fs.existsSync(path.join(repoRoot, relativePath));
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
if (missing.length > 0) {
|
|
190
|
+
fail(`required llm-workbench scripts are missing:\n${relativeMissing(missing)}\nRun: llm-wb init --dry-run`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function currentBranch(repoRoot) {
|
|
195
|
+
return capture('git', ['-C', repoRoot, 'branch', '--show-current']);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function requireChatBranch(repoRoot) {
|
|
199
|
+
const branch = currentBranch(repoRoot);
|
|
200
|
+
if (!branch.startsWith('chat/')) {
|
|
201
|
+
fail(`current branch is not a chat branch: ${branch || '<detached>'}`);
|
|
202
|
+
}
|
|
203
|
+
return branch;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function sessionIdFromBranch(branch) {
|
|
207
|
+
if (!branch.startsWith('chat/')) {
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
return branch.slice('chat/'.length);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function monthName(month) {
|
|
214
|
+
const names = {
|
|
215
|
+
'01': 'jan',
|
|
216
|
+
'02': 'feb',
|
|
217
|
+
'03': 'mar',
|
|
218
|
+
'04': 'apr',
|
|
219
|
+
'05': 'may',
|
|
220
|
+
'06': 'jun',
|
|
221
|
+
'07': 'jul',
|
|
222
|
+
'08': 'aug',
|
|
223
|
+
'09': 'sep',
|
|
224
|
+
'10': 'oct',
|
|
225
|
+
'11': 'nov',
|
|
226
|
+
'12': 'dec',
|
|
227
|
+
};
|
|
228
|
+
return names[month] || null;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function metadataValue(contents, key) {
|
|
232
|
+
const block = contents.match(/<!-- agentic-session\n([\s\S]*?)\n-->/);
|
|
233
|
+
if (!block) {
|
|
234
|
+
return '';
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const line = block[1].split('\n').find((candidate) => candidate.startsWith(`${key}: `));
|
|
238
|
+
return line ? line.slice(key.length + 2) : '';
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function findSessionLog(repoRoot, sessionId, branch) {
|
|
242
|
+
const year = sessionId.slice(0, 4);
|
|
243
|
+
const month = sessionId.slice(5, 7);
|
|
244
|
+
const day = sessionId.slice(8, 10);
|
|
245
|
+
const monthSlug = monthName(month);
|
|
246
|
+
const candidates = [];
|
|
247
|
+
|
|
248
|
+
if (year && monthSlug && day) {
|
|
249
|
+
candidates.push(path.join('commitLogs', year, monthSlug, day, sessionId, 'README.md'));
|
|
250
|
+
}
|
|
251
|
+
candidates.push(path.join('commitLogs', sessionId, 'README.md'));
|
|
252
|
+
|
|
253
|
+
for (const candidate of candidates) {
|
|
254
|
+
if (fs.existsSync(path.join(repoRoot, candidate))) {
|
|
255
|
+
return candidate;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (!year || !monthSlug || !day) {
|
|
260
|
+
fail(`could not derive session log path from branch: ${branch}`);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const parent = path.join(repoRoot, 'commitLogs', year, monthSlug, day);
|
|
264
|
+
if (fs.existsSync(parent)) {
|
|
265
|
+
for (const entry of fs.readdirSync(parent, { withFileTypes: true })) {
|
|
266
|
+
if (!entry.isDirectory()) {
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const relativePath = path.join('commitLogs', year, monthSlug, day, entry.name, 'README.md');
|
|
271
|
+
const absolutePath = path.join(repoRoot, relativePath);
|
|
272
|
+
if (!fs.existsSync(absolutePath)) {
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const contents = fs.readFileSync(absolutePath, 'utf8');
|
|
277
|
+
if (metadataValue(contents, 'id') === sessionId || metadataValue(contents, 'branch') === branch) {
|
|
278
|
+
return relativePath;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
fail(`missing chat log for ${branch}`);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function primaryWorktree(repoRoot) {
|
|
287
|
+
const output = capture('git', ['-C', repoRoot, 'worktree', 'list', '--porcelain']);
|
|
288
|
+
const first = output.split('\n').find((line) => line.startsWith('worktree '));
|
|
289
|
+
if (!first) {
|
|
290
|
+
fail('could not resolve root integration worktree');
|
|
291
|
+
}
|
|
292
|
+
return path.resolve(first.slice('worktree '.length));
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
function worktreeForBranch(repoRoot, branch) {
|
|
296
|
+
const output = capture('git', ['-C', repoRoot, 'worktree', 'list', '--porcelain']);
|
|
297
|
+
let currentPath = '';
|
|
298
|
+
|
|
299
|
+
for (const line of output.split('\n')) {
|
|
300
|
+
if (line.startsWith('worktree ')) {
|
|
301
|
+
currentPath = line.slice('worktree '.length);
|
|
302
|
+
} else if (line === `branch refs/heads/${branch}`) {
|
|
303
|
+
return path.resolve(currentPath);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return '';
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function envWithWorktreeRoot(repoRoot) {
|
|
311
|
+
return {
|
|
312
|
+
...process.env,
|
|
313
|
+
AGENTIC_CHAT_WORKTREE_ROOT: path.dirname(repoRoot),
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function parseCommitArgs(args) {
|
|
318
|
+
let message = '';
|
|
319
|
+
let summary = '';
|
|
320
|
+
let adrImpact = '';
|
|
321
|
+
let checkpoint = true;
|
|
322
|
+
const positional = [];
|
|
323
|
+
|
|
324
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
325
|
+
const arg = args[index];
|
|
326
|
+
|
|
327
|
+
switch (arg) {
|
|
328
|
+
case '-h':
|
|
329
|
+
case '--help':
|
|
330
|
+
printHelp();
|
|
331
|
+
process.exit(0);
|
|
332
|
+
break;
|
|
333
|
+
case '-m':
|
|
334
|
+
case '--message':
|
|
335
|
+
if (index + 1 >= args.length) {
|
|
336
|
+
fail(`${arg} requires a commit message`, 2);
|
|
337
|
+
}
|
|
338
|
+
message = args[index + 1];
|
|
339
|
+
index += 1;
|
|
340
|
+
break;
|
|
341
|
+
case '--summary':
|
|
342
|
+
if (index + 1 >= args.length) {
|
|
343
|
+
fail('--summary requires text', 2);
|
|
344
|
+
}
|
|
345
|
+
summary = args[index + 1];
|
|
346
|
+
index += 1;
|
|
347
|
+
break;
|
|
348
|
+
case '--adr-impact':
|
|
349
|
+
if (index + 1 >= args.length) {
|
|
350
|
+
fail('--adr-impact requires text', 2);
|
|
351
|
+
}
|
|
352
|
+
adrImpact = args[index + 1];
|
|
353
|
+
index += 1;
|
|
354
|
+
break;
|
|
355
|
+
case '--no-checkpoint':
|
|
356
|
+
checkpoint = false;
|
|
357
|
+
break;
|
|
358
|
+
default:
|
|
359
|
+
if (arg.startsWith('-')) {
|
|
360
|
+
fail(`unknown commit option: ${arg}`, 2);
|
|
361
|
+
}
|
|
362
|
+
positional.push(arg);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
if (message && positional.length > 0) {
|
|
367
|
+
fail('commit message was provided twice', 2);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (!message) {
|
|
371
|
+
message = positional.join(' ');
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (!message.trim()) {
|
|
375
|
+
fail('commit requires a message. Use: llm-wb commit -m "message"', 2);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return {
|
|
379
|
+
message,
|
|
380
|
+
summary: summary || message,
|
|
381
|
+
adrImpact,
|
|
382
|
+
checkpoint,
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function commandCommit(args) {
|
|
387
|
+
const { message, summary, adrImpact, checkpoint } = parseCommitArgs(args);
|
|
388
|
+
const repoRoot = requireGitRepo(process.cwd());
|
|
389
|
+
requireInstalledWorkbench(repoRoot);
|
|
390
|
+
requireTargetScripts(repoRoot, [
|
|
391
|
+
CHECK_WRITE_LOCATION_SCRIPT,
|
|
392
|
+
CHECK_COMMIT_PREREQUISITES_SCRIPT,
|
|
393
|
+
PREPARE_COMMIT_SCRIPT,
|
|
394
|
+
RECORD_CHAT_COMMIT_SCRIPT,
|
|
395
|
+
CHECKPOINT_CHAT_SESSION_LOG_SCRIPT,
|
|
396
|
+
]);
|
|
397
|
+
|
|
398
|
+
const branch = requireChatBranch(repoRoot);
|
|
399
|
+
const sessionId = sessionIdFromBranch(branch);
|
|
400
|
+
const logFile = findSessionLog(repoRoot, sessionId, branch);
|
|
401
|
+
const commandEnv = envWithWorktreeRoot(repoRoot);
|
|
402
|
+
|
|
403
|
+
runChecked('bash', [path.join(repoRoot, CHECK_WRITE_LOCATION_SCRIPT)], { cwd: repoRoot, env: commandEnv });
|
|
404
|
+
runChecked('bash', [path.join(repoRoot, CHECK_COMMIT_PREREQUISITES_SCRIPT)], { cwd: repoRoot, env: commandEnv });
|
|
405
|
+
|
|
406
|
+
runChecked('git', ['-C', repoRoot, 'add', '-A'], { cwd: repoRoot, env: commandEnv });
|
|
407
|
+
runChecked('git', ['-C', repoRoot, 'reset', '--', logFile], { cwd: repoRoot, env: commandEnv, stdio: 'ignore' });
|
|
408
|
+
|
|
409
|
+
const stagedResult = spawnSync('git', ['-C', repoRoot, 'diff', '--cached', '--quiet'], {
|
|
410
|
+
env: commandEnv,
|
|
411
|
+
stdio: 'ignore',
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
if (stagedResult.status === 0) {
|
|
415
|
+
fail(`no task changes to commit after excluding the session log: ${logFile}`);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
runChecked('bash', [path.join(repoRoot, PREPARE_COMMIT_SCRIPT)], { cwd: repoRoot, env: commandEnv });
|
|
419
|
+
runChecked('git', ['-C', repoRoot, 'commit', '-m', message], { cwd: repoRoot, env: commandEnv });
|
|
420
|
+
|
|
421
|
+
const commitSha = capture('git', ['-C', repoRoot, 'rev-parse', 'HEAD'], { env: commandEnv });
|
|
422
|
+
const recordArgs = [path.join(repoRoot, RECORD_CHAT_COMMIT_SCRIPT), commitSha, message, summary];
|
|
423
|
+
if (adrImpact) {
|
|
424
|
+
recordArgs.push(adrImpact);
|
|
425
|
+
}
|
|
426
|
+
runChecked('bash', recordArgs, { cwd: repoRoot, env: commandEnv });
|
|
427
|
+
|
|
428
|
+
if (checkpoint) {
|
|
429
|
+
runChecked('bash', [
|
|
430
|
+
path.join(repoRoot, CHECKPOINT_CHAT_SESSION_LOG_SCRIPT),
|
|
431
|
+
`chore(session): checkpoint ${commitSha.slice(0, 7)}`,
|
|
432
|
+
], { cwd: repoRoot, env: commandEnv });
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
console.log(`Committed chat task work: ${commitSha}`);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
function parseMergeMainArgs(args) {
|
|
439
|
+
let base = 'main';
|
|
440
|
+
let branch = '';
|
|
441
|
+
|
|
442
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
443
|
+
const arg = args[index];
|
|
444
|
+
|
|
445
|
+
switch (arg) {
|
|
446
|
+
case '-h':
|
|
447
|
+
case '--help':
|
|
448
|
+
printHelp();
|
|
449
|
+
process.exit(0);
|
|
450
|
+
break;
|
|
451
|
+
case '--base':
|
|
452
|
+
if (index + 1 >= args.length) {
|
|
453
|
+
fail('--base requires a branch name', 2);
|
|
454
|
+
}
|
|
455
|
+
base = args[index + 1];
|
|
456
|
+
index += 1;
|
|
457
|
+
break;
|
|
458
|
+
default:
|
|
459
|
+
if (arg.startsWith('-')) {
|
|
460
|
+
fail(`unknown merge-main option: ${arg}`, 2);
|
|
461
|
+
}
|
|
462
|
+
if (branch) {
|
|
463
|
+
fail('merge-main accepts at most one chat branch', 2);
|
|
464
|
+
}
|
|
465
|
+
branch = arg;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
return { base, branch };
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
function parseSessionsListArgs(args) {
|
|
473
|
+
let base = 'main';
|
|
474
|
+
|
|
475
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
476
|
+
const arg = args[index];
|
|
477
|
+
|
|
478
|
+
switch (arg) {
|
|
479
|
+
case '-h':
|
|
480
|
+
case '--help':
|
|
481
|
+
printSessionsHelp();
|
|
482
|
+
process.exit(0);
|
|
483
|
+
break;
|
|
484
|
+
case '--base':
|
|
485
|
+
if (index + 1 >= args.length) {
|
|
486
|
+
fail('--base requires a branch name', 2);
|
|
487
|
+
}
|
|
488
|
+
base = args[index + 1];
|
|
489
|
+
index += 1;
|
|
490
|
+
break;
|
|
491
|
+
default:
|
|
492
|
+
if (arg.startsWith('-')) {
|
|
493
|
+
fail(`unknown sessions list option: ${arg}`, 2);
|
|
494
|
+
}
|
|
495
|
+
fail(`unexpected sessions list argument: ${arg}`, 2);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
return { base };
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
function commandSessions(args) {
|
|
503
|
+
const [subcommand, ...subcommandArgs] = args;
|
|
504
|
+
|
|
505
|
+
if (!subcommand || subcommand === '-h' || subcommand === '--help' || subcommand === 'help') {
|
|
506
|
+
printSessionsHelp();
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
if (subcommand !== 'list') {
|
|
511
|
+
fail(`unknown sessions command: ${subcommand}`, 2);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
const { base } = parseSessionsListArgs(subcommandArgs);
|
|
515
|
+
const repoRoot = requireGitRepo(process.cwd());
|
|
516
|
+
requireInstalledWorkbench(repoRoot);
|
|
517
|
+
requireTargetScripts(repoRoot, [LIST_ACTIVE_CHAT_BRANCHES_SCRIPT]);
|
|
518
|
+
|
|
519
|
+
run('bash', [path.join(repoRoot, LIST_ACTIVE_CHAT_BRANCHES_SCRIPT), base], { cwd: repoRoot });
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
function commandMergeMain(args) {
|
|
523
|
+
const { base, branch: requestedBranch } = parseMergeMainArgs(args);
|
|
524
|
+
const currentRepoRoot = requireGitRepo(process.cwd());
|
|
525
|
+
const current = currentBranch(currentRepoRoot);
|
|
526
|
+
const targetBranch = requestedBranch || (current.startsWith('chat/') ? current : '');
|
|
527
|
+
|
|
528
|
+
if (!targetBranch) {
|
|
529
|
+
fail('merge-main needs a chat branch when not run from a chat worktree', 2);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
if (!targetBranch.startsWith('chat/')) {
|
|
533
|
+
fail(`merge-main target is not a chat branch: ${targetBranch}`, 2);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
const rootWorktree = primaryWorktree(currentRepoRoot);
|
|
537
|
+
requireInstalledWorkbench(rootWorktree);
|
|
538
|
+
requireTargetScripts(rootWorktree, [VERIFY_MERGE_READY_SCRIPT]);
|
|
539
|
+
|
|
540
|
+
const branchWorktree = worktreeForBranch(rootWorktree, targetBranch);
|
|
541
|
+
const commandEnv = branchWorktree
|
|
542
|
+
? { ...process.env, AGENTIC_CHAT_WORKTREE_ROOT: path.dirname(branchWorktree) }
|
|
543
|
+
: process.env;
|
|
544
|
+
|
|
545
|
+
runChecked('bash', [
|
|
546
|
+
path.join(rootWorktree, VERIFY_MERGE_READY_SCRIPT),
|
|
547
|
+
'--base',
|
|
548
|
+
base,
|
|
549
|
+
targetBranch,
|
|
550
|
+
], { cwd: rootWorktree, env: commandEnv });
|
|
551
|
+
|
|
552
|
+
runChecked('git', ['-C', rootWorktree, 'merge', '--no-ff', '--no-edit', targetBranch], {
|
|
553
|
+
cwd: rootWorktree,
|
|
554
|
+
env: commandEnv,
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
console.log(`Merged ${targetBranch} into local ${base}.`);
|
|
558
|
+
console.log('No remote push was performed.');
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
function parseInitArgs(args) {
|
|
562
|
+
let target = process.cwd();
|
|
563
|
+
let mode = '--apply';
|
|
564
|
+
let sawMode = false;
|
|
565
|
+
const installArgs = [];
|
|
566
|
+
|
|
567
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
568
|
+
const arg = args[index];
|
|
569
|
+
|
|
570
|
+
switch (arg) {
|
|
571
|
+
case '-h':
|
|
572
|
+
case '--help':
|
|
573
|
+
printHelp();
|
|
574
|
+
process.exit(0);
|
|
575
|
+
break;
|
|
576
|
+
case '--target':
|
|
577
|
+
if (index + 1 >= args.length) {
|
|
578
|
+
fail('--target requires a repo path', 2);
|
|
579
|
+
}
|
|
580
|
+
target = args[index + 1];
|
|
581
|
+
index += 1;
|
|
582
|
+
break;
|
|
583
|
+
case '--dry-run':
|
|
584
|
+
case '--apply':
|
|
585
|
+
if (sawMode) {
|
|
586
|
+
fail('choose only one of --dry-run or --apply', 2);
|
|
587
|
+
}
|
|
588
|
+
mode = arg;
|
|
589
|
+
sawMode = true;
|
|
590
|
+
break;
|
|
591
|
+
case '--init-commit':
|
|
592
|
+
installArgs.push(arg);
|
|
593
|
+
break;
|
|
594
|
+
default:
|
|
595
|
+
if (arg.startsWith('-')) {
|
|
596
|
+
fail(`unknown init option: ${arg}`, 2);
|
|
597
|
+
}
|
|
598
|
+
fail(`unexpected init argument: ${arg}`, 2);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
return { target, mode, installArgs };
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
function commandInit(args) {
|
|
606
|
+
const { target, mode, installArgs } = parseInitArgs(args);
|
|
607
|
+
const repoRoot = requireGitRepo(path.resolve(target));
|
|
608
|
+
const installScript = requirePackageScript(path.relative(PACKAGE_ROOT, INSTALL_SCRIPT));
|
|
609
|
+
|
|
610
|
+
// The npm package invokes its own bundled installer, while the installer
|
|
611
|
+
// writes into the caller's Git repository.
|
|
612
|
+
run('bash', [installScript, mode, ...installArgs, repoRoot], { cwd: PACKAGE_ROOT });
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
function commandList(args) {
|
|
616
|
+
if (args.length > 0) {
|
|
617
|
+
fail('list does not accept arguments', 2);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
const repoRoot = requireGitRepo(process.cwd());
|
|
621
|
+
requireInstalledWorkbench(repoRoot);
|
|
622
|
+
requireTargetScripts(repoRoot, [DISPATCHER_SCRIPT]);
|
|
623
|
+
|
|
624
|
+
run('bash', [path.join(repoRoot, DISPATCHER_SCRIPT), 'list'], { cwd: repoRoot });
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
function commandNew(args) {
|
|
628
|
+
const repoRoot = requireGitRepo(process.cwd());
|
|
629
|
+
requireInstalledWorkbench(repoRoot);
|
|
630
|
+
requireTargetScripts(repoRoot, [
|
|
631
|
+
DISPATCHER_SCRIPT,
|
|
632
|
+
NEW_COMMAND_SCRIPT,
|
|
633
|
+
START_NEW_CHAT_SCRIPT,
|
|
634
|
+
START_CHAT_SESSION_SCRIPT,
|
|
635
|
+
]);
|
|
636
|
+
|
|
637
|
+
run('bash', [path.join(repoRoot, DISPATCHER_SCRIPT), 'new', ...args], { cwd: repoRoot });
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
function main(argv) {
|
|
641
|
+
const [command, ...args] = argv;
|
|
642
|
+
|
|
643
|
+
if (!command || command === '-h' || command === '--help' || command === 'help') {
|
|
644
|
+
printHelp();
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
switch (command) {
|
|
649
|
+
case 'init':
|
|
650
|
+
commandInit(args);
|
|
651
|
+
break;
|
|
652
|
+
case 'list':
|
|
653
|
+
commandList(args);
|
|
654
|
+
break;
|
|
655
|
+
case 'new':
|
|
656
|
+
commandNew(args);
|
|
657
|
+
break;
|
|
658
|
+
case 'sessions':
|
|
659
|
+
commandSessions(args);
|
|
660
|
+
break;
|
|
661
|
+
case 'commit':
|
|
662
|
+
commandCommit(args);
|
|
663
|
+
break;
|
|
664
|
+
case 'merge-main':
|
|
665
|
+
commandMergeMain(args);
|
|
666
|
+
break;
|
|
667
|
+
default:
|
|
668
|
+
fail(`unknown command: ${command}`, 2, true);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
main(process.argv.slice(2));
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<!-- agentic-artifact:
|
|
2
|
+
schema: agentic-artifact/v2
|
|
3
|
+
id: chat.docs.readme
|
|
4
|
+
version: 1
|
|
5
|
+
status: active
|
|
6
|
+
layer: 00.chat
|
|
7
|
+
domain: documentation
|
|
8
|
+
disciplines:
|
|
9
|
+
- agentic
|
|
10
|
+
kind: readme
|
|
11
|
+
purpose: Index chat workbench documentation that supports the portable chat harness
|
|
12
|
+
and public bootstrap.
|
|
13
|
+
portability:
|
|
14
|
+
class: required
|
|
15
|
+
targets:
|
|
16
|
+
- llm-workbench
|
|
17
|
+
used_by:
|
|
18
|
+
- id: chat.workflows.bootstrap-chat-workbench-repo
|
|
19
|
+
path: .agentic/00.chat/workflows/bootstrap-chat-workbench-repo.md
|
|
20
|
+
- id: chat.script.upstream.bootstrap-llm-workbench-repo
|
|
21
|
+
path: scripts/00.chat/upstream/bootstrap-llm-workbench-repo/script.sh
|
|
22
|
+
-->
|
|
23
|
+
# Chat Workbench Docs
|
|
24
|
+
|
|
25
|
+
This folder contains documentation owned by the chat layer.
|
|
26
|
+
|
|
27
|
+
These files explain the portable chat workbench shape, not the source product
|
|
28
|
+
repo as a whole. Keep docs here when they are about chat lifecycle scripts,
|
|
29
|
+
public `llm-workbench` bootstrap boundaries, or current public-beta
|
|
30
|
+
portability behavior.
|
|
31
|
+
|
|
32
|
+
## Files
|
|
33
|
+
|
|
34
|
+
- `script-layout.md` explains the numbered `scripts/` layer command-surface
|
|
35
|
+
convention, including the current `scripts/00.chat/` and
|
|
36
|
+
`scripts/01.harness/` split.
|
|
37
|
+
- `llm-workbench-acceptance-matrix.md` maps the public-beta contract to the
|
|
38
|
+
artifacts and checks that enforce it.
|
|
39
|
+
- `bootstrap/llm-workbench-template/` contains starter public repo shell files
|
|
40
|
+
for the first `llm-workbench` bootstrap.
|
|
41
|
+
|
|
42
|
+
## Maintainer History
|
|
43
|
+
|
|
44
|
+
Maintainer decision history remains in the source repo and is not exported.
|
|
45
|
+
Public workbench exports should be understandable from current public docs such
|
|
46
|
+
as `docs/install.md`, `docs/workflows.md`, `docs/concepts.md`, and
|
|
47
|
+
`docs/adapting-to-your-repo.md`.
|