@tech-leads-club/harness-toolkit 0.3.1 → 0.3.2
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/bin/tlc-build.mjs +35 -6
- package/dist/chunks/compact-before-1e4qg1qt.mjs +1185 -0
- package/dist/chunks/compact-before-2hpbfxm5.mjs +5782 -0
- package/dist/chunks/compact-before-49j320yp.mjs +1283 -0
- package/dist/chunks/compact-before-4jrq0sqs.mjs +61 -0
- package/dist/chunks/compact-before-6w8n1vh1.mjs +186 -0
- package/dist/chunks/compact-before-7sdmwswh.mjs +52 -0
- package/dist/chunks/compact-before-beqpmqrm.mjs +187 -0
- package/dist/chunks/compact-before-j9y4jgn4.mjs +845 -0
- package/dist/chunks/compact-before-pk86tqx2.mjs +118 -0
- package/dist/chunks/compact-before-pkqk5v29.mjs +137 -0
- package/dist/chunks/compact-before-w1293m4n.mjs +315 -0
- package/dist/chunks/compact-before-wnnds45y.mjs +26 -0
- package/dist/chunks/compact-before-wt2c3nh4.mjs +551 -0
- package/dist/compact-before.mjs +13 -7961
- package/dist/doctor.mjs +33 -8480
- package/dist/help-topic.mjs +6 -14
- package/dist/init-project.mjs +36 -793
- package/dist/install-runtime.mjs +17 -7268
- package/dist/lessons-cli.mjs +25 -7043
- package/dist/obs-cli.mjs +27 -7037
- package/dist/price-lookup.mjs +11 -201
- package/dist/prompt-submit.mjs +14 -7974
- package/dist/refresh-model-prices.mjs +26 -7061
- package/dist/response-after.mjs +11 -7961
- package/dist/run.mjs +10 -7960
- package/dist/session-end.mjs +14 -8029
- package/dist/session-start.mjs +20 -8075
- package/dist/shim.mjs +18 -7024
- package/dist/stop.mjs +29 -8042
- package/dist/subagent-start.mjs +13 -7983
- package/dist/subagent-stop.mjs +11 -7961
- package/dist/support.mjs +21 -7168
- package/dist/tlc-cli.mjs +65 -8200
- package/dist/tool-after.mjs +20 -8176
- package/dist/tool-before.mjs +15 -7990
- package/dist/tool-failure.mjs +14 -7961
- package/dist/uninstall-runtime.mjs +61 -1008
- package/docs/log.md +4 -0
- package/package.json +1 -1
- package/src/core/release/release.version.ts +10 -4
package/dist/init-project.mjs
CHANGED
|
@@ -1,784 +1,27 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
function conventionalRuntimeHome() {
|
|
23
|
-
return join(homedir(), ".tlc", "harness");
|
|
24
|
-
}
|
|
25
|
-
function runtimeHome(env = process.env) {
|
|
26
|
-
return env.TLC_HOME ?? conventionalRuntimeHome();
|
|
27
|
-
}
|
|
28
|
-
function projectConfigPath(root) {
|
|
29
|
-
return join(harnessDir(root), "config.json");
|
|
30
|
-
}
|
|
31
|
-
function claudeConfigDir() {
|
|
32
|
-
const custom = process.env.CLAUDE_CONFIG_DIR?.trim();
|
|
33
|
-
return custom && custom.length > 0 ? custom : join(homedir(), ".claude");
|
|
34
|
-
}
|
|
35
|
-
function cursorConfigDir() {
|
|
36
|
-
const custom = process.env.CURSOR_CONFIG_DIR?.trim();
|
|
37
|
-
return custom && custom.length > 0 ? custom : join(homedir(), ".cursor");
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// src/providers/claude/claude.wiring.ts
|
|
41
|
-
function isPlainRecord(value) {
|
|
42
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
43
|
-
}
|
|
44
|
-
function isHooksRecord(value) {
|
|
45
|
-
return isPlainRecord(value);
|
|
46
|
-
}
|
|
47
|
-
function deepEqual(a, b) {
|
|
48
|
-
if (a === b) {
|
|
49
|
-
return true;
|
|
50
|
-
}
|
|
51
|
-
if (Array.isArray(a) || Array.isArray(b)) {
|
|
52
|
-
if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) {
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
return a.every((item, index) => deepEqual(item, b[index]));
|
|
56
|
-
}
|
|
57
|
-
if (isPlainRecord(a) && isPlainRecord(b)) {
|
|
58
|
-
const aKeys = Object.keys(a);
|
|
59
|
-
const bKeys = Object.keys(b);
|
|
60
|
-
if (aKeys.length !== bKeys.length) {
|
|
61
|
-
return false;
|
|
62
|
-
}
|
|
63
|
-
return aKeys.every((key) => bKeys.includes(key) && deepEqual(a[key], b[key]));
|
|
64
|
-
}
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
|
-
function desiredHooksFor(entries) {
|
|
68
|
-
const hooks = {};
|
|
69
|
-
for (const entry of entries) {
|
|
70
|
-
const group = {
|
|
71
|
-
hooks: [{ type: "command", command: entry.command, args: entry.args }]
|
|
72
|
-
};
|
|
73
|
-
hooks[entry.hookEvent] = [...hooks[entry.hookEvent] ?? [], group];
|
|
74
|
-
}
|
|
75
|
-
return hooks;
|
|
76
|
-
}
|
|
77
|
-
var LAUNCHER_MARKER = "tlc-exec.mjs";
|
|
78
|
-
function isHarnessGroup(group) {
|
|
79
|
-
return JSON.stringify(group ?? null).includes(LAUNCHER_MARKER);
|
|
80
|
-
}
|
|
81
|
-
function canonicalLauncherPath(path, resolve = realpathSync) {
|
|
82
|
-
try {
|
|
83
|
-
return resolve(path);
|
|
84
|
-
} catch {
|
|
85
|
-
return path;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
function canonicalizeGroups(groups, resolve) {
|
|
89
|
-
return JSON.parse(JSON.stringify(groups ?? null, (_key, value) => typeof value === "string" && value.includes(LAUNCHER_MARKER) ? canonicalLauncherPath(value, resolve) : value));
|
|
90
|
-
}
|
|
91
|
-
function mergeClaudeSettings(existingText, entries) {
|
|
92
|
-
const desired = desiredHooksFor(entries);
|
|
93
|
-
let settings = {};
|
|
94
|
-
if (existingText !== null && existingText.trim() !== "") {
|
|
95
|
-
let parsed;
|
|
96
|
-
try {
|
|
97
|
-
parsed = JSON.parse(existingText);
|
|
98
|
-
} catch (error) {
|
|
99
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
100
|
-
return { ok: false, error: message, block: JSON.stringify({ hooks: desired }, null, 2) };
|
|
101
|
-
}
|
|
102
|
-
if (!isPlainRecord(parsed)) {
|
|
103
|
-
return {
|
|
104
|
-
ok: false,
|
|
105
|
-
error: "settings.json root is not a JSON object",
|
|
106
|
-
block: JSON.stringify({ hooks: desired }, null, 2)
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
settings = parsed;
|
|
110
|
-
}
|
|
111
|
-
const currentHooks = isHooksRecord(settings.hooks) ? settings.hooks : {};
|
|
112
|
-
const mergedHooks = { ...currentHooks };
|
|
113
|
-
let changed = false;
|
|
114
|
-
for (const [hookEvent, groups] of Object.entries(desired)) {
|
|
115
|
-
const existingGroups = mergedHooks[hookEvent] ?? [];
|
|
116
|
-
const foreign = existingGroups.filter((group) => !isHarnessGroup(group));
|
|
117
|
-
const nextGroups = [...foreign, ...groups];
|
|
118
|
-
if (!deepEqual(canonicalizeGroups(existingGroups), canonicalizeGroups(nextGroups))) {
|
|
119
|
-
changed = true;
|
|
120
|
-
}
|
|
121
|
-
mergedHooks[hookEvent] = nextGroups;
|
|
122
|
-
}
|
|
123
|
-
const mergedSettings = { ...settings, hooks: mergedHooks };
|
|
124
|
-
return { ok: true, settingsText: JSON.stringify(mergedSettings, null, 2), changed };
|
|
125
|
-
}
|
|
126
|
-
function applyClaudeWiring(settingsPath, entries) {
|
|
127
|
-
const existingText = existsSync(settingsPath) ? readFileSync(settingsPath, "utf8") : null;
|
|
128
|
-
const result = mergeClaudeSettings(existingText, entries);
|
|
129
|
-
if (result.ok && result.changed) {
|
|
130
|
-
mkdirSync(dirname(settingsPath), { recursive: true });
|
|
131
|
-
writeFileSync(settingsPath, result.settingsText, "utf8");
|
|
132
|
-
}
|
|
133
|
-
return result;
|
|
134
|
-
}
|
|
135
|
-
// src/providers/provider.degrade.ts
|
|
136
|
-
var NO_HUMAN_MODES = new Set(["bypassPermissions", "dontAsk"]);
|
|
137
|
-
// bin/write-user-hooks.mjs
|
|
138
|
-
var CURSOR_MARKER = "tlc-exec.mjs";
|
|
139
|
-
function quoteIfNeeded(token) {
|
|
140
|
-
return token.includes(" ") ? `"${token}"` : token;
|
|
141
|
-
}
|
|
142
|
-
function commandStringFor(entry) {
|
|
143
|
-
return [entry.command, ...entry.args].map(quoteIfNeeded).join(" ");
|
|
144
|
-
}
|
|
145
|
-
function renderCursorHooksDocument(entries) {
|
|
146
|
-
const hooks = {};
|
|
147
|
-
for (const entry of entries) {
|
|
148
|
-
const rendered = { command: commandStringFor(entry), timeout: entry.timeoutSeconds };
|
|
149
|
-
if (entry.failClosed) {
|
|
150
|
-
rendered.failClosed = true;
|
|
151
|
-
}
|
|
152
|
-
if (entry.matcher !== undefined) {
|
|
153
|
-
rendered.matcher = entry.matcher;
|
|
154
|
-
}
|
|
155
|
-
if (entry.loopLimit !== undefined) {
|
|
156
|
-
rendered.loop_limit = entry.loopLimit;
|
|
157
|
-
}
|
|
158
|
-
hooks[entry.hookEvent] = [...hooks[entry.hookEvent] ?? [], rendered];
|
|
159
|
-
}
|
|
160
|
-
return { version: 1, hooks };
|
|
161
|
-
}
|
|
162
|
-
function isCursorWired(targetPath) {
|
|
163
|
-
return existsSync2(targetPath) && readFileSync2(targetPath, "utf8").includes(CURSOR_MARKER);
|
|
164
|
-
}
|
|
165
|
-
function applyCursorWiring(wiring, { force = false } = {}) {
|
|
166
|
-
const targetPath = wiring.target;
|
|
167
|
-
const document = renderCursorHooksDocument(wiring.entries);
|
|
168
|
-
const rendered = `${JSON.stringify(document, null, 2)}
|
|
169
|
-
`;
|
|
170
|
-
if (existsSync2(targetPath) && !force) {
|
|
171
|
-
if (isCursorWired(targetPath)) {
|
|
172
|
-
return { status: "unchanged", target: targetPath };
|
|
173
|
-
}
|
|
174
|
-
return {
|
|
175
|
-
status: "refused",
|
|
176
|
-
target: targetPath,
|
|
177
|
-
reason: `${targetPath} exists without harness entries — rerun with --force to overwrite, or merge manually.`
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
mkdirSync2(dirname2(targetPath), { recursive: true });
|
|
181
|
-
writeFileSync2(targetPath, rendered);
|
|
182
|
-
return { status: "written", target: targetPath };
|
|
183
|
-
}
|
|
184
|
-
if (false) {}
|
|
185
|
-
|
|
186
|
-
// src/core/comment-policy/comment-syntax.catalog.ts
|
|
187
|
-
var COMMENT_SYNTAX = [
|
|
188
|
-
{
|
|
189
|
-
id: "typescript",
|
|
190
|
-
extensions: [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"],
|
|
191
|
-
line: ["//"],
|
|
192
|
-
block: [["/*", "*/"]],
|
|
193
|
-
middle: ["*"]
|
|
194
|
-
},
|
|
195
|
-
{
|
|
196
|
-
id: "python",
|
|
197
|
-
extensions: [".py", ".pyi", ".pyw"],
|
|
198
|
-
line: ["#"],
|
|
199
|
-
block: [
|
|
200
|
-
['"""', '"""'],
|
|
201
|
-
["'''", "'''"]
|
|
202
|
-
],
|
|
203
|
-
middle: []
|
|
204
|
-
},
|
|
205
|
-
{
|
|
206
|
-
id: "ruby",
|
|
207
|
-
extensions: [".rb", ".rake", ".gemspec"],
|
|
208
|
-
line: ["#"],
|
|
209
|
-
block: [["=begin", "=end"]],
|
|
210
|
-
middle: []
|
|
211
|
-
},
|
|
212
|
-
{
|
|
213
|
-
id: "shell",
|
|
214
|
-
extensions: [".sh", ".bash", ".zsh", ".ksh", ".fish"],
|
|
215
|
-
line: ["#"],
|
|
216
|
-
block: [],
|
|
217
|
-
middle: []
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
id: "go",
|
|
221
|
-
extensions: [".go"],
|
|
222
|
-
line: ["//"],
|
|
223
|
-
block: [["/*", "*/"]],
|
|
224
|
-
middle: ["*"]
|
|
225
|
-
},
|
|
226
|
-
{
|
|
227
|
-
id: "rust",
|
|
228
|
-
extensions: [".rs"],
|
|
229
|
-
line: ["//"],
|
|
230
|
-
block: [["/*", "*/"]],
|
|
231
|
-
middle: ["*"]
|
|
232
|
-
},
|
|
233
|
-
{
|
|
234
|
-
id: "java",
|
|
235
|
-
extensions: [".java"],
|
|
236
|
-
line: ["//"],
|
|
237
|
-
block: [["/*", "*/"]],
|
|
238
|
-
middle: ["*"]
|
|
239
|
-
},
|
|
240
|
-
{
|
|
241
|
-
id: "kotlin",
|
|
242
|
-
extensions: [".kt", ".kts"],
|
|
243
|
-
line: ["//"],
|
|
244
|
-
block: [["/*", "*/"]],
|
|
245
|
-
middle: ["*"]
|
|
246
|
-
},
|
|
247
|
-
{
|
|
248
|
-
id: "swift",
|
|
249
|
-
extensions: [".swift"],
|
|
250
|
-
line: ["//"],
|
|
251
|
-
block: [["/*", "*/"]],
|
|
252
|
-
middle: ["*"]
|
|
253
|
-
},
|
|
254
|
-
{
|
|
255
|
-
id: "c",
|
|
256
|
-
extensions: [".c", ".h"],
|
|
257
|
-
line: ["//"],
|
|
258
|
-
block: [["/*", "*/"]],
|
|
259
|
-
middle: ["*"]
|
|
260
|
-
},
|
|
261
|
-
{
|
|
262
|
-
id: "cpp",
|
|
263
|
-
extensions: [".cc", ".cpp", ".cxx", ".hpp", ".hh", ".hxx"],
|
|
264
|
-
line: ["//"],
|
|
265
|
-
block: [["/*", "*/"]],
|
|
266
|
-
middle: ["*"]
|
|
267
|
-
},
|
|
268
|
-
{
|
|
269
|
-
id: "csharp",
|
|
270
|
-
extensions: [".cs"],
|
|
271
|
-
line: ["//"],
|
|
272
|
-
block: [["/*", "*/"]],
|
|
273
|
-
middle: ["*"]
|
|
274
|
-
},
|
|
275
|
-
{
|
|
276
|
-
id: "php",
|
|
277
|
-
extensions: [".php"],
|
|
278
|
-
line: ["//", "#"],
|
|
279
|
-
block: [["/*", "*/"]],
|
|
280
|
-
middle: ["*"]
|
|
281
|
-
},
|
|
282
|
-
{
|
|
283
|
-
id: "scala",
|
|
284
|
-
extensions: [".scala", ".sc"],
|
|
285
|
-
line: ["//"],
|
|
286
|
-
block: [["/*", "*/"]],
|
|
287
|
-
middle: ["*"]
|
|
288
|
-
},
|
|
289
|
-
{
|
|
290
|
-
id: "dart",
|
|
291
|
-
extensions: [".dart"],
|
|
292
|
-
line: ["//"],
|
|
293
|
-
block: [["/*", "*/"]],
|
|
294
|
-
middle: ["*"]
|
|
295
|
-
},
|
|
296
|
-
{
|
|
297
|
-
id: "elixir",
|
|
298
|
-
extensions: [".ex", ".exs"],
|
|
299
|
-
line: ["#"],
|
|
300
|
-
block: [],
|
|
301
|
-
middle: []
|
|
302
|
-
},
|
|
303
|
-
{
|
|
304
|
-
id: "erlang",
|
|
305
|
-
extensions: [".erl", ".hrl"],
|
|
306
|
-
line: ["%"],
|
|
307
|
-
block: [],
|
|
308
|
-
middle: []
|
|
309
|
-
},
|
|
310
|
-
{
|
|
311
|
-
id: "haskell",
|
|
312
|
-
extensions: [".hs"],
|
|
313
|
-
line: ["--"],
|
|
314
|
-
block: [["{-", "-}"]],
|
|
315
|
-
middle: []
|
|
316
|
-
},
|
|
317
|
-
{
|
|
318
|
-
id: "lua",
|
|
319
|
-
extensions: [".lua"],
|
|
320
|
-
line: ["--"],
|
|
321
|
-
block: [["--[[", "]]"]],
|
|
322
|
-
middle: []
|
|
323
|
-
},
|
|
324
|
-
{
|
|
325
|
-
id: "sql",
|
|
326
|
-
extensions: [".sql"],
|
|
327
|
-
line: ["--"],
|
|
328
|
-
block: [["/*", "*/"]],
|
|
329
|
-
middle: ["*"]
|
|
330
|
-
},
|
|
331
|
-
{
|
|
332
|
-
id: "css",
|
|
333
|
-
extensions: [".css", ".scss", ".sass", ".less"],
|
|
334
|
-
line: ["//"],
|
|
335
|
-
block: [["/*", "*/"]],
|
|
336
|
-
middle: ["*"]
|
|
337
|
-
},
|
|
338
|
-
{
|
|
339
|
-
id: "yaml",
|
|
340
|
-
extensions: [".yaml", ".yml"],
|
|
341
|
-
line: ["#"],
|
|
342
|
-
block: [],
|
|
343
|
-
middle: []
|
|
344
|
-
},
|
|
345
|
-
{
|
|
346
|
-
id: "toml",
|
|
347
|
-
extensions: [".toml"],
|
|
348
|
-
line: ["#"],
|
|
349
|
-
block: [],
|
|
350
|
-
middle: []
|
|
351
|
-
},
|
|
352
|
-
{
|
|
353
|
-
id: "ini",
|
|
354
|
-
extensions: [".ini", ".cfg", ".conf", ".properties"],
|
|
355
|
-
line: [";", "#"],
|
|
356
|
-
block: [],
|
|
357
|
-
middle: []
|
|
358
|
-
},
|
|
359
|
-
{
|
|
360
|
-
id: "dockerfile",
|
|
361
|
-
extensions: [".dockerfile", "dockerfile"],
|
|
362
|
-
line: ["#"],
|
|
363
|
-
block: [],
|
|
364
|
-
middle: []
|
|
365
|
-
},
|
|
366
|
-
{
|
|
367
|
-
id: "makefile",
|
|
368
|
-
extensions: [".mk", "makefile"],
|
|
369
|
-
line: ["#"],
|
|
370
|
-
block: [],
|
|
371
|
-
middle: []
|
|
372
|
-
},
|
|
373
|
-
{
|
|
374
|
-
id: "terraform",
|
|
375
|
-
extensions: [".tf", ".tfvars"],
|
|
376
|
-
line: ["#", "//"],
|
|
377
|
-
block: [["/*", "*/"]],
|
|
378
|
-
middle: ["*"]
|
|
379
|
-
},
|
|
380
|
-
{
|
|
381
|
-
id: "powershell",
|
|
382
|
-
extensions: [".ps1", ".psm1", ".psd1"],
|
|
383
|
-
line: ["#"],
|
|
384
|
-
block: [["<#", "#>"]],
|
|
385
|
-
middle: []
|
|
386
|
-
},
|
|
387
|
-
{
|
|
388
|
-
id: "perl",
|
|
389
|
-
extensions: [".pl", ".pm"],
|
|
390
|
-
line: ["#"],
|
|
391
|
-
block: [],
|
|
392
|
-
middle: []
|
|
393
|
-
},
|
|
394
|
-
{
|
|
395
|
-
id: "r",
|
|
396
|
-
extensions: [".r"],
|
|
397
|
-
line: ["#"],
|
|
398
|
-
block: [],
|
|
399
|
-
middle: []
|
|
400
|
-
},
|
|
401
|
-
{
|
|
402
|
-
id: "julia",
|
|
403
|
-
extensions: [".jl"],
|
|
404
|
-
line: ["#"],
|
|
405
|
-
block: [["#=", "=#"]],
|
|
406
|
-
middle: []
|
|
407
|
-
},
|
|
408
|
-
{
|
|
409
|
-
id: "vue",
|
|
410
|
-
extensions: [".vue", ".svelte"],
|
|
411
|
-
line: ["//"],
|
|
412
|
-
block: [
|
|
413
|
-
["/*", "*/"],
|
|
414
|
-
["<!--", "-->"]
|
|
415
|
-
],
|
|
416
|
-
middle: ["*"]
|
|
417
|
-
},
|
|
418
|
-
{
|
|
419
|
-
id: "html",
|
|
420
|
-
extensions: [".html", ".htm", ".xml", ".xhtml"],
|
|
421
|
-
line: [],
|
|
422
|
-
block: [["<!--", "-->"]],
|
|
423
|
-
middle: []
|
|
424
|
-
},
|
|
425
|
-
{
|
|
426
|
-
id: "graphql",
|
|
427
|
-
extensions: [".graphql", ".gql"],
|
|
428
|
-
line: ["#"],
|
|
429
|
-
block: [],
|
|
430
|
-
middle: []
|
|
431
|
-
},
|
|
432
|
-
{
|
|
433
|
-
id: "protobuf",
|
|
434
|
-
extensions: [".proto"],
|
|
435
|
-
line: ["//"],
|
|
436
|
-
block: [["/*", "*/"]],
|
|
437
|
-
middle: ["*"]
|
|
438
|
-
},
|
|
439
|
-
{
|
|
440
|
-
id: "zig",
|
|
441
|
-
extensions: [".zig"],
|
|
442
|
-
line: ["//"],
|
|
443
|
-
block: [],
|
|
444
|
-
middle: []
|
|
445
|
-
},
|
|
446
|
-
{
|
|
447
|
-
id: "clojure",
|
|
448
|
-
extensions: [".clj", ".cljs", ".cljc", ".edn"],
|
|
449
|
-
line: [";"],
|
|
450
|
-
block: [],
|
|
451
|
-
middle: []
|
|
452
|
-
},
|
|
453
|
-
{
|
|
454
|
-
id: "ocaml",
|
|
455
|
-
extensions: [".ml", ".mli"],
|
|
456
|
-
line: [],
|
|
457
|
-
block: [["(*", "*)"]],
|
|
458
|
-
middle: ["*"]
|
|
459
|
-
},
|
|
460
|
-
{
|
|
461
|
-
id: "fsharp",
|
|
462
|
-
extensions: [".fs", ".fsi", ".fsx"],
|
|
463
|
-
line: ["//"],
|
|
464
|
-
block: [["(*", "*)"]],
|
|
465
|
-
middle: ["*"]
|
|
466
|
-
},
|
|
467
|
-
{
|
|
468
|
-
id: "vim",
|
|
469
|
-
extensions: [".vim"],
|
|
470
|
-
line: ['"'],
|
|
471
|
-
block: [],
|
|
472
|
-
middle: []
|
|
473
|
-
},
|
|
474
|
-
{
|
|
475
|
-
id: "tex",
|
|
476
|
-
extensions: [".tex", ".sty", ".cls"],
|
|
477
|
-
line: ["%"],
|
|
478
|
-
block: [],
|
|
479
|
-
middle: []
|
|
480
|
-
}
|
|
481
|
-
];
|
|
482
|
-
|
|
483
|
-
// src/core/comment-policy/comment-syntax.store.ts
|
|
484
|
-
function buildIndex(entries) {
|
|
485
|
-
const byKey = new Map;
|
|
486
|
-
for (const entry of entries) {
|
|
487
|
-
const syntax = { line: entry.line, block: entry.block, middle: entry.middle };
|
|
488
|
-
for (const extension of entry.extensions) {
|
|
489
|
-
byKey.set(extension.toLowerCase(), syntax);
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
return byKey;
|
|
493
|
-
}
|
|
494
|
-
var INDEX = buildIndex(COMMENT_SYNTAX);
|
|
495
|
-
var KNOWN_EXTENSION_COUNT = INDEX.size;
|
|
496
|
-
|
|
497
|
-
// src/core/comment-policy/comment-policy.service.ts
|
|
498
|
-
var STOPWORDS = new Set([
|
|
499
|
-
"a",
|
|
500
|
-
"an",
|
|
501
|
-
"and",
|
|
502
|
-
"are",
|
|
503
|
-
"as",
|
|
504
|
-
"at",
|
|
505
|
-
"be",
|
|
506
|
-
"by",
|
|
507
|
-
"for",
|
|
508
|
-
"from",
|
|
509
|
-
"get",
|
|
510
|
-
"gets",
|
|
511
|
-
"has",
|
|
512
|
-
"in",
|
|
513
|
-
"into",
|
|
514
|
-
"is",
|
|
515
|
-
"it",
|
|
516
|
-
"its",
|
|
517
|
-
"of",
|
|
518
|
-
"on",
|
|
519
|
-
"or",
|
|
520
|
-
"return",
|
|
521
|
-
"returns",
|
|
522
|
-
"set",
|
|
523
|
-
"sets",
|
|
524
|
-
"that",
|
|
525
|
-
"the",
|
|
526
|
-
"then",
|
|
527
|
-
"this",
|
|
528
|
-
"to",
|
|
529
|
-
"true",
|
|
530
|
-
"when",
|
|
531
|
-
"which",
|
|
532
|
-
"with"
|
|
533
|
-
]);
|
|
534
|
-
|
|
535
|
-
// src/core/duplication/duplication.service.ts
|
|
536
|
-
var MIN_RUN = 6;
|
|
537
|
-
|
|
538
|
-
// src/core/observability/observability.types.ts
|
|
539
|
-
var DEFAULT_OBS = {
|
|
540
|
-
enabled: true,
|
|
541
|
-
signalPath: "obs.jsonl",
|
|
542
|
-
debugPath: "debug.jsonl",
|
|
543
|
-
debugEnabled: false,
|
|
544
|
-
includePayloads: false,
|
|
545
|
-
maxAttrChars: 500,
|
|
546
|
-
sessionCostAlertUsd: 5,
|
|
547
|
-
retentionDays: 14,
|
|
548
|
-
maxSignalEvents: 50000,
|
|
549
|
-
globalSpool: false
|
|
550
|
-
};
|
|
551
|
-
var SIGNAL_KINDS = new Set([
|
|
552
|
-
"session.start",
|
|
553
|
-
"session.end",
|
|
554
|
-
"generation.end",
|
|
555
|
-
"tool.fail",
|
|
556
|
-
"subagent.start",
|
|
557
|
-
"subagent.end",
|
|
558
|
-
"prompt.submit",
|
|
559
|
-
"compact",
|
|
560
|
-
"gate.outcome",
|
|
561
|
-
"cost.turn",
|
|
562
|
-
"cost.session_alert",
|
|
563
|
-
"ship.claim",
|
|
564
|
-
"policy.deny",
|
|
565
|
-
"policy.observe"
|
|
566
|
-
]);
|
|
567
|
-
var LIVE_ALLOWLIST = new Set([
|
|
568
|
-
"session.start",
|
|
569
|
-
"session.end",
|
|
570
|
-
"generation.end",
|
|
571
|
-
"tool.fail",
|
|
572
|
-
"shell.end",
|
|
573
|
-
"subagent.start",
|
|
574
|
-
"subagent.end",
|
|
575
|
-
"gate.outcome",
|
|
576
|
-
"cost.turn",
|
|
577
|
-
"cost.session_alert",
|
|
578
|
-
"ship.claim",
|
|
579
|
-
"policy.deny",
|
|
580
|
-
"compact",
|
|
581
|
-
"prompt.submit"
|
|
582
|
-
]);
|
|
583
|
-
|
|
584
|
-
// src/core/policy/policy.defaults.ts
|
|
585
|
-
var DEFAULT_LESSONS_POLICY = {
|
|
586
|
-
enabled: false,
|
|
587
|
-
maxInjectSession: 5,
|
|
588
|
-
maxInjectRetry: 8,
|
|
589
|
-
maxCharsSession: 900,
|
|
590
|
-
maxCharsRetry: 1400,
|
|
591
|
-
promoteHitCount: 2,
|
|
592
|
-
decayLambda: 0.02,
|
|
593
|
-
projectBoost: 1.5,
|
|
594
|
-
syncRulesFile: "auto",
|
|
595
|
-
gardenOnSessionEnd: true
|
|
596
|
-
};
|
|
597
|
-
var DEFAULTS = {
|
|
598
|
-
version: 1,
|
|
599
|
-
mode: "solo",
|
|
600
|
-
codePaths: ["src", "apps", "libs", "packages"],
|
|
601
|
-
grind: {
|
|
602
|
-
enabled: false,
|
|
603
|
-
maxLoops: 5,
|
|
604
|
-
lintCommand: null,
|
|
605
|
-
testCommand: null,
|
|
606
|
-
appendFiles: "auto"
|
|
607
|
-
},
|
|
608
|
-
shipGate: {
|
|
609
|
-
enabled: false,
|
|
610
|
-
runtimePathPrefixes: ["src", "apps", "libs", "packages", "deploy", "scripts"],
|
|
611
|
-
runtimePathExcludes: [".tlc/", "**/node_modules/", "**/.git/"],
|
|
612
|
-
evidenceDir: null,
|
|
613
|
-
evidenceMaxAgeHours: 48,
|
|
614
|
-
emptyDiffAntiShip: false,
|
|
615
|
-
claimWindowMinutes: 10
|
|
616
|
-
},
|
|
617
|
-
subagents: {
|
|
618
|
-
enforceAllowlist: false,
|
|
619
|
-
requireModel: false,
|
|
620
|
-
allowedModels: [],
|
|
621
|
-
blockedPatterns: ["-fast(?:$|[^a-z0-9])", "/fast(?:$|[^a-z0-9])"],
|
|
622
|
-
minEffort: null,
|
|
623
|
-
blockParentFast: false,
|
|
624
|
-
blockMode: "deny",
|
|
625
|
-
readOnlyTypes: ["explore"]
|
|
626
|
-
},
|
|
627
|
-
docs: {
|
|
628
|
-
command: null,
|
|
629
|
-
severity: "warn"
|
|
630
|
-
},
|
|
631
|
-
observe: {
|
|
632
|
-
enabled: false,
|
|
633
|
-
rails: []
|
|
634
|
-
},
|
|
635
|
-
comments: {
|
|
636
|
-
enabled: false,
|
|
637
|
-
onViolation: "followup",
|
|
638
|
-
mode: "declared"
|
|
639
|
-
},
|
|
640
|
-
supplyChain: {
|
|
641
|
-
enabled: false
|
|
642
|
-
},
|
|
643
|
-
duplication: {
|
|
644
|
-
enabled: false,
|
|
645
|
-
minRun: MIN_RUN
|
|
646
|
-
},
|
|
647
|
-
obs: {
|
|
648
|
-
globalSpool: false,
|
|
649
|
-
includePayloads: DEFAULT_OBS.includePayloads,
|
|
650
|
-
maxAttrChars: DEFAULT_OBS.maxAttrChars,
|
|
651
|
-
sessionCostAlertUsd: DEFAULT_OBS.sessionCostAlertUsd,
|
|
652
|
-
retentionDays: DEFAULT_OBS.retentionDays
|
|
653
|
-
},
|
|
654
|
-
untrustedContent: {
|
|
655
|
-
mode: "frame",
|
|
656
|
-
enabled: false,
|
|
657
|
-
extraTools: [],
|
|
658
|
-
extraCommandPatterns: []
|
|
659
|
-
},
|
|
660
|
-
planGate: {
|
|
661
|
-
enabled: false,
|
|
662
|
-
windowMinutes: 120
|
|
663
|
-
},
|
|
664
|
-
shell: {
|
|
665
|
-
catastrophicAsk: true,
|
|
666
|
-
stallDetection: false,
|
|
667
|
-
stallRepeatThreshold: 3
|
|
668
|
-
},
|
|
669
|
-
intelligence: {
|
|
670
|
-
gapFeedback: true,
|
|
671
|
-
failureClassification: true,
|
|
672
|
-
progressiveHandoff: true,
|
|
673
|
-
progressiveContext: true,
|
|
674
|
-
autopilot: true,
|
|
675
|
-
idleTurnGate: false,
|
|
676
|
-
budgetContinue: false,
|
|
677
|
-
budgetContinueAfterLoops: 3,
|
|
678
|
-
lessons: { ...DEFAULT_LESSONS_POLICY }
|
|
679
|
-
},
|
|
680
|
-
mcpPrime: [],
|
|
681
|
-
bootstrapExtra: []
|
|
682
|
-
};
|
|
683
|
-
|
|
684
|
-
// src/platform/style.ts
|
|
685
|
-
var COLORS = {
|
|
686
|
-
structure: "#3d3a4a",
|
|
687
|
-
accent: "#a78bfa",
|
|
688
|
-
success: "#6ee7b7",
|
|
689
|
-
warning: "#d4a574",
|
|
690
|
-
error: "#f87171",
|
|
691
|
-
info: "#93c5fd",
|
|
692
|
-
textMain: "#f5f5f7",
|
|
693
|
-
textMuted: "#9ca3af",
|
|
694
|
-
textDim: "#6b7280"
|
|
695
|
-
};
|
|
696
|
-
var SYMBOLS = {
|
|
697
|
-
check: "✔",
|
|
698
|
-
cross: "✖",
|
|
699
|
-
warning: "⚠",
|
|
700
|
-
arrow: "→",
|
|
701
|
-
arrowRight: "▸",
|
|
702
|
-
dot: "•",
|
|
703
|
-
bar: "│",
|
|
704
|
-
rule: "══",
|
|
705
|
-
dash: "──"
|
|
706
|
-
};
|
|
707
|
-
function rgb(hex) {
|
|
708
|
-
const match = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex.trim());
|
|
709
|
-
if (!match) {
|
|
710
|
-
return "255;255;255";
|
|
711
|
-
}
|
|
712
|
-
return [match[1], match[2], match[3]].map((part) => Number.parseInt(part, 16)).join(";");
|
|
713
|
-
}
|
|
714
|
-
var ESC = String.fromCharCode(27);
|
|
715
|
-
var RESET = `${ESC}[0m`;
|
|
716
|
-
function colorEnabled(env = process.env, argv = process.argv, isTty = process.stdout.isTTY === true) {
|
|
717
|
-
if ("NO_COLOR" in env) {
|
|
718
|
-
return false;
|
|
719
|
-
}
|
|
720
|
-
if (argv.includes("--no-color")) {
|
|
721
|
-
return false;
|
|
722
|
-
}
|
|
723
|
-
return isTty;
|
|
724
|
-
}
|
|
725
|
-
var STATUS_COLOR = {
|
|
726
|
-
ok: "success",
|
|
727
|
-
warn: "warning",
|
|
728
|
-
fail: "error",
|
|
729
|
-
info: "info"
|
|
730
|
-
};
|
|
731
|
-
var STATUS_MARK = {
|
|
732
|
-
ok: SYMBOLS.check,
|
|
733
|
-
warn: SYMBOLS.warning,
|
|
734
|
-
fail: SYMBOLS.cross,
|
|
735
|
-
info: SYMBOLS.arrowRight
|
|
736
|
-
};
|
|
737
|
-
var KV_WIDTH = 16;
|
|
738
|
-
function createStyle(enabled = colorEnabled()) {
|
|
739
|
-
const wrap = (code, text) => enabled ? `${ESC}[${code}m${text}${RESET}` : text;
|
|
740
|
-
const paint = (name, text) => wrap(`38;2;${rgb(COLORS[name])}`, text);
|
|
741
|
-
return {
|
|
742
|
-
enabled,
|
|
743
|
-
paint,
|
|
744
|
-
bold: (text) => wrap("1", text),
|
|
745
|
-
dim: (text) => paint("textDim", text),
|
|
746
|
-
heading: (text) => paint("accent", `${SYMBOLS.rule} ${text} ${SYMBOLS.rule}`),
|
|
747
|
-
footer: (text) => paint("textDim", `${SYMBOLS.dash} ${text} ${SYMBOLS.dash}`),
|
|
748
|
-
kv: (label, value, width = KV_WIDTH) => ` ${paint("textMuted", `${label}:`.padEnd(width))} ${value}`,
|
|
749
|
-
status: (level, text) => `${paint(STATUS_COLOR[level], STATUS_MARK[level])} ${text}`
|
|
750
|
-
};
|
|
751
|
-
}
|
|
752
|
-
var PLAIN = createStyle(false);
|
|
753
|
-
|
|
754
|
-
// src/platform/screen.ts
|
|
755
|
-
function render(screen, style) {
|
|
756
|
-
const out = [style.heading(screen.title.toUpperCase())];
|
|
757
|
-
if (screen.summary && screen.summary.length > 0) {
|
|
758
|
-
out.push(` ${screen.summary.join(style.dim(` ${SYMBOLS.bar} `))}`);
|
|
759
|
-
}
|
|
760
|
-
const width = Math.max(KV_WIDTH, ...screen.sections.flatMap((section) => (section.rows ?? []).map((row) => row.label.length + 1)));
|
|
761
|
-
for (const section of screen.sections) {
|
|
762
|
-
out.push("");
|
|
763
|
-
if (section.title) {
|
|
764
|
-
out.push(style.paint("accent", section.title));
|
|
765
|
-
}
|
|
766
|
-
for (const row of section.rows ?? []) {
|
|
767
|
-
const value = row.level ? style.status(row.level, row.value) : row.value;
|
|
768
|
-
out.push(style.kv(row.label, value, width));
|
|
769
|
-
}
|
|
770
|
-
for (const line of section.lines ?? []) {
|
|
771
|
-
out.push(line === "" ? "" : ` ${line}`);
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
if (screen.footer) {
|
|
775
|
-
out.push("", style.footer(screen.footer));
|
|
776
|
-
}
|
|
777
|
-
return out.join(`
|
|
778
|
-
`);
|
|
779
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
applyCursorWiring,
|
|
3
|
+
renderCursorHooksDocument
|
|
4
|
+
} from "./chunks/compact-before-7sdmwswh.mjs";
|
|
5
|
+
import"./chunks/compact-before-j9y4jgn4.mjs";
|
|
6
|
+
import {
|
|
7
|
+
applyClaudeWiring
|
|
8
|
+
} from "./chunks/compact-before-w1293m4n.mjs";
|
|
9
|
+
import {
|
|
10
|
+
DEFAULTS,
|
|
11
|
+
PLAIN,
|
|
12
|
+
render
|
|
13
|
+
} from "./chunks/compact-before-49j320yp.mjs";
|
|
14
|
+
import {
|
|
15
|
+
__require,
|
|
16
|
+
claudeConfigDir,
|
|
17
|
+
cursorConfigDir,
|
|
18
|
+
projectConfigPath,
|
|
19
|
+
runtimeHome
|
|
20
|
+
} from "./chunks/compact-before-4jrq0sqs.mjs";
|
|
780
21
|
|
|
781
22
|
// tools/init-project.ts
|
|
23
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
24
|
+
import { dirname, join, sep } from "node:path";
|
|
782
25
|
class UsageError extends Error {
|
|
783
26
|
}
|
|
784
27
|
function parseFlags(args) {
|
|
@@ -809,7 +52,7 @@ function usageText(style = PLAIN) {
|
|
|
809
52
|
return render(usageScreen(), style);
|
|
810
53
|
}
|
|
811
54
|
function launcherPath(home = runtimeHome()) {
|
|
812
|
-
return
|
|
55
|
+
return join(home, "bin", "tlc-exec.mjs");
|
|
813
56
|
}
|
|
814
57
|
var SHIM_COMMAND = { command: "node", argsPrefix: [] };
|
|
815
58
|
var CURSOR_SHIM_SPECS = [
|
|
@@ -853,14 +96,14 @@ function claudeShimEntries(launcher) {
|
|
|
853
96
|
...spec.loopLimit !== undefined ? { loopLimit: spec.loopLimit } : {}
|
|
854
97
|
}));
|
|
855
98
|
}
|
|
856
|
-
var PROJECT_SHIMS = [
|
|
99
|
+
var PROJECT_SHIMS = [join(".cursor", "hooks.json"), join(".claude", "settings.json")];
|
|
857
100
|
var GITIGNORE_STATE = ".tlc/harness/state/";
|
|
858
101
|
function gitignoreEntries() {
|
|
859
102
|
return [GITIGNORE_STATE, ...PROJECT_SHIMS.map((path) => path.split(sep).join("/"))];
|
|
860
103
|
}
|
|
861
104
|
function mergeGitignore(root) {
|
|
862
|
-
const path =
|
|
863
|
-
const existing =
|
|
105
|
+
const path = join(root, ".gitignore");
|
|
106
|
+
const existing = existsSync(path) ? readFileSync(path, "utf8") : "";
|
|
864
107
|
const lines = existing.split(`
|
|
865
108
|
`);
|
|
866
109
|
const missing = gitignoreEntries().filter((entry) => !lines.includes(entry));
|
|
@@ -882,15 +125,15 @@ function resolvePolicy(root, flags, stdinText) {
|
|
|
882
125
|
}
|
|
883
126
|
return JSON.parse(stdinText);
|
|
884
127
|
}
|
|
885
|
-
if (!flags.minimal && !flags.stdinJson &&
|
|
886
|
-
return JSON.parse(
|
|
128
|
+
if (!flags.minimal && !flags.stdinJson && existsSync(projectConfigPath(root))) {
|
|
129
|
+
return JSON.parse(readFileSync(projectConfigPath(root), "utf8"));
|
|
887
130
|
}
|
|
888
131
|
return DEFAULTS;
|
|
889
132
|
}
|
|
890
133
|
function detectProviders(dirs = {}) {
|
|
891
134
|
return {
|
|
892
|
-
cursor:
|
|
893
|
-
claude:
|
|
135
|
+
cursor: existsSync(dirs.cursor ?? cursorConfigDir()),
|
|
136
|
+
claude: existsSync(dirs.claude ?? claudeConfigDir())
|
|
894
137
|
};
|
|
895
138
|
}
|
|
896
139
|
function buildPlan(root, flags, stdinText, presence) {
|
|
@@ -906,28 +149,28 @@ function buildPlan(root, flags, stdinText, presence) {
|
|
|
906
149
|
function applyPlan(root, flags, presence, stdinText) {
|
|
907
150
|
const policy = resolvePolicy(root, flags, stdinText);
|
|
908
151
|
const configPath = projectConfigPath(root);
|
|
909
|
-
|
|
910
|
-
|
|
152
|
+
mkdirSync(dirname(configPath), { recursive: true });
|
|
153
|
+
writeFileSync(configPath, `${JSON.stringify(policy, null, 2)}
|
|
911
154
|
`);
|
|
912
155
|
const launcher = launcherPath();
|
|
913
156
|
const cursor = presence.cursor ? (() => {
|
|
914
157
|
const result = applyCursorWiring({
|
|
915
|
-
target:
|
|
158
|
+
target: join(root, ".cursor", "hooks.json"),
|
|
916
159
|
strategy: "replace",
|
|
917
160
|
entries: cursorShimEntries(launcher)
|
|
918
161
|
}, { force: flags.force });
|
|
919
162
|
return { skipped: false, status: result.status, target: result.target };
|
|
920
163
|
})() : { skipped: true };
|
|
921
164
|
const claude = presence.claude ? (() => {
|
|
922
|
-
const result = applyClaudeWiring(
|
|
165
|
+
const result = applyClaudeWiring(join(root, ".claude", "settings.json"), claudeShimEntries(launcher));
|
|
923
166
|
return {
|
|
924
167
|
skipped: false,
|
|
925
168
|
status: result.ok ? result.changed ? "written" : "unchanged" : "failed",
|
|
926
|
-
target:
|
|
169
|
+
target: join(root, ".claude", "settings.json")
|
|
927
170
|
};
|
|
928
171
|
})() : { skipped: true };
|
|
929
172
|
const gitignore = mergeGitignore(root);
|
|
930
|
-
|
|
173
|
+
writeFileSync(join(root, ".gitignore"), gitignore.text);
|
|
931
174
|
return { configPath, cursor, claude };
|
|
932
175
|
}
|
|
933
176
|
async function readStdin() {
|