@gitroll/tacitt-cli 0.6.10 → 0.6.12

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 (63) hide show
  1. package/README.md +47 -4
  2. package/bin/INDEX.md +6 -4
  3. package/bin/tacitt.cjs +1 -0
  4. package/dist/{agent-setup-LPd8WEsN.mjs → agent-setup-B12VbvN_.mjs} +2 -2
  5. package/dist/agent-setup-worker.mjs +5 -5
  6. package/dist/cli.mjs +39 -25
  7. package/dist/codex-title-worker.mjs +2 -2
  8. package/dist/configured-preview-worker.mjs +5 -5
  9. package/dist/configured-session-worker.mjs +27 -27
  10. package/dist/{frame-ByT1xayJ.mjs → frame-B3He21G8.mjs} +1 -1
  11. package/dist/{heap-CM298Yu0.mjs → heap-Blrat--4.mjs} +469 -30
  12. package/dist/inspection-worker.mjs +4 -4
  13. package/dist/{job-BHIwElNF.mjs → job-CBuIMTQ0.mjs} +57 -22
  14. package/dist/{locate-Cwv6WH8n.mjs → locate-D-ZaHpI0.mjs} +184 -18
  15. package/dist/{model-zvn5GUJ9.mjs → model-DR9odhWP.mjs} +1 -1
  16. package/dist/operation-executor.mjs +3 -3
  17. package/dist/preview-worker.mjs +1 -1
  18. package/dist/privacy-validator.mjs +49 -2
  19. package/dist/{query-By41gaKm.mjs → query-BYDcNKy2.mjs} +1869 -716
  20. package/dist/{run-ZQx7p4Rw.mjs → run-DQ9xyKSt.mjs} +4 -4
  21. package/dist/session-process.mjs +20 -0
  22. package/dist/{src-D_DfY--2.mjs → src-CKQlTA2Z.mjs} +297 -207
  23. package/dist/{src-3jvMvSQn.mjs → src-DeNJ8vOD.mjs} +535 -140
  24. package/dist/{src-BqtdFVq7.mjs → src-Do-qzuMn.mjs} +2329 -1786
  25. package/dist/store-database-worker.mjs +1 -1
  26. package/dist/web/assets/index-BgDdPL1c.js +172 -0
  27. package/dist/web/assets/index-DzOozqms.css +1 -0
  28. package/dist/web/index.html +3 -2
  29. package/package.json +2 -1
  30. package/skills/INDEX.md +6 -4
  31. package/skills/tacitt/INDEX.md +7 -6
  32. package/skills/tacitt/SKILL.md +11 -11
  33. package/skills/tacitt/references/INDEX.md +14 -11
  34. package/skills/tacitt/references/b-method.md +4 -4
  35. package/skills/tacitt/references/bootstrap.md +19 -5
  36. package/skills/tacitt/references/classification.md +4 -4
  37. package/skills/tacitt/references/commands.md +51 -34
  38. package/skills/tacitt/references/journey.md +7 -7
  39. package/skills/tacitt/references/parallel-review.md +35 -35
  40. package/skills/tacitt/references/send.md +15 -6
  41. package/skills/tacitt/scripts/INDEX.md +40 -37
  42. package/skills/tacitt/scripts/answer.mjs +91 -15
  43. package/skills/tacitt/scripts/journey-card-consolidation.mjs +1 -1
  44. package/skills/tacitt/scripts/journey-classification-metadata.mjs +75 -26
  45. package/skills/tacitt/scripts/journey-classification-progress.mjs +1 -2
  46. package/skills/tacitt/scripts/journey-classification-tasks.mjs +28 -8
  47. package/skills/tacitt/scripts/journey-classification.mjs +6 -1
  48. package/skills/tacitt/scripts/journey-consolidation.mjs +1 -0
  49. package/skills/tacitt/scripts/journey-panel-host.d.mts +2 -0
  50. package/skills/tacitt/scripts/journey-panel-host.mjs +25 -2
  51. package/skills/tacitt/scripts/journey-scan-timing.d.mts +5 -0
  52. package/skills/tacitt/scripts/journey-scan-timing.mjs +31 -4
  53. package/skills/tacitt/scripts/journey-state.d.mts +9 -1
  54. package/skills/tacitt/scripts/journey-state.mjs +95 -8
  55. package/skills/tacitt/scripts/journey-tasks.d.mts +1 -0
  56. package/skills/tacitt/scripts/journey-tasks.mjs +24 -9
  57. package/skills/tacitt/scripts/journey.d.mts +44 -31
  58. package/skills/tacitt/scripts/journey.mjs +34 -7
  59. package/skills/tacitt/scripts/privacy-validator.mjs +188 -11
  60. package/skills/tacitt/scripts/review.d.mts +7 -6
  61. package/skills/tacitt/scripts/review.mjs +922 -205
  62. package/dist/web/assets/index-B14e6_-z.js +0 -174
  63. package/dist/web/assets/index-CYJBq1px.css +0 -1
@@ -5484,12 +5484,33 @@ object({
5484
5484
  });
5485
5485
  //#endregion
5486
5486
  //#region packages/processing/src/errors.ts
5487
+ const sitePattern = /^[a-z][a-z0-9]*(?:-[a-z0-9]+){0,7}$/;
5488
+ const harnessPattern = /^[a-z]{1,16}$/;
5489
+ const versionPattern = /^\d{1,6}(?:\.\d{1,6}){1,3}(?:-[0-9A-Za-z.]{1,24})?$/;
5490
+ /** The validated site fields of `value`; anything that does not match its pattern is dropped. */
5491
+ function siteFields(value) {
5492
+ if (typeof value !== "object" || value === null) return void 0;
5493
+ const site = Reflect.get(value, "site");
5494
+ if (typeof site !== "string" || !sitePattern.test(site)) return void 0;
5495
+ const harness = Reflect.get(value, "harness");
5496
+ const harnessVersion = Reflect.get(value, "harnessVersion");
5497
+ return {
5498
+ site,
5499
+ ...typeof harness === "string" && harnessPattern.test(harness) ? { harness } : {},
5500
+ ...typeof harnessVersion === "string" && versionPattern.test(harnessVersion) ? { harnessVersion } : {}
5501
+ };
5502
+ }
5487
5503
  var ProcessingError = class extends Error {
5488
5504
  code;
5505
+ site;
5506
+ harness;
5507
+ harnessVersion;
5489
5508
  constructor(code, options) {
5490
5509
  super(code, options);
5491
5510
  this.name = "ProcessingError";
5492
5511
  this.code = code;
5512
+ const named = siteFields(options);
5513
+ if (named) Object.assign(this, named);
5493
5514
  }
5494
5515
  };
5495
5516
  function fail(code, options) {
@@ -5552,6 +5573,10 @@ const credentialNames = Object.freeze([
5552
5573
  "auth_token",
5553
5574
  "session_token",
5554
5575
  "authorization",
5576
+ "authorization_code",
5577
+ "oauth_code",
5578
+ "密碼",
5579
+ "密码",
5555
5580
  "proxy_authorization",
5556
5581
  "x_api_key",
5557
5582
  "private_key",
@@ -5837,13 +5862,13 @@ function assignments(input, output) {
5837
5862
  }
5838
5863
  if (input.field.kind === "key") return;
5839
5864
  const consumed = headers(input, output);
5840
- if (!/[:=]|--/u.test(input.text)) return;
5865
+ if (!/[:=:]|--/u.test(input.text)) return;
5841
5866
  if (!mayContainCredentialName(input.text)) return;
5842
- const expression = /(?:(?<![\p{L}\p{N}_/?&#-])(\\?["']?)([\p{L}\p{N}_-]{1,64})\1([ \t]*)[:=]([ \t]*)|(?<![\p{L}\p{N}_-])--([\p{L}\p{N}_-]{1,64})([ \t]+)(?![ \t-]))/giu;
5867
+ const expression = /(?:(?<![\p{L}\p{N}_/?&#-])(\\?["']?)((?:oauth[ \t]+)?authorization[ \t]+code|oauth[ \t]+code|[\p{L}\p{N}_-]{1,64})\1([ \t]*)[:=:]([ \t]*)|(?<![\p{L}\p{N}_-])--([\p{L}\p{N}_-]{1,64})([ \t]+)(?![ \t-]))/giu;
5843
5868
  let match;
5844
5869
  let headerIndex = 0;
5845
5870
  while ((match = expression.exec(input.text)) !== null) {
5846
- const label = normalizeCredentialName(match[2] ?? match[5] ?? "");
5871
+ const label = normalizeCredentialName((match[2] ?? match[5] ?? "").replace(/[ \t]+/gu, "_"));
5847
5872
  if (!credentialName(label)) continue;
5848
5873
  while ((consumed[headerIndex]?.end ?? Infinity) <= match.index) headerIndex += 1;
5849
5874
  const header = consumed[headerIndex];
@@ -7661,10 +7686,10 @@ function urlActions(locator, input, result) {
7661
7686
  actions: [action]
7662
7687
  });
7663
7688
  }
7664
- const inspect = (range, key, query = false) => {
7689
+ const inspect = (range, key, query = false, oauthResponse = false) => {
7665
7690
  if (range.start >= range.end) return;
7666
7691
  const raw = input.text.slice(range.start, range.end);
7667
- const credential = key !== void 0 && credentialName(key);
7692
+ const credential = key !== void 0 && (credentialName(key) || oauthResponse && key === "code");
7668
7693
  if (!withinLimit({
7669
7694
  raw,
7670
7695
  range
@@ -7711,6 +7736,8 @@ function urlActions(locator, input, result) {
7711
7736
  const end = hash < 0 ? locator.raw.length : hash;
7712
7737
  const question = locator.raw.indexOf("?", pathEnd);
7713
7738
  if (question >= 0 && question < end) {
7739
+ const keys = new URLSearchParams(locator.raw.slice(question + 1, end));
7740
+ const oauthResponse = (locator.scheme === "http" || locator.scheme === "https") && keys.has("code") && (keys.has("state") || keys.has("session_state") || /(?:^|\/)(?:oauth2?|callback|oauth2?[_-]callback)(?:\/|$)/iu.test(locator.raw.slice(suffix, pathEnd)));
7714
7741
  start = question + 1;
7715
7742
  for (let index = start; index <= end; index++) {
7716
7743
  if (index !== end && locator.raw[index] !== "&") continue;
@@ -7720,7 +7747,7 @@ function urlActions(locator, input, result) {
7720
7747
  if (key !== null) inspect({
7721
7748
  start: offset + equals + 1,
7722
7749
  end: offset + index
7723
- }, key, true);
7750
+ }, key, true, oauthResponse);
7724
7751
  } else inspect({
7725
7752
  start: offset + start,
7726
7753
  end: offset + index
@@ -9431,7 +9458,7 @@ Object.freeze([
9431
9458
  ]);
9432
9459
  Object.freeze({
9433
9460
  implementation: originalInspectionVersion,
9434
- detector: `static-catalog-11`,
9461
+ detector: `static-catalog-12`,
9435
9462
  parser: nativeParserVersion,
9436
9463
  dictionary: entityDictionaryVersion
9437
9464
  });
@@ -9679,6 +9706,24 @@ const termEvidenceSchema = object({
9679
9706
  rationale: termAssessmentSchema.shape.rationale,
9680
9707
  stance: termAssessmentSchema.shape.stance
9681
9708
  }).strict().refine((evidence) => evidence.end > evidence.start);
9709
+ const namedBatch = object({
9710
+ journeyId: id$1,
9711
+ batchId: id$1,
9712
+ batchDigest: digest$2
9713
+ }).strict();
9714
+ discriminatedUnion("kind", [namedBatch.extend({ kind: literal("inspect") }).strict(), namedBatch.extend({
9715
+ kind: literal("apply"),
9716
+ expectedPackId: id$1,
9717
+ idempotencyKey: id$1
9718
+ }).strict()]);
9719
+ object({
9720
+ status: _enum([
9721
+ "eligible",
9722
+ "reopened",
9723
+ "replayed"
9724
+ ]),
9725
+ packId: id$1
9726
+ }).strict();
9682
9727
  object({
9683
9728
  journeyId: id$1,
9684
9729
  idempotencyKey: id$1,
@@ -9688,6 +9733,10 @@ object({
9688
9733
  units: array(object({
9689
9734
  batchId: id$1,
9690
9735
  batchDigest: digest$2,
9736
+ coverage: object({
9737
+ attemptId: id$1,
9738
+ receipts: array(digest$2).min(1).max(8e4)
9739
+ }).strict().optional(),
9691
9740
  /** Legacy unit summary in stored packs; accepted and never read (ADR 0178). */
9692
9741
  summary: string().trim().min(1).refine((value) => Buffer.byteLength(value) <= 1024).optional(),
9693
9742
  exclude: string().trim().refine((value) => codePoints(value) >= 1 && codePoints(value) <= 500).nullable()
@@ -10107,6 +10156,13 @@ const journeyArtifactSchema = object({
10107
10156
  archiveBytes: count$1
10108
10157
  }).strict()
10109
10158
  }).strict();
10159
+ /** A closed reader attempt that left named units without a coverage receipt. */
10160
+ const reviewInterruptionSchema = object({
10161
+ inputRevision: count$1.min(1),
10162
+ packId: journeyIdSchema,
10163
+ reason: _enum(["reader-refused", "retry-exhausted"]),
10164
+ batchIds: array(journeyIdSchema).min(1).max(1e4).refine((ids) => new Set(ids).size === ids.length)
10165
+ }).strict();
10110
10166
  const journeyWorkSchema = object({
10111
10167
  id: journeyIdSchema,
10112
10168
  title: label,
@@ -10198,6 +10254,7 @@ const journeyWorkSchema = object({
10198
10254
  /** Images the Work's sessions leave out (D7); absent when a session receipt predates it. */
10199
10255
  imagesOmitted: count$1.optional()
10200
10256
  }).strict().optional(),
10257
+ reviewInterruptions: array(reviewInterruptionSchema).optional(),
10201
10258
  totalBatches: count$1,
10202
10259
  completedBatches: count$1,
10203
10260
  groupIds: array(journeyIdSchema),
@@ -10221,7 +10278,12 @@ const journeyWorkSchema = object({
10221
10278
  const journeyConsentSchema = object({
10222
10279
  provider: label,
10223
10280
  allowedAt: datetime(),
10224
- source: _enum(["conversation", "panel"])
10281
+ source: _enum(["conversation", "panel"]),
10282
+ /**
10283
+ * The account signed in when consent was recorded (ADR 0276 D8). Absent in a build with no
10284
+ * sign-in client and in a journey started before this version (Q11 a, Q13 a).
10285
+ */
10286
+ subject: string().min(1).max(128).optional()
10225
10287
  }).strict();
10226
10288
  const journeyExceptionSchema = object({
10227
10289
  id: journeyIdSchema,
@@ -10235,6 +10297,7 @@ const journeyExceptionSchema = object({
10235
10297
  }).strict();
10236
10298
  object({
10237
10299
  formatVersion: literal(10),
10300
+ outputVersion: number().int().positive().optional(),
10238
10301
  classificationRevision: count$1.nullable(),
10239
10302
  privacy: journeyPrivacySchema,
10240
10303
  delegation: journeyDelegationSchema.nullable(),
@@ -10292,7 +10355,21 @@ object({
10292
10355
  /** Sessions whose last activity lies in this period (ADR 0206); absent means all. */
10293
10356
  period: sessionPeriodSchema.optional(),
10294
10357
  /** The Passport address and links chosen in this Journey (ADR 0246); absent means none yet. */
10295
- profile: journeyProfileSchema.optional()
10358
+ profile: journeyProfileSchema.optional(),
10359
+ /**
10360
+ * The last account read that re-seeded every Work (ADR 0277 section 5). Only scope
10361
+ * confirmation and Retry set `read`; late classification records only a failure. Absent in a
10362
+ * journey of an earlier version, which reads as not `read`.
10363
+ */
10364
+ accountRead: object({
10365
+ status: _enum([
10366
+ "read",
10367
+ "signed-out",
10368
+ "unavailable"
10369
+ ]),
10370
+ subject: string().min(1).max(128).optional(),
10371
+ at: datetime()
10372
+ }).strict().optional()
10296
10373
  }).strict();
10297
10374
  //#endregion
10298
10375
  //#region packages/application/src/journey/b/model.ts
@@ -10616,7 +10693,7 @@ function locateTerms(batches, terms) {
10616
10693
  }];
10617
10694
  }));
10618
10695
  for (const { type, value, index } of unique.values()) {
10619
- if (admitCustomTerm(value)?.value !== value || !texts.some((item) => item.text.includes(value))) {
10696
+ if (value.includes("█") || admitCustomTerm(value)?.value !== value || !texts.some((item) => item.text.includes(value))) {
10620
10697
  unlocated++;
10621
10698
  unlocatedIndices.push(index);
10622
10699
  continue;
@@ -10640,7 +10717,107 @@ function locateTerms(batches, terms) {
10640
10717
  };
10641
10718
  }
10642
10719
  //#endregion
10720
+ //#region packages/application/src/journey/terms/read-pages.ts
10721
+ /** Leave ample space for tool framing, JSON escaping and the final receipt on each read. */
10722
+ const pageBytes = 6e3;
10723
+ /** Each receipt binds the delivered text, its position, the frozen batch and its assignment. */
10724
+ function reviewReadPages(batch, attemptId) {
10725
+ const pages = [];
10726
+ let text = "";
10727
+ function flush() {
10728
+ if (!text) return;
10729
+ const receipt = createHash("sha256").update(JSON.stringify([
10730
+ "scan-read-v1",
10731
+ attemptId,
10732
+ batch.id,
10733
+ batch.digest,
10734
+ pages.length,
10735
+ text
10736
+ ])).digest("hex");
10737
+ pages.push({
10738
+ text,
10739
+ receipt
10740
+ });
10741
+ text = "";
10742
+ }
10743
+ for (const chunk of batch.chunks) {
10744
+ if (!chunk.text.length) throw new Error("EMPTY_REVIEW_PAGE");
10745
+ let offset = 0;
10746
+ while (offset < chunk.text.length) {
10747
+ const header = "\nCHUNK " + chunk.id + " " + (chunk.core ? "review" : "context") + " " + chunk.role + " UTF16_START " + offset + "\n";
10748
+ const available = pageBytes - Buffer.byteLength(text + header);
10749
+ if (available < 4) {
10750
+ if (!text) throw new Error("INVALID_REVIEW_PAGE_HEADER");
10751
+ flush();
10752
+ continue;
10753
+ }
10754
+ let end = offset;
10755
+ let bytes = 0;
10756
+ while (end < chunk.text.length) {
10757
+ const point = chunk.text.codePointAt(end);
10758
+ if (point === void 0) throw new Error("INVALID_REVIEW_PAGE_RANGE");
10759
+ const size = point < 128 ? 1 : point < 2048 ? 2 : point < 65536 ? 3 : 4;
10760
+ if (bytes + size > available) break;
10761
+ end += point >= 65536 ? 2 : 1;
10762
+ bytes += size;
10763
+ }
10764
+ text += header + chunk.text.slice(offset, end);
10765
+ offset = end;
10766
+ if (offset < chunk.text.length) flush();
10767
+ }
10768
+ }
10769
+ flush();
10770
+ return pages;
10771
+ }
10772
+ //#endregion
10643
10773
  //#region apps/cli/src/skill-install/privacy-validator.ts
10774
+ const sourceReferenceSchema = object({
10775
+ chunkId: uuid(),
10776
+ start: number().int(),
10777
+ end: number().int()
10778
+ }).strict();
10779
+ /** Resolve sensitive spans locally against the projected, assigned core text. */
10780
+ function resolvePrivacySources(raw, batches) {
10781
+ if (!Array.isArray(raw)) throw new Error("INVALID_FINDING");
10782
+ if (!raw.some((term) => typeof term === "object" && term !== null && "source" in term)) return raw;
10783
+ const chunks = new Map(batches.flatMap(({ chunks }) => chunks.map((chunk) => [chunk.id, chunk])));
10784
+ const diagnostics = [];
10785
+ let invalidCount = 0;
10786
+ const resolved = raw.map((term, index) => {
10787
+ if (typeof term !== "object" || term === null || !("source" in term)) return term;
10788
+ const invalid = (reason) => {
10789
+ invalidCount++;
10790
+ if (diagnostics.length < 32) diagnostics.push(`draft.terms[${index}].source: ${reason}`);
10791
+ };
10792
+ const reference = sourceReferenceSchema.safeParse(term.source);
10793
+ if (!reference.success || "value" in term) return invalid("use only a chunkId and integer start/end offsets for the source");
10794
+ const { chunkId, start, end } = reference.data;
10795
+ const chunk = chunks.get(chunkId);
10796
+ if (!chunk?.core) return invalid("select an assigned core chunk");
10797
+ if (start < 0 || end <= start || end > chunk.text.length) return invalid("check chunk-relative UTF-16 bounds");
10798
+ if (end - start > 8e3) return invalid("span exceeds the length limit");
10799
+ if (chunk.displayMasks?.some((range) => range.start < end && start < range.end)) return invalid("span intersects masked text");
10800
+ const value = chunk.text.slice(start, end);
10801
+ if (!value.isWellFormed()) {
10802
+ if ((chunk.text.codePointAt(start - 1) ?? 0) > 65535 || (chunk.text.codePointAt(end - 1) ?? 0) > 65535) return invalid("offset splits a UTF-16 surrogate pair");
10803
+ return invalid("span contains invalid UTF-16");
10804
+ }
10805
+ if (value.includes("█")) return invalid("span intersects masked text");
10806
+ if (!value.trim()) return invalid("span contains only whitespace");
10807
+ if (Array.from(value).length > 4e3) return invalid("span exceeds the length limit");
10808
+ const { source: _source, ...rest } = term;
10809
+ return {
10810
+ ...rest,
10811
+ value
10812
+ };
10813
+ });
10814
+ if (invalidCount) {
10815
+ const remaining = invalidCount - diagnostics.length;
10816
+ if (remaining) diagnostics.push(`${remaining} additional invalid source references`);
10817
+ throw new Error("INVALID_REVIEW_SPAN", { cause: diagnostics });
10818
+ }
10819
+ return resolved;
10820
+ }
10644
10821
  const suppliedTerms = array(object({
10645
10822
  key: string(),
10646
10823
  type: string(),
@@ -10683,4 +10860,4 @@ function validateStageAnswer(input, answer) {
10683
10860
  }
10684
10861
  }
10685
10862
  //#endregion
10686
- export { locateTerms, validateStageAnswer };
10863
+ export { locateTerms, resolvePrivacySources, reviewReadPages, validateStageAnswer };
@@ -3,11 +3,7 @@ export function parseReply(text: string): Record<string, unknown>
3
3
  export function estimateTokens(text: string): number
4
4
  export function readPlan(text: string, pageTokens?: number): { offset: number; limit: number }[]
5
5
  export function renderGuidance(guidance: unknown): string
6
- export function renderPackTask(
7
- packId: string,
8
- guidance: unknown,
9
- units: readonly { ref: string; unit: unknown }[],
10
- ): string
6
+ export function renderPackTask(packId: string, guidance: unknown): string
11
7
  export function readAnswer(replies: readonly Record<string, unknown>[]): {
12
8
  units: Map<string, { summary: string; exclude: string | null }>
13
9
  terms: { type: string; value: string; disposition: string; reason: string }[]
@@ -74,9 +70,13 @@ export function writePackTask(
74
70
  task: string,
75
71
  text: string,
76
72
  unitRefs: readonly string[],
77
- sourceBatches?: readonly {
73
+ sourceBatches: readonly {
74
+ id: string
75
+ digest: string
78
76
  workId: string
79
77
  chunks: readonly {
78
+ id: string
79
+ role: string
80
80
  text: string
81
81
  offset: number
82
82
  core: boolean
@@ -84,4 +84,5 @@ export function writePackTask(
84
84
  fieldHash: string
85
85
  }[]
86
86
  }[],
87
+ attemptId?: string,
87
88
  ): Promise<string>