tldr-experts 0.3.0 → 0.4.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/CHANGELOG.md +1957 -0
- package/README.md +99 -12
- package/dist/hooks/answer-capture.js +21 -12
- package/dist/hooks/budget-gate.js +95 -11
- package/dist/hooks/{chunk-0bt6yb2q.js → chunk-39zh2e44.js} +10 -1
- package/dist/hooks/chunk-4cp363kv.js +1766 -0
- package/dist/hooks/{chunk-t8tdv11p.js → chunk-7y2dq0pj.js} +1 -1
- package/dist/hooks/chunk-9zsqxr6y.js +213 -0
- package/dist/hooks/{chunk-a8p2rc94.js → chunk-b8kxzna2.js} +1 -1
- package/dist/hooks/{chunk-j234zf0t.js → chunk-c6t5nx0r.js} +37 -166
- package/dist/hooks/{chunk-g395gk7e.js → chunk-m3mewgnw.js} +36 -17
- package/dist/hooks/chunk-phmdk72a.js +164 -0
- package/dist/hooks/chunk-rpcxsqh3.js +199 -0
- package/dist/hooks/{chunk-azctppjh.js → chunk-rz541e2b.js} +7 -1
- package/dist/hooks/{chunk-y0jdr3et.js → chunk-s1c5h7yx.js} +71 -29
- package/dist/hooks/{chunk-p274ckxv.js → chunk-sq44k6g2.js} +155 -12
- package/dist/hooks/{chunk-x98qs959.js → chunk-t1ywrfr4.js} +35 -42
- package/dist/hooks/{chunk-1zwcxd3f.js → chunk-tzzwddct.js} +1 -1
- package/dist/hooks/claim-sources.js +31 -23
- package/dist/hooks/dod-gate.js +12 -37
- package/dist/hooks/no-reask.js +9 -9
- package/dist/hooks/session-start.js +176 -422
- package/dist/hooks/statusline.js +14 -11
- package/dist/tldrx.js +22798 -12309
- package/package.json +3 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/skills/tldrx/SKILL.md +16 -3
- package/stages/build/stage.md +5 -0
- package/stages/build/stage.yml +2 -1
- package/stages/plan/stage.md +11 -0
- package/templates/budget.yml +5 -0
- package/templates/epic.md +5 -3
- package/dist/hooks/chunk-ae6bkfs5.js +0 -0
- package/dist/hooks/chunk-kw4tffzf.js +0 -139
- package/dist/hooks/chunk-sdjnnmzz.js +0 -497
- package/dist/hooks/chunk-t56k6146.js +0 -14
|
@@ -7284,6 +7284,93 @@ var runtime = onBun ? bunRuntime : nodeRuntime;
|
|
|
7284
7284
|
function parseYaml(text) {
|
|
7285
7285
|
return runtime.parseYaml(text);
|
|
7286
7286
|
}
|
|
7287
|
+
function parseYamlRepairing(text) {
|
|
7288
|
+
try {
|
|
7289
|
+
return { doc: parseYaml(text), repaired: false };
|
|
7290
|
+
} catch (original) {
|
|
7291
|
+
const mended = rejoinBrokenQuotedScalars(text);
|
|
7292
|
+
if (mended === null)
|
|
7293
|
+
throw original;
|
|
7294
|
+
try {
|
|
7295
|
+
return { doc: parseYaml(mended), repaired: true };
|
|
7296
|
+
} catch {
|
|
7297
|
+
throw original;
|
|
7298
|
+
}
|
|
7299
|
+
}
|
|
7300
|
+
}
|
|
7301
|
+
function rejoinBrokenQuotedScalars(text) {
|
|
7302
|
+
const out = [];
|
|
7303
|
+
let changed = false;
|
|
7304
|
+
let inDouble = false;
|
|
7305
|
+
let inSingle = false;
|
|
7306
|
+
for (let i = 0;i < text.length; i++) {
|
|
7307
|
+
const ch = text[i];
|
|
7308
|
+
if (inDouble) {
|
|
7309
|
+
if (ch === "\\") {
|
|
7310
|
+
out.push(ch, text[i + 1] ?? "");
|
|
7311
|
+
i++;
|
|
7312
|
+
continue;
|
|
7313
|
+
}
|
|
7314
|
+
if (ch === '"') {
|
|
7315
|
+
inDouble = false;
|
|
7316
|
+
out.push(ch);
|
|
7317
|
+
continue;
|
|
7318
|
+
}
|
|
7319
|
+
const escaped = CONTROL_ESCAPES[ch];
|
|
7320
|
+
if (escaped !== undefined) {
|
|
7321
|
+
out.push(escaped);
|
|
7322
|
+
changed = true;
|
|
7323
|
+
continue;
|
|
7324
|
+
}
|
|
7325
|
+
out.push(ch);
|
|
7326
|
+
continue;
|
|
7327
|
+
}
|
|
7328
|
+
if (inSingle) {
|
|
7329
|
+
if (ch === "'") {
|
|
7330
|
+
if (text[i + 1] === "'") {
|
|
7331
|
+
out.push(ch, ch);
|
|
7332
|
+
i++;
|
|
7333
|
+
} else {
|
|
7334
|
+
inSingle = false;
|
|
7335
|
+
out.push(ch);
|
|
7336
|
+
}
|
|
7337
|
+
continue;
|
|
7338
|
+
}
|
|
7339
|
+
out.push(ch);
|
|
7340
|
+
continue;
|
|
7341
|
+
}
|
|
7342
|
+
if (ch === '"')
|
|
7343
|
+
inDouble = true;
|
|
7344
|
+
else if (ch === "'")
|
|
7345
|
+
inSingle = true;
|
|
7346
|
+
else if (ch === "#" && (i === 0 || text[i - 1] === " " || text[i - 1] === `
|
|
7347
|
+
`)) {
|
|
7348
|
+
const end = text.indexOf(`
|
|
7349
|
+
`, i);
|
|
7350
|
+
const stop = end === -1 ? text.length : end;
|
|
7351
|
+
out.push(text.slice(i, stop));
|
|
7352
|
+
i = stop - 1;
|
|
7353
|
+
continue;
|
|
7354
|
+
}
|
|
7355
|
+
out.push(ch);
|
|
7356
|
+
}
|
|
7357
|
+
if (inDouble)
|
|
7358
|
+
return null;
|
|
7359
|
+
return changed ? out.join("") : null;
|
|
7360
|
+
}
|
|
7361
|
+
var CONTROL_ESCAPES = {
|
|
7362
|
+
"\n": "\\n",
|
|
7363
|
+
"\r": "\\r",
|
|
7364
|
+
"\v": "\\v",
|
|
7365
|
+
"\f": "\\f",
|
|
7366
|
+
"\x00": "\\0",
|
|
7367
|
+
"\x07": "\\a",
|
|
7368
|
+
"\b": "\\b",
|
|
7369
|
+
"\x1B": "\\e",
|
|
7370
|
+
"
": "\\N",
|
|
7371
|
+
"\u2028": "\\L",
|
|
7372
|
+
"\u2029": "\\P"
|
|
7373
|
+
};
|
|
7287
7374
|
|
|
7288
7375
|
// src/core/paths.ts
|
|
7289
7376
|
import { dirname as dirname2, join } from "node:path";
|
|
@@ -7313,10 +7400,15 @@ var TEMPLATES_DIR = join(FRAMEWORK_ROOT, "templates");
|
|
|
7313
7400
|
var PLUGIN_DIR = join(FRAMEWORK_ROOT, "plugin");
|
|
7314
7401
|
var PROJECT_FRAMEWORK_DIR = ".tldrx";
|
|
7315
7402
|
var PROJECT_WORK_DIR = "tldrx-work";
|
|
7403
|
+
var PROJECT_WORKTREES_DIR = "worktrees";
|
|
7404
|
+
var EPIC_WORKTREE_PREFIX = "_epic-";
|
|
7405
|
+
function isEpicWorktreeOf(name, runId) {
|
|
7406
|
+
return name.startsWith(`${EPIC_WORKTREE_PREFIX}${runId}-`);
|
|
7407
|
+
}
|
|
7316
7408
|
|
|
7317
7409
|
// src/hooks/lib/workspace.ts
|
|
7318
7410
|
import { existsSync as existsSync2, readdirSync, readFileSync, statSync as statSync2 } from "node:fs";
|
|
7319
|
-
import { dirname as dirname3, isAbsolute, join as join2, resolve, sep } from "node:path";
|
|
7411
|
+
import { basename, dirname as dirname3, isAbsolute, join as join2, resolve, sep } from "node:path";
|
|
7320
7412
|
function locateWork(filePath) {
|
|
7321
7413
|
if (filePath === "")
|
|
7322
7414
|
return null;
|
|
@@ -7348,10 +7440,32 @@ function findWorkspaceRoot(start) {
|
|
|
7348
7440
|
return null;
|
|
7349
7441
|
}
|
|
7350
7442
|
var FALLBACK_DEFAULT_BRANCH = "main";
|
|
7443
|
+
function commandRolesOf(doc) {
|
|
7444
|
+
const out = new Map;
|
|
7445
|
+
const list = doc?.repos;
|
|
7446
|
+
if (!Array.isArray(list))
|
|
7447
|
+
return out;
|
|
7448
|
+
for (const entry of list) {
|
|
7449
|
+
if (typeof entry?.name !== "string")
|
|
7450
|
+
continue;
|
|
7451
|
+
const roles = new Map;
|
|
7452
|
+
const cmds = entry.commands;
|
|
7453
|
+
if (cmds !== null && typeof cmds === "object") {
|
|
7454
|
+
for (const [role, value] of Object.entries(cmds)) {
|
|
7455
|
+
if (typeof value !== "string" || value.trim() === "")
|
|
7456
|
+
continue;
|
|
7457
|
+
roles.set(role, value);
|
|
7458
|
+
}
|
|
7459
|
+
}
|
|
7460
|
+
out.set(entry.name, roles);
|
|
7461
|
+
}
|
|
7462
|
+
return out;
|
|
7463
|
+
}
|
|
7351
7464
|
function loadWorkspace(root) {
|
|
7352
7465
|
const repos = new Map;
|
|
7353
7466
|
const commands = new Set;
|
|
7354
7467
|
const repoCommands = new Map;
|
|
7468
|
+
const commandRoles = new Map;
|
|
7355
7469
|
const defaultBranches = new Map;
|
|
7356
7470
|
let seedTriageThresholdTokens = null;
|
|
7357
7471
|
const empty = () => ({
|
|
@@ -7359,6 +7473,7 @@ function loadWorkspace(root) {
|
|
|
7359
7473
|
repos,
|
|
7360
7474
|
commands,
|
|
7361
7475
|
repoCommands,
|
|
7476
|
+
commandRoles,
|
|
7362
7477
|
defaultBranches,
|
|
7363
7478
|
seedTriageThresholdTokens
|
|
7364
7479
|
});
|
|
@@ -7381,23 +7496,21 @@ function loadWorkspace(root) {
|
|
|
7381
7496
|
const list = doc?.repos;
|
|
7382
7497
|
if (!Array.isArray(list))
|
|
7383
7498
|
return empty();
|
|
7499
|
+
const declared = commandRolesOf(doc);
|
|
7384
7500
|
for (const entry of list) {
|
|
7385
7501
|
if (typeof entry?.name !== "string")
|
|
7386
7502
|
continue;
|
|
7387
7503
|
repos.set(entry.name, typeof entry.path === "string" ? entry.path : ".");
|
|
7388
7504
|
defaultBranches.set(entry.name, typeof entry.default_branch === "string" && entry.default_branch !== "" ? entry.default_branch : FALLBACK_DEFAULT_BRANCH);
|
|
7389
7505
|
const own = [];
|
|
7390
|
-
const
|
|
7391
|
-
|
|
7392
|
-
|
|
7393
|
-
|
|
7394
|
-
|
|
7395
|
-
commands.add(value);
|
|
7396
|
-
if (!own.includes(value))
|
|
7397
|
-
own.push(value);
|
|
7398
|
-
}
|
|
7506
|
+
const roles = declared.get(entry.name) ?? new Map;
|
|
7507
|
+
for (const value of roles.values()) {
|
|
7508
|
+
commands.add(value);
|
|
7509
|
+
if (!own.includes(value))
|
|
7510
|
+
own.push(value);
|
|
7399
7511
|
}
|
|
7400
7512
|
repoCommands.set(entry.name, own);
|
|
7513
|
+
commandRoles.set(entry.name, roles);
|
|
7401
7514
|
}
|
|
7402
7515
|
return empty();
|
|
7403
7516
|
}
|
|
@@ -7406,9 +7519,39 @@ function toSrcContext(workspace, runDir) {
|
|
|
7406
7519
|
root: workspace.root,
|
|
7407
7520
|
repos: workspace.repos,
|
|
7408
7521
|
commands: workspace.commands,
|
|
7409
|
-
runDir: runDir ?? null
|
|
7522
|
+
runDir: runDir ?? null,
|
|
7523
|
+
epicWorktrees: epicWorktreesOf(workspace, runDir ?? null)
|
|
7410
7524
|
};
|
|
7411
7525
|
}
|
|
7526
|
+
function epicWorktreesOf(workspace, runDir) {
|
|
7527
|
+
if (runDir === null || runDir === "")
|
|
7528
|
+
return [];
|
|
7529
|
+
const runId = basename(runDir);
|
|
7530
|
+
if (runId === "")
|
|
7531
|
+
return [];
|
|
7532
|
+
const trees = [];
|
|
7533
|
+
for (const repo of workspace.repos.keys()) {
|
|
7534
|
+
const dir = join2(workspace.root, PROJECT_FRAMEWORK_DIR, PROJECT_WORKTREES_DIR, repo);
|
|
7535
|
+
if (!existsSync2(dir))
|
|
7536
|
+
continue;
|
|
7537
|
+
let entries;
|
|
7538
|
+
try {
|
|
7539
|
+
entries = readdirSync(dir);
|
|
7540
|
+
} catch {
|
|
7541
|
+
continue;
|
|
7542
|
+
}
|
|
7543
|
+
for (const name of entries.slice().sort()) {
|
|
7544
|
+
if (!isEpicWorktreeOf(name, runId))
|
|
7545
|
+
continue;
|
|
7546
|
+
const abs = join2(dir, name);
|
|
7547
|
+
try {
|
|
7548
|
+
if (statSync2(abs).isDirectory())
|
|
7549
|
+
trees.push({ repo, dir: abs });
|
|
7550
|
+
} catch {}
|
|
7551
|
+
}
|
|
7552
|
+
}
|
|
7553
|
+
return trees;
|
|
7554
|
+
}
|
|
7412
7555
|
function repoPath(workspace, name) {
|
|
7413
7556
|
const rel = workspace.repos.get(name);
|
|
7414
7557
|
return rel === undefined ? null : join2(workspace.root, rel);
|
|
@@ -7432,4 +7575,4 @@ function listRunDirs(root) {
|
|
|
7432
7575
|
return dirs.sort().reverse();
|
|
7433
7576
|
}
|
|
7434
7577
|
|
|
7435
|
-
export { runtime, parseYaml, STAGES_DIR, TEMPLATES_DIR, PROJECT_FRAMEWORK_DIR, PROJECT_WORK_DIR, locateWork, findWorkspaceRoot, loadWorkspace, toSrcContext, repoPath, factsPath, stageYamlPath, listRunDirs };
|
|
7578
|
+
export { runtime, parseYaml, parseYamlRepairing, STAGES_DIR, TEMPLATES_DIR, PROJECT_FRAMEWORK_DIR, PROJECT_WORK_DIR, locateWork, findWorkspaceRoot, loadWorkspace, toSrcContext, repoPath, factsPath, stageYamlPath, listRunDirs };
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
2
|
emitFactsYaml,
|
|
3
3
|
withWorkspaceLock,
|
|
4
|
-
workspaceRootOfFactsPath
|
|
5
|
-
|
|
4
|
+
workspaceRootOfFactsPath,
|
|
5
|
+
writeAtomic
|
|
6
|
+
} from "./chunk-c6t5nx0r.js";
|
|
6
7
|
import {
|
|
8
|
+
FACT_CONFIDENCES,
|
|
9
|
+
FACT_KINDS,
|
|
10
|
+
MAX_FACTS,
|
|
11
|
+
MAX_FACT_CHARS,
|
|
12
|
+
factNumber,
|
|
13
|
+
formatFactId,
|
|
14
|
+
isLive,
|
|
15
|
+
isRetired,
|
|
7
16
|
noteDeprecations
|
|
8
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-rpcxsqh3.js";
|
|
9
18
|
import {
|
|
10
19
|
asDocument,
|
|
11
20
|
isRecord,
|
|
@@ -15,29 +24,13 @@ import {
|
|
|
15
24
|
requireString,
|
|
16
25
|
requireVersion,
|
|
17
26
|
result
|
|
18
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-39zh2e44.js";
|
|
19
28
|
import {
|
|
20
29
|
parseYaml
|
|
21
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-sq44k6g2.js";
|
|
22
31
|
|
|
23
32
|
// src/core/facts/FactsStore.ts
|
|
24
|
-
import { existsSync,
|
|
25
|
-
import { dirname } from "node:path";
|
|
26
|
-
|
|
27
|
-
// src/core/facts/Fact.ts
|
|
28
|
-
var FACT_KINDS = ["answer", "observed", "derived"];
|
|
29
|
-
var FACT_CONFIDENCES = ["measured", "inferred", "stated"];
|
|
30
|
-
var MAX_FACTS = 5000;
|
|
31
|
-
var MAX_FACT_CHARS = 300;
|
|
32
|
-
function isRetired(fact) {
|
|
33
|
-
return fact.retired !== null && fact.retired.at !== null;
|
|
34
|
-
}
|
|
35
|
-
function factNumber(id) {
|
|
36
|
-
return Number.parseInt(id.slice(1), 10);
|
|
37
|
-
}
|
|
38
|
-
function formatFactId(n) {
|
|
39
|
-
return `F${String(n).padStart(3, "0")}`;
|
|
40
|
-
}
|
|
33
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
41
34
|
|
|
42
35
|
// src/core/facts/validateFactsFile.ts
|
|
43
36
|
var ID_RE = /^F\d{3,6}$/;
|
|
@@ -94,6 +87,9 @@ function validateFactsFile(input) {
|
|
|
94
87
|
} else if (row.source !== undefined) {
|
|
95
88
|
issues.push({ path: `${path}.source`, message: "expected a mapping" });
|
|
96
89
|
}
|
|
90
|
+
if (row.truncated !== undefined && typeof row.truncated !== "boolean") {
|
|
91
|
+
issues.push({ path: `${path}.truncated`, message: "expected true, false or absent" });
|
|
92
|
+
}
|
|
97
93
|
const superseded = typeof row.superseded_by === "string";
|
|
98
94
|
const retired = isRecord(row.retired) && row.retired.at !== null && row.retired.at !== undefined;
|
|
99
95
|
if (superseded && retired) {
|
|
@@ -158,7 +154,7 @@ function findDuplicate(question, area, facts, threshold = DEFAULT_JACCARD_THRESH
|
|
|
158
154
|
for (const fact of facts) {
|
|
159
155
|
if (fact.area !== area)
|
|
160
156
|
continue;
|
|
161
|
-
if (
|
|
157
|
+
if (!isLive(fact))
|
|
162
158
|
continue;
|
|
163
159
|
const score = jaccard(asked, tokenize(fact.fact));
|
|
164
160
|
if (score < threshold)
|
|
@@ -204,7 +200,7 @@ class FactsStore {
|
|
|
204
200
|
return this.rows;
|
|
205
201
|
}
|
|
206
202
|
get active() {
|
|
207
|
-
return this.rows.filter(
|
|
203
|
+
return this.rows.filter(isLive);
|
|
208
204
|
}
|
|
209
205
|
get(id) {
|
|
210
206
|
return this.rows.find((f) => f.id === id);
|
|
@@ -214,9 +210,10 @@ class FactsStore {
|
|
|
214
210
|
return formatFactId(highest + 1);
|
|
215
211
|
}
|
|
216
212
|
append(input) {
|
|
213
|
+
const cut = input.fact.length > MAX_FACT_CHARS;
|
|
217
214
|
const fact = {
|
|
218
215
|
id: this.nextId(),
|
|
219
|
-
fact:
|
|
216
|
+
fact: cut ? `${input.fact.slice(0, MAX_FACT_CHARS - 1)}…` : input.fact,
|
|
220
217
|
area: input.area,
|
|
221
218
|
repos: [...input.repos],
|
|
222
219
|
kind: input.kind,
|
|
@@ -224,11 +221,21 @@ class FactsStore {
|
|
|
224
221
|
source: { ...input.source },
|
|
225
222
|
supersedes: input.supersedes ?? null,
|
|
226
223
|
superseded_by: null,
|
|
227
|
-
retired: input.retired ?? null
|
|
224
|
+
retired: input.retired ?? null,
|
|
225
|
+
...cut || input.truncated === true ? { truncated: true } : {}
|
|
228
226
|
};
|
|
229
227
|
this.rows.push(fact);
|
|
230
228
|
return fact;
|
|
231
229
|
}
|
|
230
|
+
headOf(id) {
|
|
231
|
+
let fact = this.get(id);
|
|
232
|
+
for (let step = 0;fact !== undefined && fact.superseded_by !== null; step++) {
|
|
233
|
+
if (step >= this.rows.length)
|
|
234
|
+
return;
|
|
235
|
+
fact = this.get(fact.superseded_by);
|
|
236
|
+
}
|
|
237
|
+
return fact;
|
|
238
|
+
}
|
|
232
239
|
supersede(oldId, input) {
|
|
233
240
|
const index = this.rows.findIndex((f) => f.id === oldId);
|
|
234
241
|
if (index === -1)
|
|
@@ -272,7 +279,7 @@ class FactsStore {
|
|
|
272
279
|
throw new Error(`refusing to write an invalid facts.yml: ${first?.path ?? ""} ${first?.message ?? ""}`);
|
|
273
280
|
}
|
|
274
281
|
withWorkspaceLock(workspaceRootOfFactsPath(path), () => {
|
|
275
|
-
|
|
282
|
+
writeAtomic(path, text);
|
|
276
283
|
});
|
|
277
284
|
}
|
|
278
285
|
static update(path, fn) {
|
|
@@ -284,19 +291,5 @@ class FactsStore {
|
|
|
284
291
|
});
|
|
285
292
|
}
|
|
286
293
|
}
|
|
287
|
-
function writeFactsAtomic(path, text) {
|
|
288
|
-
const temp = `${path}.tmp-${String(process.pid)}`;
|
|
289
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
290
|
-
try {
|
|
291
|
-
writeFileSync(temp, text, "utf8");
|
|
292
|
-
renameSync(temp, path);
|
|
293
|
-
} catch (error) {
|
|
294
|
-
try {
|
|
295
|
-
if (existsSync(temp))
|
|
296
|
-
rmSync(temp, { force: true });
|
|
297
|
-
} catch {}
|
|
298
|
-
throw error;
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
294
|
|
|
302
|
-
export {
|
|
295
|
+
export { FactsStore };
|
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
wouldBeContent
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-7y2dq0pj.js";
|
|
5
5
|
import {
|
|
6
6
|
claimSourcesDeny,
|
|
7
7
|
claimSourcesEmptySectionDeny,
|
|
8
8
|
claimSourcesMalformedDeny,
|
|
9
9
|
claimSourcesUnresolvedDeny
|
|
10
10
|
} from "./chunk-9gb21660.js";
|
|
11
|
-
import {
|
|
12
|
-
isHandoff,
|
|
13
|
-
validateHandoff
|
|
14
|
-
} from "./chunk-kw4tffzf.js";
|
|
15
11
|
import {
|
|
16
12
|
allow,
|
|
17
13
|
deny,
|
|
@@ -20,14 +16,19 @@ import {
|
|
|
20
16
|
postContext,
|
|
21
17
|
readPayload,
|
|
22
18
|
runHook
|
|
23
|
-
} from "./chunk-
|
|
24
|
-
import"./chunk-
|
|
25
|
-
import
|
|
19
|
+
} from "./chunk-tzzwddct.js";
|
|
20
|
+
import"./chunk-b8kxzna2.js";
|
|
21
|
+
import {
|
|
22
|
+
isHandoff,
|
|
23
|
+
validateCitations,
|
|
24
|
+
validateHandoff
|
|
25
|
+
} from "./chunk-9zsqxr6y.js";
|
|
26
|
+
import"./chunk-m3mewgnw.js";
|
|
26
27
|
import {
|
|
27
28
|
loadWorkspace,
|
|
28
29
|
locateWork,
|
|
29
30
|
toSrcContext
|
|
30
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-sq44k6g2.js";
|
|
31
32
|
|
|
32
33
|
// src/hooks/claim-sources.ts
|
|
33
34
|
await runHook("claim-sources", async () => {
|
|
@@ -43,24 +44,31 @@ await runHook("claim-sources", async () => {
|
|
|
43
44
|
const wouldBe = wouldBeContent(payload, filePath);
|
|
44
45
|
if (wouldBe.kind !== "content")
|
|
45
46
|
return;
|
|
46
|
-
const looksLikeHandoff = filePath.endsWith("handoff.md") || isHandoff(wouldBe.text);
|
|
47
|
-
if (!looksLikeHandoff)
|
|
48
|
-
return;
|
|
49
47
|
const workspace = loadWorkspace(location.root);
|
|
50
|
-
const
|
|
51
|
-
if (report.ok)
|
|
52
|
-
return;
|
|
48
|
+
const srcCtx = toSrcContext(workspace, location.runDir);
|
|
53
49
|
const relPath = `tldrx-work/${location.run}/${location.relative}`;
|
|
54
50
|
const parts = [];
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
51
|
+
const looksLikeHandoff = filePath.endsWith("handoff.md") || isHandoff(wouldBe.text);
|
|
52
|
+
if (looksLikeHandoff) {
|
|
53
|
+
const report = validateHandoff(wouldBe.text, srcCtx);
|
|
54
|
+
if (report.ok)
|
|
55
|
+
return;
|
|
56
|
+
if (report.unsourced.length > 0)
|
|
57
|
+
parts.push(claimSourcesDeny(relPath, report.unsourced));
|
|
58
|
+
if (report.malformed.length > 0)
|
|
59
|
+
parts.push(claimSourcesMalformedDeny(relPath, report.malformed));
|
|
60
|
+
if (report.emptySections.length > 0) {
|
|
61
|
+
parts.push(claimSourcesEmptySectionDeny(relPath, [...report.emptySections]));
|
|
62
|
+
}
|
|
63
|
+
if (report.unresolved.length > 0)
|
|
64
|
+
parts.push(claimSourcesUnresolvedDeny(relPath, report.unresolved));
|
|
65
|
+
} else {
|
|
66
|
+
const report = validateCitations(wouldBe.text, srcCtx);
|
|
67
|
+
if (report.malformed.length > 0)
|
|
68
|
+
parts.push(claimSourcesMalformedDeny(relPath, report.malformed));
|
|
69
|
+
if (report.unresolved.length > 0)
|
|
70
|
+
parts.push(claimSourcesUnresolvedDeny(relPath, report.unresolved));
|
|
61
71
|
}
|
|
62
|
-
if (report.unresolved.length > 0)
|
|
63
|
-
parts.push(claimSourcesUnresolvedDeny(relPath, report.unresolved));
|
|
64
72
|
if (parts.length === 0)
|
|
65
73
|
return;
|
|
66
74
|
const message = parts.join(`
|
package/dist/hooks/dod-gate.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
wouldBeContent
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-7y2dq0pj.js";
|
|
5
5
|
import {
|
|
6
6
|
dodGateDeny,
|
|
7
7
|
dodGateInternalErrorDeny,
|
|
@@ -15,54 +15,29 @@ import {
|
|
|
15
15
|
filePathOf,
|
|
16
16
|
isWriteOrEdit,
|
|
17
17
|
readPayload
|
|
18
|
-
} from "./chunk-
|
|
19
|
-
import"./chunk-
|
|
20
|
-
import
|
|
21
|
-
|
|
18
|
+
} from "./chunk-tzzwddct.js";
|
|
19
|
+
import"./chunk-b8kxzna2.js";
|
|
20
|
+
import {
|
|
21
|
+
parseDodBlock
|
|
22
|
+
} from "./chunk-phmdk72a.js";
|
|
23
|
+
import"./chunk-39zh2e44.js";
|
|
22
24
|
import {
|
|
23
25
|
loadWorkspace,
|
|
24
26
|
locateWork,
|
|
25
27
|
repoPath,
|
|
26
28
|
runtime
|
|
27
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-sq44k6g2.js";
|
|
28
30
|
|
|
29
31
|
// src/hooks/dod-gate.ts
|
|
30
32
|
import { basename, join } from "node:path";
|
|
31
33
|
import { existsSync } from "node:fs";
|
|
32
34
|
|
|
33
|
-
// src/core/schemas/story.ts
|
|
34
|
-
var FENCE_OPEN_RE = /^\s*```+\s*dod\s*$/i;
|
|
35
|
-
var FENCE_CLOSE_RE = /^\s*```+\s*$/;
|
|
36
|
-
function parseDodBlock(text) {
|
|
37
|
-
const commands = [];
|
|
38
|
-
let present = false;
|
|
39
|
-
let inside = false;
|
|
40
|
-
for (const line of text.split(`
|
|
41
|
-
`)) {
|
|
42
|
-
if (inside) {
|
|
43
|
-
if (FENCE_CLOSE_RE.test(line)) {
|
|
44
|
-
inside = false;
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
const command = line.trim();
|
|
48
|
-
if (command !== "" && !command.startsWith("#"))
|
|
49
|
-
commands.push(command);
|
|
50
|
-
continue;
|
|
51
|
-
}
|
|
52
|
-
if (FENCE_OPEN_RE.test(line)) {
|
|
53
|
-
present = true;
|
|
54
|
-
inside = true;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return { present, commands };
|
|
58
|
-
}
|
|
59
|
-
|
|
60
35
|
// src/hooks/lib/story.ts
|
|
61
36
|
var DONE_RE = /^\s*(?:[-*]\s*)?(?:\*\*)?status(?:\*\*)?\s*:\s*["'`]?done["'`]?\.?\s*$/i;
|
|
62
37
|
var REPO_RE = /^\s*(?:[-*]\s*)?(?:\*\*)?repo(?:\*\*)?\s*:\s*["'`]?([A-Za-z0-9._-]{1,64})["'`]?\s*$/i;
|
|
63
38
|
var TIMEOUT_RE = /^\s*(?:[-*]\s*)?(?:\*\*)?timeout_s(?:\*\*)?\s*:\s*(\d{1,6})\s*$/i;
|
|
64
|
-
var
|
|
65
|
-
var
|
|
39
|
+
var FENCE_OPEN_RE = /^\s*```+\s*dod\s*$/i;
|
|
40
|
+
var FENCE_CLOSE_RE = /^\s*```+\s*$/;
|
|
66
41
|
function readStory(text) {
|
|
67
42
|
const lines = text.split(`
|
|
68
43
|
`);
|
|
@@ -73,11 +48,11 @@ function readStory(text) {
|
|
|
73
48
|
let inDod = false;
|
|
74
49
|
for (const line of lines) {
|
|
75
50
|
if (inDod) {
|
|
76
|
-
if (
|
|
51
|
+
if (FENCE_CLOSE_RE.test(line))
|
|
77
52
|
inDod = false;
|
|
78
53
|
continue;
|
|
79
54
|
}
|
|
80
|
-
if (
|
|
55
|
+
if (FENCE_OPEN_RE.test(line)) {
|
|
81
56
|
inDod = true;
|
|
82
57
|
continue;
|
|
83
58
|
}
|
package/dist/hooks/no-reask.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
wouldBeContent
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-7y2dq0pj.js";
|
|
5
5
|
import {
|
|
6
6
|
noReAskDeny
|
|
7
7
|
} from "./chunk-9gb21660.js";
|
|
8
8
|
import {
|
|
9
9
|
FactsStore
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-t1ywrfr4.js";
|
|
11
11
|
import {
|
|
12
12
|
allow,
|
|
13
13
|
deny,
|
|
@@ -15,19 +15,19 @@ import {
|
|
|
15
15
|
isWriteOrEdit,
|
|
16
16
|
readPayload,
|
|
17
17
|
runHook
|
|
18
|
-
} from "./chunk-
|
|
19
|
-
import"./chunk-
|
|
18
|
+
} from "./chunk-tzzwddct.js";
|
|
19
|
+
import"./chunk-b8kxzna2.js";
|
|
20
|
+
import"./chunk-c6t5nx0r.js";
|
|
20
21
|
import {
|
|
21
22
|
openBlocks,
|
|
22
23
|
parseQuestions
|
|
23
|
-
} from "./chunk-
|
|
24
|
-
import"./chunk-
|
|
25
|
-
import"./chunk-
|
|
26
|
-
import"./chunk-0bt6yb2q.js";
|
|
24
|
+
} from "./chunk-rpcxsqh3.js";
|
|
25
|
+
import"./chunk-m3mewgnw.js";
|
|
26
|
+
import"./chunk-39zh2e44.js";
|
|
27
27
|
import {
|
|
28
28
|
factsPath,
|
|
29
29
|
locateWork
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-sq44k6g2.js";
|
|
31
31
|
|
|
32
32
|
// src/hooks/no-reask.ts
|
|
33
33
|
import { existsSync, readFileSync } from "node:fs";
|