@gitroll/tacitt-cli 0.6.12 → 0.6.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/{agent-setup-B12VbvN_.mjs → agent-setup-CEPQfjBv.mjs} +2 -2
  2. package/dist/agent-setup-worker.mjs +5 -5
  3. package/dist/cli.mjs +10 -10
  4. package/dist/codex-title-worker.mjs +1 -1
  5. package/dist/configured-preview-worker.mjs +5 -5
  6. package/dist/configured-session-worker.mjs +5 -5
  7. package/dist/{frame-B3He21G8.mjs → frame-CRm99088.mjs} +1 -1
  8. package/dist/{heap-Blrat--4.mjs → heap-Bh9tySJp.mjs} +12 -7
  9. package/dist/inspection-worker.mjs +4 -4
  10. package/dist/{job-CBuIMTQ0.mjs → job-CsWKWcM4.mjs} +135 -36
  11. package/dist/{locate-D-ZaHpI0.mjs → locate-CP2t26j2.mjs} +449 -244
  12. package/dist/{model-DR9odhWP.mjs → model-ChHuVKoB.mjs} +1 -1
  13. package/dist/operation-executor.mjs +3 -3
  14. package/dist/preview-worker.mjs +1 -1
  15. package/dist/privacy-validator.mjs +1 -1
  16. package/dist/{query-BYDcNKy2.mjs → query-D28k3XOr.mjs} +6044 -5706
  17. package/dist/{run-DQ9xyKSt.mjs → run-CiJmV__5.mjs} +6 -6
  18. package/dist/{src-Do-qzuMn.mjs → src-B3il9x5F.mjs} +617 -545
  19. package/dist/{src-CKQlTA2Z.mjs → src-CWMrGXJK.mjs} +180 -30
  20. package/dist/{src-DeNJ8vOD.mjs → src-CmvEJj46.mjs} +1806 -1690
  21. package/dist/store-database-worker.mjs +1 -1
  22. package/dist/web/assets/index-XdWDOC5H.js +172 -0
  23. package/dist/web/index.html +1 -1
  24. package/package.json +1 -1
  25. package/skills/tacitt/INDEX.md +1 -1
  26. package/skills/tacitt/SKILL.md +5 -3
  27. package/skills/tacitt/references/INDEX.md +2 -2
  28. package/skills/tacitt/references/b-method.md +4 -2
  29. package/skills/tacitt/references/bootstrap.md +1 -1
  30. package/skills/tacitt/references/commands.md +23 -4
  31. package/skills/tacitt/references/journey.md +5 -3
  32. package/skills/tacitt/references/parallel-review.md +22 -9
  33. package/skills/tacitt/references/remote-workers.md +6 -2
  34. package/skills/tacitt/scripts/INDEX.md +5 -5
  35. package/skills/tacitt/scripts/answer.mjs +12 -1
  36. package/skills/tacitt/scripts/describe.mjs +3 -2
  37. package/skills/tacitt/scripts/journey-classification-tasks.mjs +2 -0
  38. package/skills/tacitt/scripts/journey-classification.mjs +1 -0
  39. package/skills/tacitt/scripts/journey-scan-timing.mjs +3 -2
  40. package/skills/tacitt/scripts/journey-state.d.mts +3 -0
  41. package/skills/tacitt/scripts/journey-state.mjs +8 -1
  42. package/skills/tacitt/scripts/journey.mjs +31 -1
  43. package/skills/tacitt/scripts/privacy-validator.mjs +160 -40
  44. package/skills/tacitt/scripts/review.d.mts +1 -0
  45. package/skills/tacitt/scripts/review.mjs +296 -35
  46. package/dist/web/assets/index-BgDdPL1c.js +0 -172
@@ -1,17 +1,17 @@
1
- import { Gn as nativeField, Kn as nativeItems, Mn as walkNativeFields, Wn as nativeBoolean, Xn as retainedMainTextNodes, _r as declaredVersion, br as processingSite, dn as observeSource, fn as sourceSnapshotId, gr as ProcessingError, nr as defaultLimits, qn as nativeText, zn as parseNativeRecord } from "./locate-D-ZaHpI0.mjs";
2
- import { $r as nativeAdapterVersions, Oi as gitMetadataBudgetBytes, it as reviewInventory } from "./src-Do-qzuMn.mjs";
3
- import { a as isRecord, i as errorCode, n as checkDiscoveryAbort, o as unresolvedMetadata, r as discoveryBounds, t as DiscoveryWarnings } from "./model-DR9odhWP.mjs";
4
- import { c as previewLimits, d as checkOpenSource, f as checkSource, h as openSource, i as pageFits, l as previewSourceVersion, m as noSymlinks, p as fileSnapshot, r as previewHeapLimits, s as previewMessageSchema, u as createZstdFrameCheck } from "./run-DQ9xyKSt.mjs";
1
+ import { $n as retainedMainTextNodes, Cr as processingSite, Fn as walkNativeFields, Hn as parseNativeRecord, Jn as nativeField, Xn as nativeText, Yn as nativeItems, ar as defaultLimits, br as declaredVersion, hn as sourceSnapshotId, mn as observeSource, qn as nativeBoolean, yr as ProcessingError } from "./locate-CP2t26j2.mjs";
2
+ import { Hr as nativeAdapterVersions, it as reviewInventory, ji as gitMetadataBudgetBytes } from "./src-B3il9x5F.mjs";
3
+ import { a as isRecord, i as errorCode, n as checkDiscoveryAbort, o as unresolvedMetadata, r as discoveryBounds, t as DiscoveryWarnings } from "./model-ChHuVKoB.mjs";
4
+ import { c as previewLimits, d as checkOpenSource, f as checkSource, h as openSource, i as pageFits, l as previewSourceVersion, m as noSymlinks, p as fileSnapshot, r as previewHeapLimits, s as previewMessageSchema, u as createZstdFrameCheck } from "./run-CiJmV__5.mjs";
5
5
  import { a as titleHintLimits, n as titleHeapLimits, o as titleInputSchema, r as decodeTitleError, s as titleReplySchema } from "./heap-1FYhGds4.mjs";
6
6
  import { constants } from "node:fs";
7
- import { lstat, open, opendir, readFile, readdir, realpath, stat } from "node:fs/promises";
7
+ import { access, constants as constants$1, lstat, open, opendir, readFile, readdir, realpath, stat } from "node:fs/promises";
8
8
  import { execFile } from "node:child_process";
9
9
  import { basename, dirname, isAbsolute, join, normalize, posix, relative, resolve, sep, win32 } from "node:path";
10
10
  import { PassThrough, Readable } from "node:stream";
11
11
  import { createHash, randomUUID } from "node:crypto";
12
12
  import { homedir, platform, tmpdir } from "node:os";
13
13
  import { pipeline } from "node:stream/promises";
14
- import { constants as constants$1, createZstdDecompress } from "node:zlib";
14
+ import { constants as constants$2, createZstdDecompress } from "node:zlib";
15
15
  import { Worker } from "node:worker_threads";
16
16
  import { setFlagsFromString } from "node:v8";
17
17
  import { parse, quote } from "shell-quote";
@@ -4215,7 +4215,8 @@ function seedEnvironment(input) {
4215
4215
  return env;
4216
4216
  }
4217
4217
  function gitCommands(env, limits, signal, budget) {
4218
- return async (args, directory = tmpdir(), allowMissing = false) => {
4218
+ /** Runs one command within the limits; settles with its exit status and output. */
4219
+ const run = async (args, directory) => {
4219
4220
  checkSeedAbort(signal);
4220
4221
  if (budget.remaining < 1) throw new ProcessingError("PROCESSING_LIMIT");
4221
4222
  return await new Promise((resolve, reject) => {
@@ -4239,15 +4240,158 @@ function gitCommands(env, limits, signal, budget) {
4239
4240
  budget.remaining -= bytes;
4240
4241
  if (signal.aborted) return reject(new ProcessingError("PROCESSING_CANCELED"));
4241
4242
  if (budget.remaining < 0 || bytes > limits.maxCommandBytes || error?.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER" || error?.killed) return reject(new ProcessingError("PROCESSING_LIMIT"));
4242
- if (error !== null && !(allowMissing && error.code === 1)) return reject(new ProcessingError("PROCESSING_FAILED"));
4243
- try {
4244
- resolve(new TextDecoder("utf-8", { fatal: true }).decode(stdout));
4245
- } catch {
4246
- reject(new ProcessingError("PROCESSING_FAILED"));
4247
- }
4243
+ resolve({
4244
+ error,
4245
+ stdout,
4246
+ stderr
4247
+ });
4248
4248
  });
4249
4249
  });
4250
4250
  };
4251
+ const failed = (args, code) => new ProcessingError("PROCESSING_FAILED", gitExitSite(args[0], code));
4252
+ const command = async (args, directory = tmpdir(), allowMissing = false) => {
4253
+ const { error, stdout } = await run(args, directory);
4254
+ if (error !== null && !(allowMissing && error.code === 1)) throw failed(args, error.code);
4255
+ try {
4256
+ return new TextDecoder("utf-8", { fatal: true }).decode(stdout);
4257
+ } catch {
4258
+ throw new ProcessingError("PROCESSING_FAILED");
4259
+ }
4260
+ };
4261
+ /**
4262
+ * True only when `cat-file -e` reports a well-formed object ID absent without any error
4263
+ * (exit 1, empty stderr) with lazy fetching off, and the object store proves it absent.
4264
+ * Git also answers exit 1 for an unreadable object directory, so an unproven absence
4265
+ * fails closed instead of skipping the ref.
4266
+ */
4267
+ const objectMissing = async (objectId, directory) => {
4268
+ if (!objectIdPattern.test(objectId) || env["GIT_NO_LAZY_FETCH"] !== "1") throw new ProcessingError("PROCESSING_FAILED");
4269
+ const args = [
4270
+ "cat-file",
4271
+ "-e",
4272
+ "--end-of-options",
4273
+ objectId
4274
+ ];
4275
+ const { error, stderr } = await run(args, directory);
4276
+ if (error === null) return false;
4277
+ if (error.code !== 1 || stderr.byteLength !== 0) throw failed(args, error.code);
4278
+ if (!await provablyAbsent(resolve(directory, (await command([
4279
+ "rev-parse",
4280
+ "--git-path",
4281
+ "objects"
4282
+ ], directory)).trimEnd()), objectId)) throw failed(args, error.code);
4283
+ return true;
4284
+ };
4285
+ return Object.assign(command, { objectMissing });
4286
+ }
4287
+ /**
4288
+ * The local object store cannot hold `objectId`: no alternates, its loose path is reached
4289
+ * and absent (ENOENT, so every directory on the way is searchable), and every pack file
4290
+ * is readable, so Git's own pack lookup was complete.
4291
+ */
4292
+ async function provablyAbsent(objects, objectId) {
4293
+ const absent = async (path) => {
4294
+ try {
4295
+ await lstat(path);
4296
+ return false;
4297
+ } catch (error) {
4298
+ return errorCode(error) === "ENOENT";
4299
+ }
4300
+ };
4301
+ if (!await absent(join(objects, "info", "alternates"))) return false;
4302
+ if (!await absent(join(objects, objectId.slice(0, 2), objectId.slice(2)))) return false;
4303
+ let packs;
4304
+ try {
4305
+ packs = await readdir(join(objects, "pack"));
4306
+ } catch (error) {
4307
+ return errorCode(error) === "ENOENT";
4308
+ }
4309
+ try {
4310
+ for (const pack of packs) await access(join(objects, "pack", pack), constants$1.R_OK);
4311
+ } catch {
4312
+ return false;
4313
+ }
4314
+ return true;
4315
+ }
4316
+ /** A full SHA-1 or SHA-256 object ID as `for-each-ref` and `rev-parse` print it. */
4317
+ const objectIdPattern = /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/u;
4318
+ const gitSiteCommands = /* @__PURE__ */ new Set([
4319
+ "show-ref",
4320
+ "log",
4321
+ "config",
4322
+ "for-each-ref",
4323
+ "rev-parse",
4324
+ "cat-file"
4325
+ ]);
4326
+ /** Only fixed, known command names and process exit statuses may reach safe diagnostics. */
4327
+ function gitExitSite(command, code) {
4328
+ if (!gitSiteCommands.has(command ?? "") || typeof code !== "number" || !Number.isInteger(code) || code < 1 || code > 255) return {};
4329
+ return { site: `git-${command}-exit-${code}` };
4330
+ }
4331
+ //#endregion
4332
+ //#region packages/harnesses/src/export/git/refs.ts
4333
+ /** `show-ref` or `log` exited 128, as a ref to a missing object makes them. */
4334
+ function missingObjectExit(error) {
4335
+ return error instanceof ProcessingError && error.code === "PROCESSING_FAILED" && /^git-(?:show-ref|log)-exit-128$/u.test(error.site ?? "");
4336
+ }
4337
+ /**
4338
+ * `show-ref --head`, or, when it exits 128 or `enumerate` is set, every ref with a present
4339
+ * tip (ADR 2026-11-15-skip-missing-object-refs). A 128 exit that no missing tip explains
4340
+ * still fails closed.
4341
+ */
4342
+ async function readRefs(command, directory, enumerate = false) {
4343
+ if (enumerate) return await enumerateRefs(command, directory);
4344
+ try {
4345
+ return {
4346
+ text: await command(["show-ref", "--head"], directory, true),
4347
+ skipped: []
4348
+ };
4349
+ } catch (error) {
4350
+ if (!missingObjectExit(error)) throw error;
4351
+ const refs = await enumerateRefs(command, directory);
4352
+ if (!refs.skipped.length) throw error;
4353
+ return refs;
4354
+ }
4355
+ }
4356
+ /** Every author reachable from the refs that were not skipped, HEAD included. */
4357
+ async function readAuthors(command, directory, refs) {
4358
+ return await command([
4359
+ "log",
4360
+ ...refs.skipped.map((name) => `--exclude=${name}`),
4361
+ "--all",
4362
+ "--no-mailmap",
4363
+ "--no-show-signature",
4364
+ "--format=%an",
4365
+ "-z"
4366
+ ], directory);
4367
+ }
4368
+ /** `for-each-ref` lists a ref whose object is missing; `cat-file -e` decides each tip. */
4369
+ async function enumerateRefs(command, directory) {
4370
+ const head = await command([
4371
+ "rev-parse",
4372
+ "--verify",
4373
+ "--quiet",
4374
+ "HEAD"
4375
+ ], directory, true);
4376
+ const listed = await command(["for-each-ref", "--format=%(objectname) %(refname)"], directory);
4377
+ const lines = [...head ? [`${head.trimEnd()} HEAD`] : [], ...listed.split("\n")];
4378
+ if (lines.pop() !== "") throw new ProcessingError("PROCESSING_FAILED");
4379
+ const refs = lines.map((line) => {
4380
+ const space = line.indexOf(" ");
4381
+ const id = line.slice(0, space);
4382
+ const name = line.slice(space + 1);
4383
+ if (space < 0 || !objectIdPattern.test(id) || !name) throw new ProcessingError("PROCESSING_FAILED");
4384
+ return {
4385
+ id,
4386
+ name
4387
+ };
4388
+ });
4389
+ const missing = /* @__PURE__ */ new Map();
4390
+ for (const { id } of refs) if (!missing.has(id)) missing.set(id, await command.objectMissing(id, directory));
4391
+ return {
4392
+ text: refs.filter(({ id }) => !missing.get(id)).map(({ id, name }) => `${id} ${name}\n`).join(""),
4393
+ skipped: refs.filter(({ id }) => missing.get(id)).map(({ name }) => name)
4394
+ };
4251
4395
  }
4252
4396
  //#endregion
4253
4397
  //#region packages/harnesses/src/git/config.ts
@@ -4363,14 +4507,14 @@ async function selectedRepositories(roots, limits, signal, budget) {
4363
4507
  }
4364
4508
  //#endregion
4365
4509
  //#region packages/harnesses/src/export/git/state.ts
4366
- /** Pin local shallow boundaries as evidence limits without requiring unfetched history. */
4367
- async function localHistoryState(repository, refs, budget, signal) {
4510
+ /** Pin refs, local shallow boundaries and the skipped-ref count without requiring unfetched history. */
4511
+ async function localHistoryState(repository, refs, budget, signal, skipped = 0) {
4368
4512
  checkSeedAbort(signal);
4369
4513
  const shared = await gitText(join(repository.gitDirectory, "commondir"), 16384, budget);
4370
4514
  const common = shared === null ? repository.gitDirectory : resolve(repository.gitDirectory, shared.trim());
4371
4515
  const shallow = await gitText(join(common, "shallow"), budget.remaining, budget);
4372
4516
  checkSeedAbort(signal);
4373
- return createHash("sha256").update(`${Buffer.byteLength(refs)}:`).update(refs).update(shallow === null ? "absent" : `present:${shallow}`).digest("hex");
4517
+ return createHash("sha256").update(`${Buffer.byteLength(refs)}:`).update(refs).update(shallow === null ? "absent" : `present:${shallow}`).update(skipped ? `skipped:${skipped}` : "").digest("hex");
4374
4518
  }
4375
4519
  //#endregion
4376
4520
  //#region packages/harnesses/src/export/git/index.ts
@@ -4411,19 +4555,24 @@ function createGitNameSeedProvider(options = {}) {
4411
4555
  checkSeedAbort(signal);
4412
4556
  const scoped = await readNameConfig(command, repository.directory, limits, budget, signal);
4413
4557
  collect(scoped.names);
4414
- const before = await localHistoryState(repository, await command(["show-ref", "--head"], repository.directory, true), budget, signal);
4415
- const authors = await command([
4416
- "log",
4417
- "--all",
4418
- "--no-mailmap",
4419
- "--no-show-signature",
4420
- "--format=%an",
4421
- "-z"
4422
- ], repository.directory);
4423
- if (before !== await localHistoryState(repository, await command(["show-ref", "--head"], repository.directory, true), budget, signal)) throw new ProcessingError("PROCESSING_FAILED");
4558
+ let refs = await readRefs(command, repository.directory);
4559
+ let authors;
4560
+ try {
4561
+ authors = await readAuthors(command, repository.directory, refs);
4562
+ } catch (error) {
4563
+ if (refs.skipped.length || !missingObjectExit(error)) throw error;
4564
+ refs = await readRefs(command, repository.directory, true);
4565
+ if (!refs.skipped.length) throw error;
4566
+ authors = await readAuthors(command, repository.directory, refs);
4567
+ }
4568
+ const enumerate = refs.skipped.length > 0;
4569
+ const before = await localHistoryState(repository, refs.text, budget, signal, refs.skipped.length);
4570
+ const afterRefs = await readRefs(command, repository.directory, enumerate);
4571
+ if (before !== await localHistoryState(repository, afterRefs.text, budget, signal, afterRefs.skipped.length)) throw new ProcessingError("PROCESSING_FAILED");
4424
4572
  originals.set(repository.directory, {
4425
4573
  history: before,
4426
- config: scoped.fingerprint
4574
+ config: scoped.fingerprint,
4575
+ enumerate
4427
4576
  });
4428
4577
  collect(authors.split("\0"));
4429
4578
  snapshots.push(Object.freeze({
@@ -4436,9 +4585,10 @@ function createGitNameSeedProvider(options = {}) {
4436
4585
  }));
4437
4586
  }
4438
4587
  for (const repository of repositories) {
4439
- const history = await localHistoryState(repository, await command(["show-ref", "--head"], repository.directory, true), budget, signal);
4440
- const scoped = await readNameConfig(command, repository.directory, limits, budget, signal);
4441
4588
  const original = originals.get(repository.directory);
4589
+ const refs = await readRefs(command, repository.directory, original?.enumerate);
4590
+ const history = await localHistoryState(repository, refs.text, budget, signal, refs.skipped.length);
4591
+ const scoped = await readNameConfig(command, repository.directory, limits, budget, signal);
4442
4592
  if (original?.history !== history || original.config !== scoped.fingerprint) throw new ProcessingError("PROCESSING_FAILED");
4443
4593
  }
4444
4594
  if (config.fingerprint !== (await readNameConfig(command, void 0, limits, budget, signal, true)).fingerprint) throw new ProcessingError("PROCESSING_FAILED");
@@ -4682,7 +4832,7 @@ async function metadataStream(part, harness, options) {
4682
4832
  });
4683
4833
  const decoded = part.representation === "jsonl.zst" ? createZstdDecompress({
4684
4834
  chunkSize: Math.min(discoveryBounds.chunkBytes, headLimit),
4685
- params: { [constants$1.ZSTD_d_windowLogMax]: previewLimits.zstdWindowLogMax }
4835
+ params: { [constants$2.ZSTD_d_windowLogMax]: previewLimits.zstdWindowLogMax }
4686
4836
  }) : new PassThrough({ highWaterMark: chunkBytes });
4687
4837
  let streamError;
4688
4838
  const cancellation = new AbortController();