@tech-leads-club/harness-toolkit 0.3.0 → 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/README.md +46 -11
- package/bin/tlc-build.mjs +35 -6
- package/config.example.json +1 -1
- 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 +18 -1039
- 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 +2 -2
- package/src/core/release/release.version.ts +10 -4
- package/tools/install-runtime.ts +21 -1
|
@@ -1,1003 +1,56 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
OPERATOR_OWNED,
|
|
3
|
+
RUNTIME_PAYLOAD
|
|
4
|
+
} from "./chunks/compact-before-6w8n1vh1.mjs";
|
|
5
|
+
import {
|
|
6
|
+
NPM_MARKER,
|
|
7
|
+
NPM_PACKAGE
|
|
8
|
+
} from "./chunks/compact-before-1e4qg1qt.mjs";
|
|
9
|
+
import"./chunks/compact-before-wnnds45y.mjs";
|
|
10
|
+
import {
|
|
11
|
+
removeClaudeWiring,
|
|
12
|
+
unmergeClaudeSettings,
|
|
13
|
+
unwireCursorHooks
|
|
14
|
+
} from "./chunks/compact-before-w1293m4n.mjs";
|
|
15
|
+
import"./chunks/compact-before-2hpbfxm5.mjs";
|
|
16
|
+
import {
|
|
17
|
+
PLAIN,
|
|
18
|
+
createStyle,
|
|
19
|
+
render
|
|
20
|
+
} from "./chunks/compact-before-49j320yp.mjs";
|
|
21
|
+
import {
|
|
22
|
+
__require,
|
|
23
|
+
claudeConfigDir,
|
|
24
|
+
cursorConfigDir,
|
|
25
|
+
runtimeHome
|
|
26
|
+
} from "./chunks/compact-before-4jrq0sqs.mjs";
|
|
3
27
|
|
|
4
28
|
// tools/uninstall-runtime.ts
|
|
5
29
|
import {
|
|
6
|
-
existsSync
|
|
30
|
+
existsSync,
|
|
7
31
|
lstatSync,
|
|
8
|
-
readFileSync
|
|
32
|
+
readFileSync,
|
|
9
33
|
readlinkSync,
|
|
10
|
-
realpathSync
|
|
34
|
+
realpathSync,
|
|
11
35
|
rmSync,
|
|
12
36
|
statSync,
|
|
13
37
|
unlinkSync,
|
|
14
|
-
writeFileSync
|
|
38
|
+
writeFileSync
|
|
15
39
|
} from "node:fs";
|
|
16
|
-
import { homedir as homedir2 } from "node:os";
|
|
17
|
-
import { basename, dirname, isAbsolute, join as join3, relative as relative2, resolve as resolve2 } from "node:path";
|
|
18
|
-
|
|
19
|
-
// src/platform/paths.ts
|
|
20
40
|
import { homedir } from "node:os";
|
|
21
|
-
import { join } from "node:path";
|
|
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 claudeConfigDir() {
|
|
29
|
-
const custom = process.env.CLAUDE_CONFIG_DIR?.trim();
|
|
30
|
-
return custom && custom.length > 0 ? custom : join(homedir(), ".claude");
|
|
31
|
-
}
|
|
32
|
-
function cursorConfigDir() {
|
|
33
|
-
const custom = process.env.CURSOR_CONFIG_DIR?.trim();
|
|
34
|
-
return custom && custom.length > 0 ? custom : join(homedir(), ".cursor");
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// src/platform/fs-atomic.ts
|
|
38
|
-
var RETRYABLE_CODES = new Set(["EPERM", "EBUSY", "EACCES"]);
|
|
39
|
-
|
|
40
|
-
// src/core/comment-policy/comment-syntax.catalog.ts
|
|
41
|
-
var COMMENT_SYNTAX = [
|
|
42
|
-
{
|
|
43
|
-
id: "typescript",
|
|
44
|
-
extensions: [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"],
|
|
45
|
-
line: ["//"],
|
|
46
|
-
block: [["/*", "*/"]],
|
|
47
|
-
middle: ["*"]
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
id: "python",
|
|
51
|
-
extensions: [".py", ".pyi", ".pyw"],
|
|
52
|
-
line: ["#"],
|
|
53
|
-
block: [
|
|
54
|
-
['"""', '"""'],
|
|
55
|
-
["'''", "'''"]
|
|
56
|
-
],
|
|
57
|
-
middle: []
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
id: "ruby",
|
|
61
|
-
extensions: [".rb", ".rake", ".gemspec"],
|
|
62
|
-
line: ["#"],
|
|
63
|
-
block: [["=begin", "=end"]],
|
|
64
|
-
middle: []
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
id: "shell",
|
|
68
|
-
extensions: [".sh", ".bash", ".zsh", ".ksh", ".fish"],
|
|
69
|
-
line: ["#"],
|
|
70
|
-
block: [],
|
|
71
|
-
middle: []
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
id: "go",
|
|
75
|
-
extensions: [".go"],
|
|
76
|
-
line: ["//"],
|
|
77
|
-
block: [["/*", "*/"]],
|
|
78
|
-
middle: ["*"]
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
id: "rust",
|
|
82
|
-
extensions: [".rs"],
|
|
83
|
-
line: ["//"],
|
|
84
|
-
block: [["/*", "*/"]],
|
|
85
|
-
middle: ["*"]
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
id: "java",
|
|
89
|
-
extensions: [".java"],
|
|
90
|
-
line: ["//"],
|
|
91
|
-
block: [["/*", "*/"]],
|
|
92
|
-
middle: ["*"]
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
id: "kotlin",
|
|
96
|
-
extensions: [".kt", ".kts"],
|
|
97
|
-
line: ["//"],
|
|
98
|
-
block: [["/*", "*/"]],
|
|
99
|
-
middle: ["*"]
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
id: "swift",
|
|
103
|
-
extensions: [".swift"],
|
|
104
|
-
line: ["//"],
|
|
105
|
-
block: [["/*", "*/"]],
|
|
106
|
-
middle: ["*"]
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
id: "c",
|
|
110
|
-
extensions: [".c", ".h"],
|
|
111
|
-
line: ["//"],
|
|
112
|
-
block: [["/*", "*/"]],
|
|
113
|
-
middle: ["*"]
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
id: "cpp",
|
|
117
|
-
extensions: [".cc", ".cpp", ".cxx", ".hpp", ".hh", ".hxx"],
|
|
118
|
-
line: ["//"],
|
|
119
|
-
block: [["/*", "*/"]],
|
|
120
|
-
middle: ["*"]
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
id: "csharp",
|
|
124
|
-
extensions: [".cs"],
|
|
125
|
-
line: ["//"],
|
|
126
|
-
block: [["/*", "*/"]],
|
|
127
|
-
middle: ["*"]
|
|
128
|
-
},
|
|
129
|
-
{
|
|
130
|
-
id: "php",
|
|
131
|
-
extensions: [".php"],
|
|
132
|
-
line: ["//", "#"],
|
|
133
|
-
block: [["/*", "*/"]],
|
|
134
|
-
middle: ["*"]
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
id: "scala",
|
|
138
|
-
extensions: [".scala", ".sc"],
|
|
139
|
-
line: ["//"],
|
|
140
|
-
block: [["/*", "*/"]],
|
|
141
|
-
middle: ["*"]
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
id: "dart",
|
|
145
|
-
extensions: [".dart"],
|
|
146
|
-
line: ["//"],
|
|
147
|
-
block: [["/*", "*/"]],
|
|
148
|
-
middle: ["*"]
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
id: "elixir",
|
|
152
|
-
extensions: [".ex", ".exs"],
|
|
153
|
-
line: ["#"],
|
|
154
|
-
block: [],
|
|
155
|
-
middle: []
|
|
156
|
-
},
|
|
157
|
-
{
|
|
158
|
-
id: "erlang",
|
|
159
|
-
extensions: [".erl", ".hrl"],
|
|
160
|
-
line: ["%"],
|
|
161
|
-
block: [],
|
|
162
|
-
middle: []
|
|
163
|
-
},
|
|
164
|
-
{
|
|
165
|
-
id: "haskell",
|
|
166
|
-
extensions: [".hs"],
|
|
167
|
-
line: ["--"],
|
|
168
|
-
block: [["{-", "-}"]],
|
|
169
|
-
middle: []
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
id: "lua",
|
|
173
|
-
extensions: [".lua"],
|
|
174
|
-
line: ["--"],
|
|
175
|
-
block: [["--[[", "]]"]],
|
|
176
|
-
middle: []
|
|
177
|
-
},
|
|
178
|
-
{
|
|
179
|
-
id: "sql",
|
|
180
|
-
extensions: [".sql"],
|
|
181
|
-
line: ["--"],
|
|
182
|
-
block: [["/*", "*/"]],
|
|
183
|
-
middle: ["*"]
|
|
184
|
-
},
|
|
185
|
-
{
|
|
186
|
-
id: "css",
|
|
187
|
-
extensions: [".css", ".scss", ".sass", ".less"],
|
|
188
|
-
line: ["//"],
|
|
189
|
-
block: [["/*", "*/"]],
|
|
190
|
-
middle: ["*"]
|
|
191
|
-
},
|
|
192
|
-
{
|
|
193
|
-
id: "yaml",
|
|
194
|
-
extensions: [".yaml", ".yml"],
|
|
195
|
-
line: ["#"],
|
|
196
|
-
block: [],
|
|
197
|
-
middle: []
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
id: "toml",
|
|
201
|
-
extensions: [".toml"],
|
|
202
|
-
line: ["#"],
|
|
203
|
-
block: [],
|
|
204
|
-
middle: []
|
|
205
|
-
},
|
|
206
|
-
{
|
|
207
|
-
id: "ini",
|
|
208
|
-
extensions: [".ini", ".cfg", ".conf", ".properties"],
|
|
209
|
-
line: [";", "#"],
|
|
210
|
-
block: [],
|
|
211
|
-
middle: []
|
|
212
|
-
},
|
|
213
|
-
{
|
|
214
|
-
id: "dockerfile",
|
|
215
|
-
extensions: [".dockerfile", "dockerfile"],
|
|
216
|
-
line: ["#"],
|
|
217
|
-
block: [],
|
|
218
|
-
middle: []
|
|
219
|
-
},
|
|
220
|
-
{
|
|
221
|
-
id: "makefile",
|
|
222
|
-
extensions: [".mk", "makefile"],
|
|
223
|
-
line: ["#"],
|
|
224
|
-
block: [],
|
|
225
|
-
middle: []
|
|
226
|
-
},
|
|
227
|
-
{
|
|
228
|
-
id: "terraform",
|
|
229
|
-
extensions: [".tf", ".tfvars"],
|
|
230
|
-
line: ["#", "//"],
|
|
231
|
-
block: [["/*", "*/"]],
|
|
232
|
-
middle: ["*"]
|
|
233
|
-
},
|
|
234
|
-
{
|
|
235
|
-
id: "powershell",
|
|
236
|
-
extensions: [".ps1", ".psm1", ".psd1"],
|
|
237
|
-
line: ["#"],
|
|
238
|
-
block: [["<#", "#>"]],
|
|
239
|
-
middle: []
|
|
240
|
-
},
|
|
241
|
-
{
|
|
242
|
-
id: "perl",
|
|
243
|
-
extensions: [".pl", ".pm"],
|
|
244
|
-
line: ["#"],
|
|
245
|
-
block: [],
|
|
246
|
-
middle: []
|
|
247
|
-
},
|
|
248
|
-
{
|
|
249
|
-
id: "r",
|
|
250
|
-
extensions: [".r"],
|
|
251
|
-
line: ["#"],
|
|
252
|
-
block: [],
|
|
253
|
-
middle: []
|
|
254
|
-
},
|
|
255
|
-
{
|
|
256
|
-
id: "julia",
|
|
257
|
-
extensions: [".jl"],
|
|
258
|
-
line: ["#"],
|
|
259
|
-
block: [["#=", "=#"]],
|
|
260
|
-
middle: []
|
|
261
|
-
},
|
|
262
|
-
{
|
|
263
|
-
id: "vue",
|
|
264
|
-
extensions: [".vue", ".svelte"],
|
|
265
|
-
line: ["//"],
|
|
266
|
-
block: [
|
|
267
|
-
["/*", "*/"],
|
|
268
|
-
["<!--", "-->"]
|
|
269
|
-
],
|
|
270
|
-
middle: ["*"]
|
|
271
|
-
},
|
|
272
|
-
{
|
|
273
|
-
id: "html",
|
|
274
|
-
extensions: [".html", ".htm", ".xml", ".xhtml"],
|
|
275
|
-
line: [],
|
|
276
|
-
block: [["<!--", "-->"]],
|
|
277
|
-
middle: []
|
|
278
|
-
},
|
|
279
|
-
{
|
|
280
|
-
id: "graphql",
|
|
281
|
-
extensions: [".graphql", ".gql"],
|
|
282
|
-
line: ["#"],
|
|
283
|
-
block: [],
|
|
284
|
-
middle: []
|
|
285
|
-
},
|
|
286
|
-
{
|
|
287
|
-
id: "protobuf",
|
|
288
|
-
extensions: [".proto"],
|
|
289
|
-
line: ["//"],
|
|
290
|
-
block: [["/*", "*/"]],
|
|
291
|
-
middle: ["*"]
|
|
292
|
-
},
|
|
293
|
-
{
|
|
294
|
-
id: "zig",
|
|
295
|
-
extensions: [".zig"],
|
|
296
|
-
line: ["//"],
|
|
297
|
-
block: [],
|
|
298
|
-
middle: []
|
|
299
|
-
},
|
|
300
|
-
{
|
|
301
|
-
id: "clojure",
|
|
302
|
-
extensions: [".clj", ".cljs", ".cljc", ".edn"],
|
|
303
|
-
line: [";"],
|
|
304
|
-
block: [],
|
|
305
|
-
middle: []
|
|
306
|
-
},
|
|
307
|
-
{
|
|
308
|
-
id: "ocaml",
|
|
309
|
-
extensions: [".ml", ".mli"],
|
|
310
|
-
line: [],
|
|
311
|
-
block: [["(*", "*)"]],
|
|
312
|
-
middle: ["*"]
|
|
313
|
-
},
|
|
314
|
-
{
|
|
315
|
-
id: "fsharp",
|
|
316
|
-
extensions: [".fs", ".fsi", ".fsx"],
|
|
317
|
-
line: ["//"],
|
|
318
|
-
block: [["(*", "*)"]],
|
|
319
|
-
middle: ["*"]
|
|
320
|
-
},
|
|
321
|
-
{
|
|
322
|
-
id: "vim",
|
|
323
|
-
extensions: [".vim"],
|
|
324
|
-
line: ['"'],
|
|
325
|
-
block: [],
|
|
326
|
-
middle: []
|
|
327
|
-
},
|
|
328
|
-
{
|
|
329
|
-
id: "tex",
|
|
330
|
-
extensions: [".tex", ".sty", ".cls"],
|
|
331
|
-
line: ["%"],
|
|
332
|
-
block: [],
|
|
333
|
-
middle: []
|
|
334
|
-
}
|
|
335
|
-
];
|
|
336
|
-
|
|
337
|
-
// src/core/comment-policy/comment-syntax.store.ts
|
|
338
|
-
function buildIndex(entries) {
|
|
339
|
-
const byKey = new Map;
|
|
340
|
-
for (const entry of entries) {
|
|
341
|
-
const syntax = { line: entry.line, block: entry.block, middle: entry.middle };
|
|
342
|
-
for (const extension of entry.extensions) {
|
|
343
|
-
byKey.set(extension.toLowerCase(), syntax);
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
return byKey;
|
|
347
|
-
}
|
|
348
|
-
var INDEX = buildIndex(COMMENT_SYNTAX);
|
|
349
|
-
var KNOWN_EXTENSION_COUNT = INDEX.size;
|
|
350
|
-
|
|
351
|
-
// src/core/comment-policy/comment-policy.service.ts
|
|
352
|
-
var STOPWORDS = new Set([
|
|
353
|
-
"a",
|
|
354
|
-
"an",
|
|
355
|
-
"and",
|
|
356
|
-
"are",
|
|
357
|
-
"as",
|
|
358
|
-
"at",
|
|
359
|
-
"be",
|
|
360
|
-
"by",
|
|
361
|
-
"for",
|
|
362
|
-
"from",
|
|
363
|
-
"get",
|
|
364
|
-
"gets",
|
|
365
|
-
"has",
|
|
366
|
-
"in",
|
|
367
|
-
"into",
|
|
368
|
-
"is",
|
|
369
|
-
"it",
|
|
370
|
-
"its",
|
|
371
|
-
"of",
|
|
372
|
-
"on",
|
|
373
|
-
"or",
|
|
374
|
-
"return",
|
|
375
|
-
"returns",
|
|
376
|
-
"set",
|
|
377
|
-
"sets",
|
|
378
|
-
"that",
|
|
379
|
-
"the",
|
|
380
|
-
"then",
|
|
381
|
-
"this",
|
|
382
|
-
"to",
|
|
383
|
-
"true",
|
|
384
|
-
"when",
|
|
385
|
-
"which",
|
|
386
|
-
"with"
|
|
387
|
-
]);
|
|
388
|
-
|
|
389
|
-
// src/core/duplication/duplication.service.ts
|
|
390
|
-
var MIN_RUN = 6;
|
|
391
|
-
|
|
392
|
-
// src/core/floor/floor.paths.ts
|
|
393
|
-
var SECRET_BASENAMES = new Set([
|
|
394
|
-
".git-credentials",
|
|
395
|
-
".netrc",
|
|
396
|
-
".npmrc",
|
|
397
|
-
".pgpass",
|
|
398
|
-
"credentials",
|
|
399
|
-
"id_dsa",
|
|
400
|
-
"id_ecdsa",
|
|
401
|
-
"id_ed25519",
|
|
402
|
-
"id_rsa"
|
|
403
|
-
]);
|
|
404
|
-
|
|
405
|
-
// src/core/floor/floor.tokenize.ts
|
|
406
|
-
var SEPARATORS = new Set([";", "|", "&", `
|
|
407
|
-
`]);
|
|
408
|
-
var ESCAPABLE = new Set([" ", "\t", '"', "'", "$", "`", "\\", ";", "|", "&", "(", ")"]);
|
|
409
|
-
|
|
410
|
-
// src/core/floor/floor.verb.ts
|
|
411
|
-
var WRAPPERS = new Set(["command", "doas", "env", "nice", "nohup", "sudo", "time", "xargs"]);
|
|
412
|
-
|
|
413
|
-
// src/core/floor/floor.policy-surface.ts
|
|
414
|
-
var PROVEN_READERS = new Set([
|
|
415
|
-
"cat",
|
|
416
|
-
"cmp",
|
|
417
|
-
"diff",
|
|
418
|
-
"echo",
|
|
419
|
-
"file",
|
|
420
|
-
"grep",
|
|
421
|
-
"head",
|
|
422
|
-
"jq",
|
|
423
|
-
"less",
|
|
424
|
-
"ls",
|
|
425
|
-
"md5sum",
|
|
426
|
-
"more",
|
|
427
|
-
"od",
|
|
428
|
-
"printf",
|
|
429
|
-
"rg",
|
|
430
|
-
"sha256sum",
|
|
431
|
-
"stat",
|
|
432
|
-
"strings",
|
|
433
|
-
"tail",
|
|
434
|
-
"test",
|
|
435
|
-
"[",
|
|
436
|
-
"wc",
|
|
437
|
-
"xxd"
|
|
438
|
-
]);
|
|
439
|
-
var GIT_READERS = new Set(["show", "diff", "log", "status", "ls-files", "cat-file", "blame"]);
|
|
440
|
-
var EXECUTES_STDIN = new Set([
|
|
441
|
-
"ash",
|
|
442
|
-
"awk",
|
|
443
|
-
"bash",
|
|
444
|
-
"bun",
|
|
445
|
-
"dash",
|
|
446
|
-
"deno",
|
|
447
|
-
"ed",
|
|
448
|
-
"ex",
|
|
449
|
-
"fish",
|
|
450
|
-
"gawk",
|
|
451
|
-
"ksh",
|
|
452
|
-
"lua",
|
|
453
|
-
"node",
|
|
454
|
-
"perl",
|
|
455
|
-
"php",
|
|
456
|
-
"python",
|
|
457
|
-
"python2",
|
|
458
|
-
"python3",
|
|
459
|
-
"ruby",
|
|
460
|
-
"sed",
|
|
461
|
-
"sh",
|
|
462
|
-
"tclsh",
|
|
463
|
-
"zsh"
|
|
464
|
-
]);
|
|
465
|
-
var HARNESS_BINS = new Set(["tlc", "tlc.cmd"]);
|
|
466
|
-
var MUTATING_SUBCOMMANDS = new Set(["pause", "resume", "grind", "mode", "init", "gate", "policy"]);
|
|
467
|
-
|
|
468
|
-
// src/core/floor/floor.service.ts
|
|
469
|
-
var DESTRUCTIVE_VERBS = new Set(["dd", "rm", "rmdir", "shred", "truncate"]);
|
|
470
|
-
var MACHINE_VERBS = new Set(["halt", "poweroff", "reboot", "shutdown"]);
|
|
471
|
-
var READER_VERBS = new Set(["base64", "cat", "head", "less", "more", "od", "strings", "tail", "xxd"]);
|
|
472
|
-
var READING_TOOLS = new Set(["Read", "Edit", "MultiEdit", "NotebookEdit"]);
|
|
473
|
-
var EXPANDING_VERBS = new Set([".", "eval", "source"]);
|
|
474
|
-
var SHELLS = new Set(["ash", "bash", "dash", "fish", "ksh", "sh", "zsh"]);
|
|
475
|
-
var FETCH_VERBS = new Set(["aria2c", "curl", "fetch", "http", "httpie", "https", "wget"]);
|
|
476
|
-
var NETWORK_VERBS = new Set([...FETCH_VERBS, "nc", "ncat", "socat", "telnet", "lwp-request"]);
|
|
477
|
-
|
|
478
|
-
// src/core/gate/gate.findings.ts
|
|
479
|
-
var SOURCE_EXT = "ts|tsx|mts|cts|js|jsx|mjs|cjs|py|go|rb|rs|java|kt|swift|php|sh|sql";
|
|
480
|
-
var PATH_IN_OUTPUT = new RegExp(`(?:file://)?((?:[A-Za-z]:)?[\\w./~@+-]*[\\w-]\\.(?:${SOURCE_EXT}))(?=[:)\\s,'"\`]|$)`, "g");
|
|
481
|
-
|
|
482
|
-
// src/core/gate/gate.command.ts
|
|
483
|
-
var RECIPE_RUNNERS = new Set(["just", "make", "task", "mise", "rake"]);
|
|
484
|
-
var SCRIPT_RUNNERS = new Set(["npm", "yarn", "pnpm"]);
|
|
485
|
-
var TRANSPARENT_PREFIXES = new Set(["npx", "bunx", "dlx", "exec"]);
|
|
486
|
-
|
|
487
|
-
// src/core/gate/gate.lock.ts
|
|
488
|
-
var GATE_LOCK_STALE_MS = 30 * 60 * 1000;
|
|
489
|
-
|
|
490
|
-
// src/core/lesson/lesson.store.ts
|
|
491
|
-
var EPOCH = "1970-01-01T00:00:00.000Z";
|
|
492
|
-
function coreLesson(input) {
|
|
493
|
-
return {
|
|
494
|
-
...input,
|
|
495
|
-
scope: "gate-execution",
|
|
496
|
-
source: "core",
|
|
497
|
-
tier: "core",
|
|
498
|
-
status: "active",
|
|
499
|
-
confidence: 1,
|
|
500
|
-
hitCount: 1,
|
|
501
|
-
pinned: false,
|
|
502
|
-
refs: [],
|
|
503
|
-
sessionKeys: [],
|
|
504
|
-
injectedCount: 0,
|
|
505
|
-
gradeableCount: 0,
|
|
506
|
-
helpedCount: 0,
|
|
507
|
-
neutralCount: 0,
|
|
508
|
-
firstSeenAt: EPOCH,
|
|
509
|
-
lastSeenAt: EPOCH,
|
|
510
|
-
lastAccessedAt: EPOCH,
|
|
511
|
-
updatedAt: EPOCH
|
|
512
|
-
};
|
|
513
|
-
}
|
|
514
|
-
var CORE_LESSONS = [
|
|
515
|
-
coreLesson({
|
|
516
|
-
id: "core:gate:lint",
|
|
517
|
-
failedGate: "lint",
|
|
518
|
-
category: "verification",
|
|
519
|
-
triggerTokens: ["lint", "biome", "eslint", "ruff", "format"],
|
|
520
|
-
instruction: "A lint gate failure means changed files still violate the project lint command. Fix the reported findings without suppressions.",
|
|
521
|
-
avoid: "Do not add lint suppressions, disable comments, or delete failing files to silence the gate.",
|
|
522
|
-
prefer: "Apply the smallest fix that clears each finding, then let the stop hook re-check.",
|
|
523
|
-
preRetryCheck: "Confirm the lint command targets only the intended changed files and still fails for the same codes.",
|
|
524
|
-
priority: 90
|
|
525
|
-
}),
|
|
526
|
-
coreLesson({
|
|
527
|
-
id: "core:gate:test",
|
|
528
|
-
failedGate: "test",
|
|
529
|
-
category: "verification",
|
|
530
|
-
triggerTokens: ["test", "vitest", "jest", "pytest", "failing"],
|
|
531
|
-
instruction: "A test gate failure means assertions still fail. Fix the behavior or the test under the real contract — do not delete or skip tests.",
|
|
532
|
-
avoid: "Do not delete failing tests, mark them skipped, or weaken assertions to force green.",
|
|
533
|
-
prefer: "Reproduce the failure, fix root cause, re-run the same test target.",
|
|
534
|
-
preRetryCheck: "Identify the failing test name/file from the gate output before editing.",
|
|
535
|
-
priority: 90
|
|
536
|
-
}),
|
|
537
|
-
coreLesson({
|
|
538
|
-
id: "core:gate:comments",
|
|
539
|
-
failedGate: "comments",
|
|
540
|
-
category: "verification",
|
|
541
|
-
triggerTokens: ["junk comment", "TODO", "FIXME", "banner"],
|
|
542
|
-
instruction: "Junk-comment policy failed. Delete narrating comments, banners, TODO/FIXME, and commented-out code.",
|
|
543
|
-
avoid: "Do not keep TODO markers or section banners 'for clarity'.",
|
|
544
|
-
prefer: "Keep only comments that explain a non-obvious why (invariant, hazard, external constraint).",
|
|
545
|
-
preRetryCheck: "Scan the listed file:line hits and remove each one.",
|
|
546
|
-
priority: 80
|
|
547
|
-
}),
|
|
548
|
-
coreLesson({
|
|
549
|
-
id: "core:gate:ship",
|
|
550
|
-
failedGate: "ship",
|
|
551
|
-
category: "ship-evidence",
|
|
552
|
-
triggerTokens: ["ship", "evidence", "90-verdict", "PASS"],
|
|
553
|
-
instruction: "Ship claim without recent production PASS evidence. Produce real evidence before claiming done.",
|
|
554
|
-
avoid: "Do not claim shipped based on unit tests alone when runtime paths changed.",
|
|
555
|
-
prefer: "Run production E2E, write 90-verdict.txt PASS, cite the evidence path.",
|
|
556
|
-
preRetryCheck: "Confirm evidenceDir and a recent PASS verdict exist for this change.",
|
|
557
|
-
priority: 95
|
|
558
|
-
}),
|
|
559
|
-
coreLesson({
|
|
560
|
-
id: "core:gate:empty-diff",
|
|
561
|
-
failedGate: "empty-diff",
|
|
562
|
-
category: "ship-evidence",
|
|
563
|
-
triggerTokens: ["empty", "diff", "no changes", "shipped"],
|
|
564
|
-
instruction: "Done/shipped was claimed with zero file changes. Either implement the work or explain why zero-diff is correct — do not claim shipped on an empty tree.",
|
|
565
|
-
avoid: "Do not restate 'done' without a real diff or an explicit zero-change justification.",
|
|
566
|
-
prefer: "Make the missing change, or clearly document why no files should change.",
|
|
567
|
-
preRetryCheck: "Inspect git status / changed files before the next stop.",
|
|
568
|
-
priority: 92
|
|
569
|
-
}),
|
|
570
|
-
coreLesson({
|
|
571
|
-
id: "core:gate:stagnation",
|
|
572
|
-
failedGate: "stagnation",
|
|
573
|
-
category: "stagnation",
|
|
574
|
-
triggerTokens: ["stagnation", "identical", "fingerprint", "same fail"],
|
|
575
|
-
instruction: "Identical validation fingerprint repeated. Change approach — do not re-apply the same failing edit.",
|
|
576
|
-
avoid: "Do not retry the exact same patch, command, or suppression.",
|
|
577
|
-
prefer: "Diagnose root cause with a different path, or escalate with BLOCKED / TRIED / NEED.",
|
|
578
|
-
preRetryCheck: "Diff your last edit against the gate output; ensure the next action is different.",
|
|
579
|
-
priority: 100
|
|
580
|
-
})
|
|
581
|
-
];
|
|
582
|
-
|
|
583
|
-
// src/platform/style.ts
|
|
584
|
-
var COLORS = {
|
|
585
|
-
structure: "#3d3a4a",
|
|
586
|
-
accent: "#a78bfa",
|
|
587
|
-
success: "#6ee7b7",
|
|
588
|
-
warning: "#d4a574",
|
|
589
|
-
error: "#f87171",
|
|
590
|
-
info: "#93c5fd",
|
|
591
|
-
textMain: "#f5f5f7",
|
|
592
|
-
textMuted: "#9ca3af",
|
|
593
|
-
textDim: "#6b7280"
|
|
594
|
-
};
|
|
595
|
-
var SYMBOLS = {
|
|
596
|
-
check: "✔",
|
|
597
|
-
cross: "✖",
|
|
598
|
-
warning: "⚠",
|
|
599
|
-
arrow: "→",
|
|
600
|
-
arrowRight: "▸",
|
|
601
|
-
dot: "•",
|
|
602
|
-
bar: "│",
|
|
603
|
-
rule: "══",
|
|
604
|
-
dash: "──"
|
|
605
|
-
};
|
|
606
|
-
function rgb(hex) {
|
|
607
|
-
const match = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex.trim());
|
|
608
|
-
if (!match) {
|
|
609
|
-
return "255;255;255";
|
|
610
|
-
}
|
|
611
|
-
return [match[1], match[2], match[3]].map((part) => Number.parseInt(part, 16)).join(";");
|
|
612
|
-
}
|
|
613
|
-
var ESC = String.fromCharCode(27);
|
|
614
|
-
var RESET = `${ESC}[0m`;
|
|
615
|
-
function colorEnabled(env = process.env, argv = process.argv, isTty = process.stdout.isTTY === true) {
|
|
616
|
-
if ("NO_COLOR" in env) {
|
|
617
|
-
return false;
|
|
618
|
-
}
|
|
619
|
-
if (argv.includes("--no-color")) {
|
|
620
|
-
return false;
|
|
621
|
-
}
|
|
622
|
-
return isTty;
|
|
623
|
-
}
|
|
624
|
-
var STATUS_COLOR = {
|
|
625
|
-
ok: "success",
|
|
626
|
-
warn: "warning",
|
|
627
|
-
fail: "error",
|
|
628
|
-
info: "info"
|
|
629
|
-
};
|
|
630
|
-
var STATUS_MARK = {
|
|
631
|
-
ok: SYMBOLS.check,
|
|
632
|
-
warn: SYMBOLS.warning,
|
|
633
|
-
fail: SYMBOLS.cross,
|
|
634
|
-
info: SYMBOLS.arrowRight
|
|
635
|
-
};
|
|
636
|
-
var KV_WIDTH = 16;
|
|
637
|
-
function createStyle(enabled = colorEnabled()) {
|
|
638
|
-
const wrap = (code, text) => enabled ? `${ESC}[${code}m${text}${RESET}` : text;
|
|
639
|
-
const paint = (name, text) => wrap(`38;2;${rgb(COLORS[name])}`, text);
|
|
640
|
-
return {
|
|
641
|
-
enabled,
|
|
642
|
-
paint,
|
|
643
|
-
bold: (text) => wrap("1", text),
|
|
644
|
-
dim: (text) => paint("textDim", text),
|
|
645
|
-
heading: (text) => paint("accent", `${SYMBOLS.rule} ${text} ${SYMBOLS.rule}`),
|
|
646
|
-
footer: (text) => paint("textDim", `${SYMBOLS.dash} ${text} ${SYMBOLS.dash}`),
|
|
647
|
-
kv: (label, value, width = KV_WIDTH) => ` ${paint("textMuted", `${label}:`.padEnd(width))} ${value}`,
|
|
648
|
-
status: (level, text) => `${paint(STATUS_COLOR[level], STATUS_MARK[level])} ${text}`
|
|
649
|
-
};
|
|
650
|
-
}
|
|
651
|
-
var PLAIN = createStyle(false);
|
|
652
|
-
|
|
653
|
-
// src/platform/screen.ts
|
|
654
|
-
function render(screen, style) {
|
|
655
|
-
const out = [style.heading(screen.title.toUpperCase())];
|
|
656
|
-
if (screen.summary && screen.summary.length > 0) {
|
|
657
|
-
out.push(` ${screen.summary.join(style.dim(` ${SYMBOLS.bar} `))}`);
|
|
658
|
-
}
|
|
659
|
-
const width = Math.max(KV_WIDTH, ...screen.sections.flatMap((section) => (section.rows ?? []).map((row) => row.label.length + 1)));
|
|
660
|
-
for (const section of screen.sections) {
|
|
661
|
-
out.push("");
|
|
662
|
-
if (section.title) {
|
|
663
|
-
out.push(style.paint("accent", section.title));
|
|
664
|
-
}
|
|
665
|
-
for (const row of section.rows ?? []) {
|
|
666
|
-
const value = row.level ? style.status(row.level, row.value) : row.value;
|
|
667
|
-
out.push(style.kv(row.label, value, width));
|
|
668
|
-
}
|
|
669
|
-
for (const line of section.lines ?? []) {
|
|
670
|
-
out.push(line === "" ? "" : ` ${line}`);
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
if (screen.footer) {
|
|
674
|
-
out.push("", style.footer(screen.footer));
|
|
675
|
-
}
|
|
676
|
-
return out.join(`
|
|
677
|
-
`);
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
// src/core/observability/observability.report.ts
|
|
681
|
-
var SHELL_TOOLS = new Set(["Bash", "run_terminal_cmd", "terminal"]);
|
|
682
|
-
|
|
683
|
-
// src/core/observability/observability.types.ts
|
|
684
|
-
var DEFAULT_OBS = {
|
|
685
|
-
enabled: true,
|
|
686
|
-
signalPath: "obs.jsonl",
|
|
687
|
-
debugPath: "debug.jsonl",
|
|
688
|
-
debugEnabled: false,
|
|
689
|
-
includePayloads: false,
|
|
690
|
-
maxAttrChars: 500,
|
|
691
|
-
sessionCostAlertUsd: 5,
|
|
692
|
-
retentionDays: 14,
|
|
693
|
-
maxSignalEvents: 50000,
|
|
694
|
-
globalSpool: false
|
|
695
|
-
};
|
|
696
|
-
var SIGNAL_KINDS = new Set([
|
|
697
|
-
"session.start",
|
|
698
|
-
"session.end",
|
|
699
|
-
"generation.end",
|
|
700
|
-
"tool.fail",
|
|
701
|
-
"subagent.start",
|
|
702
|
-
"subagent.end",
|
|
703
|
-
"prompt.submit",
|
|
704
|
-
"compact",
|
|
705
|
-
"gate.outcome",
|
|
706
|
-
"cost.turn",
|
|
707
|
-
"cost.session_alert",
|
|
708
|
-
"ship.claim",
|
|
709
|
-
"policy.deny",
|
|
710
|
-
"policy.observe"
|
|
711
|
-
]);
|
|
712
|
-
var LIVE_ALLOWLIST = new Set([
|
|
713
|
-
"session.start",
|
|
714
|
-
"session.end",
|
|
715
|
-
"generation.end",
|
|
716
|
-
"tool.fail",
|
|
717
|
-
"shell.end",
|
|
718
|
-
"subagent.start",
|
|
719
|
-
"subagent.end",
|
|
720
|
-
"gate.outcome",
|
|
721
|
-
"cost.turn",
|
|
722
|
-
"cost.session_alert",
|
|
723
|
-
"ship.claim",
|
|
724
|
-
"policy.deny",
|
|
725
|
-
"compact",
|
|
726
|
-
"prompt.submit"
|
|
727
|
-
]);
|
|
728
|
-
|
|
729
|
-
// src/core/observability/observability.service.ts
|
|
730
|
-
var PAYLOAD_KEYS = new Set(["tool_input", "tool_output", "prompt", "text", "content", "output"]);
|
|
731
|
-
|
|
732
|
-
// src/core/observability/observability.why.ts
|
|
733
|
-
var NONE = new Set(["none", "", "undefined"]);
|
|
734
|
-
var NOTHING_WAS_THE_HARNESS = [
|
|
735
|
-
"No harness decision in this window.",
|
|
736
|
-
"Whatever you just saw was the model, not a rail — the harness allowed everything it was asked about."
|
|
737
|
-
].join(`
|
|
738
|
-
`);
|
|
739
|
-
|
|
740
|
-
// src/core/policy/policy.defaults.ts
|
|
741
|
-
var DEFAULT_LESSONS_POLICY = {
|
|
742
|
-
enabled: false,
|
|
743
|
-
maxInjectSession: 5,
|
|
744
|
-
maxInjectRetry: 8,
|
|
745
|
-
maxCharsSession: 900,
|
|
746
|
-
maxCharsRetry: 1400,
|
|
747
|
-
promoteHitCount: 2,
|
|
748
|
-
decayLambda: 0.02,
|
|
749
|
-
projectBoost: 1.5,
|
|
750
|
-
syncRulesFile: "auto",
|
|
751
|
-
gardenOnSessionEnd: true
|
|
752
|
-
};
|
|
753
|
-
var DEFAULTS = {
|
|
754
|
-
version: 1,
|
|
755
|
-
mode: "solo",
|
|
756
|
-
codePaths: ["src", "apps", "libs", "packages"],
|
|
757
|
-
grind: {
|
|
758
|
-
enabled: false,
|
|
759
|
-
maxLoops: 5,
|
|
760
|
-
lintCommand: null,
|
|
761
|
-
testCommand: null,
|
|
762
|
-
appendFiles: "auto"
|
|
763
|
-
},
|
|
764
|
-
shipGate: {
|
|
765
|
-
enabled: false,
|
|
766
|
-
runtimePathPrefixes: ["src", "apps", "libs", "packages", "deploy", "scripts"],
|
|
767
|
-
runtimePathExcludes: [".tlc/", "**/node_modules/", "**/.git/"],
|
|
768
|
-
evidenceDir: null,
|
|
769
|
-
evidenceMaxAgeHours: 48,
|
|
770
|
-
emptyDiffAntiShip: false,
|
|
771
|
-
claimWindowMinutes: 10
|
|
772
|
-
},
|
|
773
|
-
subagents: {
|
|
774
|
-
enforceAllowlist: false,
|
|
775
|
-
requireModel: false,
|
|
776
|
-
allowedModels: [],
|
|
777
|
-
blockedPatterns: ["-fast(?:$|[^a-z0-9])", "/fast(?:$|[^a-z0-9])"],
|
|
778
|
-
minEffort: null,
|
|
779
|
-
blockParentFast: false,
|
|
780
|
-
blockMode: "deny",
|
|
781
|
-
readOnlyTypes: ["explore"]
|
|
782
|
-
},
|
|
783
|
-
docs: {
|
|
784
|
-
command: null,
|
|
785
|
-
severity: "warn"
|
|
786
|
-
},
|
|
787
|
-
observe: {
|
|
788
|
-
enabled: false,
|
|
789
|
-
rails: []
|
|
790
|
-
},
|
|
791
|
-
comments: {
|
|
792
|
-
enabled: false,
|
|
793
|
-
onViolation: "followup",
|
|
794
|
-
mode: "declared"
|
|
795
|
-
},
|
|
796
|
-
supplyChain: {
|
|
797
|
-
enabled: false
|
|
798
|
-
},
|
|
799
|
-
duplication: {
|
|
800
|
-
enabled: false,
|
|
801
|
-
minRun: MIN_RUN
|
|
802
|
-
},
|
|
803
|
-
obs: {
|
|
804
|
-
globalSpool: false,
|
|
805
|
-
includePayloads: DEFAULT_OBS.includePayloads,
|
|
806
|
-
maxAttrChars: DEFAULT_OBS.maxAttrChars,
|
|
807
|
-
sessionCostAlertUsd: DEFAULT_OBS.sessionCostAlertUsd,
|
|
808
|
-
retentionDays: DEFAULT_OBS.retentionDays
|
|
809
|
-
},
|
|
810
|
-
untrustedContent: {
|
|
811
|
-
mode: "frame",
|
|
812
|
-
enabled: false,
|
|
813
|
-
extraTools: [],
|
|
814
|
-
extraCommandPatterns: []
|
|
815
|
-
},
|
|
816
|
-
planGate: {
|
|
817
|
-
enabled: false,
|
|
818
|
-
windowMinutes: 120
|
|
819
|
-
},
|
|
820
|
-
shell: {
|
|
821
|
-
catastrophicAsk: true,
|
|
822
|
-
stallDetection: false,
|
|
823
|
-
stallRepeatThreshold: 3
|
|
824
|
-
},
|
|
825
|
-
intelligence: {
|
|
826
|
-
gapFeedback: true,
|
|
827
|
-
failureClassification: true,
|
|
828
|
-
progressiveHandoff: true,
|
|
829
|
-
progressiveContext: true,
|
|
830
|
-
autopilot: true,
|
|
831
|
-
idleTurnGate: false,
|
|
832
|
-
budgetContinue: false,
|
|
833
|
-
budgetContinueAfterLoops: 3,
|
|
834
|
-
lessons: { ...DEFAULT_LESSONS_POLICY }
|
|
835
|
-
},
|
|
836
|
-
mcpPrime: [],
|
|
837
|
-
bootstrapExtra: []
|
|
838
|
-
};
|
|
839
|
-
|
|
840
|
-
// src/core/policy/policy.guard.ts
|
|
841
|
-
var WRITE_TOOLS = new Set(["Edit", "Write", "Delete", "MultiEdit", "NotebookEdit"]);
|
|
842
|
-
|
|
843
|
-
// src/core/presence/presence.service.ts
|
|
844
|
-
var STALE_MS = 10 * 60 * 1000;
|
|
845
|
-
|
|
846
|
-
// src/core/shell-policy/shell-policy.service.ts
|
|
847
|
-
var WRAPPERS2 = new Set(["command", "doas", "env", "nice", "nohup", "sudo", "time", "xargs"]);
|
|
848
|
-
var MACHINE = new Set(["halt", "poweroff", "reboot", "shutdown"]);
|
|
849
|
-
var NETWORK = new Set(["curl", "ftp", "gh", "nc", "ncat", "rsync", "scp", "sftp", "ssh", "telnet", "wget"]);
|
|
850
|
-
var WRITE = new Set(["cp", "mv", "rm", "rmdir", "tee", "truncate"]);
|
|
851
|
-
var PRIVILEGE = new Set(["chmod", "chown"]);
|
|
852
|
-
var PAIRED_ASK = new Set(["write", "privilege", "network"]);
|
|
853
|
-
// src/core/supply-chain/supply-chain.service.ts
|
|
854
|
-
var UNPINNED_SPECS = new Set(["latest", "*", "x", "X", "", "main", "master", "HEAD"]);
|
|
855
|
-
|
|
856
|
-
// src/core/turn/turn.activity.ts
|
|
857
|
-
var TOOL_KINDS = new Set([
|
|
858
|
-
"tool.start",
|
|
859
|
-
"tool.end",
|
|
860
|
-
"tool.fail",
|
|
861
|
-
"shell.start",
|
|
862
|
-
"shell.end",
|
|
863
|
-
"mcp.start",
|
|
864
|
-
"mcp.end",
|
|
865
|
-
"file.edit",
|
|
866
|
-
"file.read"
|
|
867
|
-
]);
|
|
868
|
-
// bin/tlc-cli.ts
|
|
869
|
-
var NPM_PACKAGE = "@tech-leads-club/harness-toolkit";
|
|
870
|
-
var NPM_MARKER = "installed-from-npm";
|
|
871
|
-
if (false) {}
|
|
872
|
-
|
|
873
|
-
// src/providers/claude/claude.wiring.ts
|
|
874
|
-
import { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from "node:fs";
|
|
875
|
-
function isPlainRecord(value) {
|
|
876
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
877
|
-
}
|
|
878
|
-
function isHooksRecord(value) {
|
|
879
|
-
return isPlainRecord(value);
|
|
880
|
-
}
|
|
881
|
-
var LAUNCHER_MARKER = "tlc-exec.mjs";
|
|
882
|
-
function isHarnessGroup(group) {
|
|
883
|
-
return JSON.stringify(group ?? null).includes(LAUNCHER_MARKER);
|
|
884
|
-
}
|
|
885
|
-
function unmergeClaudeSettings(existingText) {
|
|
886
|
-
if (existingText === null || existingText.trim() === "") {
|
|
887
|
-
return { ok: true, settingsText: "", changed: false };
|
|
888
|
-
}
|
|
889
|
-
let parsed;
|
|
890
|
-
try {
|
|
891
|
-
parsed = JSON.parse(existingText);
|
|
892
|
-
} catch (error) {
|
|
893
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
894
|
-
return { ok: false, error: message, block: "" };
|
|
895
|
-
}
|
|
896
|
-
if (!isPlainRecord(parsed)) {
|
|
897
|
-
return { ok: false, error: "settings.json root is not a JSON object", block: "" };
|
|
898
|
-
}
|
|
899
|
-
const currentHooks = isHooksRecord(parsed.hooks) ? parsed.hooks : {};
|
|
900
|
-
const remainingHooks = {};
|
|
901
|
-
let changed = false;
|
|
902
|
-
for (const [hookEvent, groups] of Object.entries(currentHooks)) {
|
|
903
|
-
const foreign = groups.filter((group) => !isHarnessGroup(group));
|
|
904
|
-
if (foreign.length !== groups.length) {
|
|
905
|
-
changed = true;
|
|
906
|
-
}
|
|
907
|
-
if (foreign.length > 0) {
|
|
908
|
-
remainingHooks[hookEvent] = foreign;
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
const next = {};
|
|
912
|
-
for (const [key, value] of Object.entries(parsed)) {
|
|
913
|
-
if (key !== "hooks") {
|
|
914
|
-
next[key] = value;
|
|
915
|
-
} else if (Object.keys(remainingHooks).length > 0) {
|
|
916
|
-
next.hooks = remainingHooks;
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
return { ok: true, settingsText: JSON.stringify(next, null, 2), changed };
|
|
920
|
-
}
|
|
921
|
-
function removeClaudeWiring(settingsPath) {
|
|
922
|
-
if (!existsSync(settingsPath)) {
|
|
923
|
-
return { ok: true, settingsText: "", changed: false };
|
|
924
|
-
}
|
|
925
|
-
const result = unmergeClaudeSettings(readFileSync(settingsPath, "utf8"));
|
|
926
|
-
if (result.ok && result.changed) {
|
|
927
|
-
writeFileSync(settingsPath, result.settingsText, "utf8");
|
|
928
|
-
}
|
|
929
|
-
return result;
|
|
930
|
-
}
|
|
931
|
-
|
|
932
|
-
// src/providers/cursor/cursor.wiring.ts
|
|
933
|
-
function unwireCursorHooks(text, marker = "tlc-exec.mjs") {
|
|
934
|
-
if (text === null || text.trim() === "") {
|
|
935
|
-
return { kind: "absent" };
|
|
936
|
-
}
|
|
937
|
-
let parsed;
|
|
938
|
-
try {
|
|
939
|
-
parsed = JSON.parse(text);
|
|
940
|
-
} catch {
|
|
941
|
-
return { kind: "unparsed" };
|
|
942
|
-
}
|
|
943
|
-
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
944
|
-
return { kind: "unparsed" };
|
|
945
|
-
}
|
|
946
|
-
const document = parsed;
|
|
947
|
-
const hooks = document.hooks !== null && typeof document.hooks === "object" && !Array.isArray(document.hooks) ? document.hooks : {};
|
|
948
|
-
const remaining = {};
|
|
949
|
-
let removed = 0;
|
|
950
|
-
let kept = 0;
|
|
951
|
-
for (const [hookEvent, value] of Object.entries(hooks)) {
|
|
952
|
-
const list = Array.isArray(value) ? value : [];
|
|
953
|
-
const foreign = list.filter((row) => !JSON.stringify(row ?? null).includes(marker));
|
|
954
|
-
removed += list.length - foreign.length;
|
|
955
|
-
if (foreign.length > 0) {
|
|
956
|
-
remaining[hookEvent] = foreign;
|
|
957
|
-
kept += foreign.length;
|
|
958
|
-
}
|
|
959
|
-
}
|
|
960
|
-
if (kept === 0) {
|
|
961
|
-
return { kind: "empty", removed };
|
|
962
|
-
}
|
|
963
|
-
return {
|
|
964
|
-
kind: "rewritten",
|
|
965
|
-
removed,
|
|
966
|
-
text: `${JSON.stringify({ ...document, hooks: remaining }, null, 2)}
|
|
967
|
-
`
|
|
968
|
-
};
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
// tools/install-runtime.ts
|
|
972
|
-
import { join as join2, relative, resolve, sep } from "node:path";
|
|
973
|
-
var RUNTIME_PAYLOAD = [
|
|
974
|
-
"bin",
|
|
975
|
-
"capabilities",
|
|
976
|
-
"dist",
|
|
977
|
-
"docs",
|
|
978
|
-
"skills",
|
|
979
|
-
"src",
|
|
980
|
-
"tools",
|
|
981
|
-
"config.example.json",
|
|
982
|
-
"package.json"
|
|
983
|
-
];
|
|
984
|
-
var OPERATOR_OWNED = ["config.json", "state", "flags"];
|
|
985
|
-
var NOT_SHIPPED = [join2("tools", "dev"), join2("tools", "__test__")];
|
|
986
|
-
if (false) {}
|
|
987
|
-
|
|
988
|
-
// tools/uninstall-runtime.ts
|
|
41
|
+
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
989
42
|
function uninstallTargets(env = process.env) {
|
|
990
|
-
const userHome =
|
|
991
|
-
const binDir = env.TLC_BIN_DIR?.trim() ||
|
|
43
|
+
const userHome = homedir();
|
|
44
|
+
const binDir = env.TLC_BIN_DIR?.trim() || join(userHome, ".local", "bin");
|
|
992
45
|
return {
|
|
993
46
|
home: runtimeHome(env),
|
|
994
|
-
binLinks: [
|
|
995
|
-
claudeSettings:
|
|
996
|
-
cursorHooks:
|
|
47
|
+
binLinks: [join(binDir, "tlc"), join(binDir, "tlc.cmd")],
|
|
48
|
+
claudeSettings: join(claudeConfigDir(), "settings.json"),
|
|
49
|
+
cursorHooks: join(cursorConfigDir(), "hooks.json"),
|
|
997
50
|
skillLinks: [
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
51
|
+
join(claudeConfigDir(), "skills", "harness-init"),
|
|
52
|
+
join(cursorConfigDir(), "skills", "harness-init"),
|
|
53
|
+
join(userHome, ".tlc", "skills", "harness-init")
|
|
1001
54
|
]
|
|
1002
55
|
};
|
|
1003
56
|
}
|
|
@@ -1009,15 +62,15 @@ function isSymlink(path) {
|
|
|
1009
62
|
}
|
|
1010
63
|
}
|
|
1011
64
|
function canonicalise(path) {
|
|
1012
|
-
let head =
|
|
65
|
+
let head = resolve(path);
|
|
1013
66
|
const tail = [];
|
|
1014
67
|
for (;; ) {
|
|
1015
68
|
try {
|
|
1016
|
-
return
|
|
69
|
+
return join(realpathSync(head), ...tail);
|
|
1017
70
|
} catch {
|
|
1018
71
|
const parent = dirname(head);
|
|
1019
72
|
if (parent === head) {
|
|
1020
|
-
return
|
|
73
|
+
return resolve(path);
|
|
1021
74
|
}
|
|
1022
75
|
tail.unshift(basename(head));
|
|
1023
76
|
head = parent;
|
|
@@ -1026,17 +79,17 @@ function canonicalise(path) {
|
|
|
1026
79
|
}
|
|
1027
80
|
function resolveLink(path) {
|
|
1028
81
|
try {
|
|
1029
|
-
return
|
|
82
|
+
return realpathSync(path);
|
|
1030
83
|
} catch {
|
|
1031
84
|
try {
|
|
1032
85
|
const target = readlinkSync(path);
|
|
1033
|
-
return canonicalise(isAbsolute(target) ? target :
|
|
86
|
+
return canonicalise(isAbsolute(target) ? target : resolve(dirname(path), target));
|
|
1034
87
|
} catch {
|
|
1035
88
|
return canonicalise(path);
|
|
1036
89
|
}
|
|
1037
90
|
}
|
|
1038
91
|
}
|
|
1039
|
-
function isInsideRoot(target, root, pathApi = { relative
|
|
92
|
+
function isInsideRoot(target, root, pathApi = { relative, isAbsolute }) {
|
|
1040
93
|
if (target === root) {
|
|
1041
94
|
return true;
|
|
1042
95
|
}
|
|
@@ -1046,16 +99,16 @@ function isInsideRoot(target, root, pathApi = { relative: relative2, isAbsolute
|
|
|
1046
99
|
function pointsInto(link, home) {
|
|
1047
100
|
return isInsideRoot(resolveLink(link), canonicalise(home));
|
|
1048
101
|
}
|
|
1049
|
-
var
|
|
102
|
+
var LAUNCHER_MARKER = "tlc-exec.mjs";
|
|
1050
103
|
function carriesLauncherMarker(path) {
|
|
1051
104
|
try {
|
|
1052
|
-
return statSync(path).size < 4096 &&
|
|
105
|
+
return statSync(path).size < 4096 && readFileSync(path, "utf8").includes(LAUNCHER_MARKER);
|
|
1053
106
|
} catch {
|
|
1054
107
|
return false;
|
|
1055
108
|
}
|
|
1056
109
|
}
|
|
1057
110
|
function planLink(items, path, home, label, ownership) {
|
|
1058
|
-
if (!
|
|
111
|
+
if (!existsSync(path) && !isSymlink(path)) {
|
|
1059
112
|
return;
|
|
1060
113
|
}
|
|
1061
114
|
if (!isSymlink(path)) {
|
|
@@ -1082,10 +135,10 @@ function planLink(items, path, home, label, ownership) {
|
|
|
1082
135
|
});
|
|
1083
136
|
}
|
|
1084
137
|
function planClaude(items, settingsPath) {
|
|
1085
|
-
if (!
|
|
138
|
+
if (!existsSync(settingsPath)) {
|
|
1086
139
|
return;
|
|
1087
140
|
}
|
|
1088
|
-
const result = unmergeClaudeSettings(
|
|
141
|
+
const result = unmergeClaudeSettings(readFileSync(settingsPath, "utf8"));
|
|
1089
142
|
if (!result.ok) {
|
|
1090
143
|
items.push({
|
|
1091
144
|
action: "keep",
|
|
@@ -1104,7 +157,7 @@ function planClaude(items, settingsPath) {
|
|
|
1104
157
|
});
|
|
1105
158
|
}
|
|
1106
159
|
function planCursor(items, hooksPath) {
|
|
1107
|
-
const text =
|
|
160
|
+
const text = existsSync(hooksPath) ? readFileSync(hooksPath, "utf8") : null;
|
|
1108
161
|
const result = unwireCursorHooks(text);
|
|
1109
162
|
switch (result.kind) {
|
|
1110
163
|
case "absent":
|
|
@@ -1135,22 +188,22 @@ function planRuntime(items, home, purge) {
|
|
|
1135
188
|
});
|
|
1136
189
|
return true;
|
|
1137
190
|
}
|
|
1138
|
-
if (!
|
|
191
|
+
if (!existsSync(home)) {
|
|
1139
192
|
return false;
|
|
1140
193
|
}
|
|
1141
194
|
for (const entry of RUNTIME_PAYLOAD) {
|
|
1142
|
-
const path =
|
|
1143
|
-
if (
|
|
195
|
+
const path = join(home, entry);
|
|
196
|
+
if (existsSync(path)) {
|
|
1144
197
|
items.push({ action: "remove", target: path, detail: "runtime payload" });
|
|
1145
198
|
}
|
|
1146
199
|
}
|
|
1147
|
-
const marker =
|
|
1148
|
-
if (
|
|
200
|
+
const marker = join(home, NPM_MARKER);
|
|
201
|
+
if (existsSync(marker)) {
|
|
1149
202
|
items.push({ action: "remove", target: marker, detail: "install marker" });
|
|
1150
203
|
}
|
|
1151
204
|
for (const entry of OPERATOR_OWNED) {
|
|
1152
|
-
const path =
|
|
1153
|
-
if (!
|
|
205
|
+
const path = join(home, entry);
|
|
206
|
+
if (!existsSync(path)) {
|
|
1154
207
|
continue;
|
|
1155
208
|
}
|
|
1156
209
|
items.push(purge ? { action: "remove", target: path, detail: "--purge" } : { action: "keep", target: path, detail: "yours — add --purge to remove it" });
|
|
@@ -1158,7 +211,7 @@ function planRuntime(items, home, purge) {
|
|
|
1158
211
|
return false;
|
|
1159
212
|
}
|
|
1160
213
|
function planManual(items, home) {
|
|
1161
|
-
if (
|
|
214
|
+
if (existsSync(join(home, NPM_MARKER))) {
|
|
1162
215
|
items.push({
|
|
1163
216
|
action: "manual",
|
|
1164
217
|
target: `npm uninstall -g ${NPM_PACKAGE}`,
|
|
@@ -1197,9 +250,9 @@ function applyUninstall(plan, targets) {
|
|
|
1197
250
|
if (item.action === "unmerge" && item.target === targets.claudeSettings) {
|
|
1198
251
|
removeClaudeWiring(item.target);
|
|
1199
252
|
} else if (item.action === "unmerge") {
|
|
1200
|
-
const result = unwireCursorHooks(
|
|
253
|
+
const result = unwireCursorHooks(readFileSync(item.target, "utf8"));
|
|
1201
254
|
if (result.kind === "rewritten") {
|
|
1202
|
-
|
|
255
|
+
writeFileSync(item.target, result.text, "utf8");
|
|
1203
256
|
}
|
|
1204
257
|
} else if (item.action === "unlink") {
|
|
1205
258
|
unlinkSync(item.target);
|