@plinth-music/cli 0.20.0 → 0.21.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/dist/cli.js CHANGED
@@ -7584,7 +7584,7 @@ function _getBuiltinFlags(long, short, userNames, userAliases) {
7584
7584
  // package.json
7585
7585
  var package_default = {
7586
7586
  name: "@plinth-music/cli",
7587
- version: "0.20.0",
7587
+ version: "0.21.0",
7588
7588
  description: "Plinth capstone sync daemon and CLI",
7589
7589
  type: "module",
7590
7590
  private: false,
@@ -30505,6 +30505,560 @@ function ensureGitignore(workspaceSlug) {
30505
30505
  function backupStamp2(d) {
30506
30506
  return d.toISOString().replace(/[-:.]/g, "").replace("Z", "");
30507
30507
  }
30508
+ // src/lib/context/observation.ts
30509
+ import {
30510
+ closeSync as closeSync2,
30511
+ constants as FS,
30512
+ fstatSync,
30513
+ lstatSync as lstatSync3,
30514
+ openSync as openSync2,
30515
+ readSync,
30516
+ realpathSync as realpathSync2
30517
+ } from "node:fs";
30518
+ import { createHash as createHash2 } from "node:crypto";
30519
+ import { basename as basename2, dirname as dirname6, join as join8, resolve as resolve3, sep as sep4 } from "node:path";
30520
+ var OBSERVATION_MAX_BYTES = 64 * 1024 * 1024;
30521
+ var OBSERVATION_MAX_LINES = 200000;
30522
+ var READ_CHUNK = 1024 * 1024;
30523
+ var PROVENANCE_MAX = 256;
30524
+ var UNSAFE_PROVENANCE = /[\p{Cc}\p{Cf}]/u;
30525
+ function safeProvenance(v) {
30526
+ if (typeof v !== "string" || v === "")
30527
+ return null;
30528
+ if (v.length > PROVENANCE_MAX)
30529
+ return null;
30530
+ if (UNSAFE_PROVENANCE.test(v))
30531
+ return null;
30532
+ return v;
30533
+ }
30534
+ var ATTACHMENT_LABELS = new Set([
30535
+ "skill_listing",
30536
+ "deferred_tools_delta",
30537
+ "mcp_instructions_delta",
30538
+ "command_permissions",
30539
+ "agent_listing_delta",
30540
+ "total_tokens_reminder",
30541
+ "auto_mode",
30542
+ "remote_session_change",
30543
+ "file_history_snapshot"
30544
+ ]);
30545
+ function isFailure(x) {
30546
+ return x.status !== undefined;
30547
+ }
30548
+ function openSelected(selectedPath, hooks = {}) {
30549
+ const resolved = resolve3(selectedPath);
30550
+ let canonicalPath;
30551
+ try {
30552
+ canonicalPath = realpathSync2(resolved);
30553
+ } catch (err) {
30554
+ const code = err?.code;
30555
+ if (code === "ENOENT") {
30556
+ return { status: "absent", refusalReason: null, canonicalPath: null, indirection: false };
30557
+ }
30558
+ if (code === "ELOOP") {
30559
+ return {
30560
+ status: "refused",
30561
+ refusalReason: "path-unresolvable",
30562
+ canonicalPath: null,
30563
+ indirection: true
30564
+ };
30565
+ }
30566
+ return { status: "unreadable", refusalReason: null, canonicalPath: null, indirection: false };
30567
+ }
30568
+ const indirection = canonicalPath !== resolved;
30569
+ let before;
30570
+ try {
30571
+ before = lstatSync3(canonicalPath);
30572
+ } catch (err) {
30573
+ const code = err?.code;
30574
+ if (code === "ENOENT") {
30575
+ return { status: "absent", refusalReason: null, canonicalPath, indirection };
30576
+ }
30577
+ return { status: "unreadable", refusalReason: null, canonicalPath, indirection };
30578
+ }
30579
+ hooks.afterIdentityCheck?.();
30580
+ let fd;
30581
+ try {
30582
+ fd = openSync2(canonicalPath, FS.O_RDONLY | FS.O_NOFOLLOW | FS.O_NONBLOCK);
30583
+ } catch (err) {
30584
+ const code = err?.code;
30585
+ if (code === "ENOENT") {
30586
+ return { status: "absent", refusalReason: null, canonicalPath, indirection };
30587
+ }
30588
+ if (code === "ELOOP" || code === "EMLINK") {
30589
+ return { status: "refused", refusalReason: "target-changed", canonicalPath, indirection };
30590
+ }
30591
+ return { status: "unreadable", refusalReason: null, canonicalPath, indirection };
30592
+ }
30593
+ let after;
30594
+ try {
30595
+ after = fstatSync(fd);
30596
+ } catch {
30597
+ closeSync2(fd);
30598
+ return { status: "unreadable", refusalReason: null, canonicalPath, indirection };
30599
+ }
30600
+ if (!after.isFile()) {
30601
+ closeSync2(fd);
30602
+ return { status: "refused", refusalReason: "not-regular-file", canonicalPath, indirection };
30603
+ }
30604
+ if (after.dev !== before.dev || after.ino !== before.ino) {
30605
+ closeSync2(fd);
30606
+ return { status: "refused", refusalReason: "target-changed", canonicalPath, indirection };
30607
+ }
30608
+ return { fd, canonicalPath, indirection };
30609
+ }
30610
+ function readBounded(fd, maxBytes) {
30611
+ const hash2 = createHash2("sha256");
30612
+ const chunks = [];
30613
+ const buf = Buffer.allocUnsafe(READ_CHUNK);
30614
+ let bytesRead = 0;
30615
+ let truncated = false;
30616
+ for (;; ) {
30617
+ const want = Math.min(READ_CHUNK, maxBytes - bytesRead);
30618
+ if (want <= 0) {
30619
+ const probe2 = readSync(fd, buf, 0, 1, bytesRead);
30620
+ truncated = probe2 > 0;
30621
+ break;
30622
+ }
30623
+ const n = readSync(fd, buf, 0, want, bytesRead);
30624
+ if (n <= 0)
30625
+ break;
30626
+ const slice = Buffer.from(buf.subarray(0, n));
30627
+ hash2.update(slice);
30628
+ chunks.push(slice);
30629
+ bytesRead += n;
30630
+ }
30631
+ return {
30632
+ text: Buffer.concat(chunks).toString("utf8"),
30633
+ bytesRead,
30634
+ truncated,
30635
+ sha256: hash2.digest("hex")
30636
+ };
30637
+ }
30638
+ var USAGE_FIELDS = [
30639
+ ["inputTokens", ["input_tokens"]],
30640
+ ["cacheReadTokens", ["cache_read_input_tokens"]],
30641
+ ["cacheCreationTokens", ["cache_creation_input_tokens"]],
30642
+ ["outputTokens", ["output_tokens"]],
30643
+ ["cacheCreation1hTokens", ["cache_creation", "ephemeral_1h_input_tokens"]],
30644
+ ["cacheCreation5mTokens", ["cache_creation", "ephemeral_5m_input_tokens"]]
30645
+ ];
30646
+ function dig(obj, path) {
30647
+ let cur = obj;
30648
+ for (const key of path) {
30649
+ if (cur === null || typeof cur !== "object")
30650
+ return;
30651
+ cur = cur[key];
30652
+ }
30653
+ return cur;
30654
+ }
30655
+
30656
+ class UsageAccumulator {
30657
+ byRequest = new Map;
30658
+ sums = new Map;
30659
+ present = new Map;
30660
+ requests = 0;
30661
+ countedRecords = 0;
30662
+ duplicateRecords = 0;
30663
+ conflictingDuplicates = 0;
30664
+ untaggedRecords = 0;
30665
+ recordsWithoutUsage = 0;
30666
+ unresolvableRecords = 0;
30667
+ add(record2) {
30668
+ if (record2["type"] !== "assistant")
30669
+ return;
30670
+ const usage = dig(record2, ["message", "usage"]);
30671
+ const hasUsage = usage !== null && typeof usage === "object";
30672
+ if (hasUsage)
30673
+ this.countedRecords += 1;
30674
+ else
30675
+ this.recordsWithoutUsage += 1;
30676
+ const requestId = record2["requestId"];
30677
+ if (typeof requestId !== "string" || requestId === "") {
30678
+ if (hasUsage)
30679
+ this.untaggedRecords += 1;
30680
+ else
30681
+ this.unresolvableRecords += 1;
30682
+ return;
30683
+ }
30684
+ if (!this.byRequest.has(requestId)) {
30685
+ this.byRequest.set(requestId, null);
30686
+ this.requests += 1;
30687
+ }
30688
+ if (!hasUsage)
30689
+ return;
30690
+ const fingerprint = JSON.stringify(USAGE_FIELDS.map(([, path]) => dig(usage, path) ?? null));
30691
+ const prior = this.byRequest.get(requestId) ?? null;
30692
+ if (prior !== null) {
30693
+ if (prior === fingerprint)
30694
+ this.duplicateRecords += 1;
30695
+ else
30696
+ this.conflictingDuplicates += 1;
30697
+ return;
30698
+ }
30699
+ this.byRequest.set(requestId, fingerprint);
30700
+ for (const [name, path] of USAGE_FIELDS) {
30701
+ const raw = dig(usage, path);
30702
+ if (typeof raw !== "number" || !Number.isFinite(raw))
30703
+ continue;
30704
+ this.present.set(name, (this.present.get(name) ?? 0) + 1);
30705
+ this.sums.set(name, (this.sums.get(name) ?? 0) + raw);
30706
+ }
30707
+ }
30708
+ unresolved() {
30709
+ let n = 0;
30710
+ for (const fp of this.byRequest.values())
30711
+ if (fp === null)
30712
+ n += 1;
30713
+ return n;
30714
+ }
30715
+ finish() {
30716
+ if (this.countedRecords === 0 && this.recordsWithoutUsage === 0)
30717
+ return null;
30718
+ const unresolvedRequests = this.unresolved();
30719
+ const incompleteFields = [];
30720
+ const value = (name) => {
30721
+ const present2 = this.present.get(name) ?? 0;
30722
+ if (present2 > 0 && present2 === this.requests)
30723
+ return this.sums.get(name) ?? 0;
30724
+ if (present2 > 0)
30725
+ incompleteFields.push(name);
30726
+ return null;
30727
+ };
30728
+ const fields = Object.fromEntries(USAGE_FIELDS.map(([name]) => [name, value(name)]));
30729
+ const anyFullyCovered = USAGE_FIELDS.some(([name]) => (this.present.get(name) ?? 0) > 0 && (this.present.get(name) ?? 0) === this.requests);
30730
+ return {
30731
+ requests: this.requests,
30732
+ countedRecords: this.countedRecords,
30733
+ duplicateRecords: this.duplicateRecords,
30734
+ conflictingDuplicates: this.conflictingDuplicates,
30735
+ untaggedRecords: this.untaggedRecords,
30736
+ unresolvedRequests,
30737
+ recordsWithoutUsage: this.recordsWithoutUsage,
30738
+ unresolvableRecords: this.unresolvableRecords,
30739
+ ...fields,
30740
+ incompleteFields,
30741
+ incomplete: incompleteFields.length > 0 || this.conflictingDuplicates > 0 || this.untaggedRecords > 0 || unresolvedRequests > 0 || this.unresolvableRecords > 0 || this.requests > 0 && !anyFullyCovered
30742
+ };
30743
+ }
30744
+ }
30745
+ function hasToolResult(content) {
30746
+ if (!Array.isArray(content))
30747
+ return false;
30748
+ return content.some((b) => b !== null && typeof b === "object" && b["type"] === "tool_result");
30749
+ }
30750
+ function contentText(content) {
30751
+ if (typeof content === "string")
30752
+ return content;
30753
+ if (!Array.isArray(content))
30754
+ return "";
30755
+ return content.map((b) => b !== null && typeof b === "object" && typeof b["text"] === "string" ? b["text"] : "").join("");
30756
+ }
30757
+ function payloadBytes(payload) {
30758
+ if (payload === undefined)
30759
+ return 0;
30760
+ if (typeof payload === "string")
30761
+ return Buffer.byteLength(payload, "utf8");
30762
+ try {
30763
+ return Buffer.byteLength(JSON.stringify(payload) ?? "", "utf8");
30764
+ } catch {
30765
+ return 0;
30766
+ }
30767
+ }
30768
+
30769
+ class DeliveryAccumulator {
30770
+ rows = new Map;
30771
+ pendingCommand = false;
30772
+ bump(kind, label, bytes) {
30773
+ const key = `${kind} ${label}`;
30774
+ const row = this.rows.get(key) ?? { kind, label, occurrences: 0, recordedBytes: 0 };
30775
+ row.occurrences += 1;
30776
+ row.recordedBytes += bytes;
30777
+ this.rows.set(key, row);
30778
+ }
30779
+ add(record2) {
30780
+ const wasPending = this.pendingCommand;
30781
+ this.pendingCommand = false;
30782
+ const type = record2["type"];
30783
+ if (type === "attachment") {
30784
+ const att = record2["attachment"];
30785
+ const rawLabel = dig(att, ["type"]);
30786
+ const label = typeof rawLabel === "string" && ATTACHMENT_LABELS.has(rawLabel) ? rawLabel : "other";
30787
+ this.bump("harness-listing", label, payloadBytes(att));
30788
+ return;
30789
+ }
30790
+ if (type !== "user")
30791
+ return;
30792
+ const content = dig(record2, ["message", "content"]);
30793
+ const bytes = payloadBytes(content);
30794
+ const text = contentText(content);
30795
+ if (record2["isMeta"] === true) {
30796
+ if (wasPending)
30797
+ this.bump("command-body", "command-body", bytes);
30798
+ else
30799
+ this.bump("meta-injection", "meta-injection", bytes);
30800
+ return;
30801
+ }
30802
+ if (hasToolResult(content)) {
30803
+ this.bump("tool-result", "tool-result", bytes);
30804
+ return;
30805
+ }
30806
+ const opening = text.trimStart();
30807
+ this.pendingCommand = opening.startsWith("<command-message>") || opening.startsWith("<command-name>");
30808
+ this.bump("user-turn", "user-turn", bytes);
30809
+ }
30810
+ finish() {
30811
+ return [...this.rows.values()].sort((a, b) => b.recordedBytes - a.recordedBytes || a.label.localeCompare(b.label));
30812
+ }
30813
+ }
30814
+
30815
+ class BindingAccumulator {
30816
+ sessionIds = new Set;
30817
+ versions = new Set;
30818
+ cwds = new Set;
30819
+ branches = new Set;
30820
+ first = null;
30821
+ last = null;
30822
+ rejected = 0;
30823
+ add(record2) {
30824
+ const str2 = (k) => {
30825
+ const raw = record2[k];
30826
+ const safe = safeProvenance(raw);
30827
+ if (safe === null && typeof raw === "string" && raw !== "")
30828
+ this.rejected += 1;
30829
+ return safe;
30830
+ };
30831
+ const sid = str2("sessionId");
30832
+ if (sid !== null)
30833
+ this.sessionIds.add(sid);
30834
+ const ver = str2("version");
30835
+ if (ver !== null)
30836
+ this.versions.add(ver);
30837
+ const cwd = str2("cwd");
30838
+ if (cwd !== null)
30839
+ this.cwds.add(cwd);
30840
+ const branch = str2("gitBranch");
30841
+ if (branch !== null)
30842
+ this.branches.add(branch);
30843
+ const ts = str2("timestamp");
30844
+ if (ts !== null) {
30845
+ if (this.first === null || ts < this.first)
30846
+ this.first = ts;
30847
+ if (this.last === null || ts > this.last)
30848
+ this.last = ts;
30849
+ }
30850
+ }
30851
+ finish(workspaceMirrorDir) {
30852
+ const only = (s) => s.size === 1 ? [...s][0] : null;
30853
+ const cwd = only(this.cwds);
30854
+ const consistent = this.sessionIds.size === 1 && this.versions.size === 1 && this.cwds.size === 1;
30855
+ return {
30856
+ sessionId: only(this.sessionIds),
30857
+ runtimeVersion: only(this.versions),
30858
+ cwd,
30859
+ gitBranch: only(this.branches),
30860
+ firstTimestamp: this.first,
30861
+ lastTimestamp: this.last,
30862
+ distinctSessionIds: this.sessionIds.size,
30863
+ consistent,
30864
+ scope: deriveScope(cwd, workspaceMirrorDir),
30865
+ rejectedFields: this.rejected
30866
+ };
30867
+ }
30868
+ }
30869
+ function canonicalise(p) {
30870
+ const full = resolve3(p);
30871
+ let cur = full;
30872
+ const tail = [];
30873
+ for (;; ) {
30874
+ try {
30875
+ const real = realpathSync2(cur);
30876
+ return tail.length === 0 ? real : join8(real, ...tail.slice().reverse());
30877
+ } catch {
30878
+ const parent = dirname6(cur);
30879
+ if (parent === cur)
30880
+ return full;
30881
+ tail.push(basename2(cur));
30882
+ cur = parent;
30883
+ }
30884
+ }
30885
+ }
30886
+ function deriveScope(cwd, workspaceMirrorDir) {
30887
+ if (cwd === null || workspaceMirrorDir === undefined)
30888
+ return "unknown";
30889
+ const ws = canonicalise(workspaceMirrorDir);
30890
+ const here = canonicalise(cwd);
30891
+ if (here === ws)
30892
+ return "root";
30893
+ if (here.startsWith(ws.endsWith(sep4) ? ws : ws + sep4))
30894
+ return "below-root";
30895
+ return "outside";
30896
+ }
30897
+ function limitsFor(obs) {
30898
+ const limits = [
30899
+ {
30900
+ id: "observation-not-attributable",
30901
+ what: "which source contributed which tokens is not recoverable from this artefact: the standing context arrives as one aggregate in the first request's cache fields, with no per-source breakdown. The remainder is unattributable, not zero",
30902
+ owner: "not exposed by the measured artefact, runtime and this adapter; further effective-loading work stays with S2/E15 and the packaged half"
30903
+ },
30904
+ {
30905
+ id: "observation-interval",
30906
+ what: "this covers only the interval actually read from the selected file, identified by its byte boundary and digest. A live session keeps growing, so the same path measured later is a different interval",
30907
+ owner: "the reader who selected the file; re-run to extend it"
30908
+ },
30909
+ {
30910
+ id: "observation-inventory-not-contemporaneous",
30911
+ what: "the source inventory above is what is on disk NOW. It is not evidence that those files existed, or had those sizes, during the observed interval",
30912
+ owner: "E15, which compares arms rather than inventories"
30913
+ },
30914
+ {
30915
+ id: "observation-compaction",
30916
+ what: "resume, clear and compaction are not detected and were not demonstrated in any measured sample, so a compacted session may be reported as one continuous interval",
30917
+ owner: "a later S2/E15 lane with a purpose-built compacted session"
30918
+ },
30919
+ {
30920
+ id: "observation-delivery-cause",
30921
+ what: "a command body is labelled only when an invocation marker precedes it; an uncorrelated meta-injection's cause is not established. And a recorded delivery proves delivery happened, never that a body is not loaded by some other route",
30922
+ owner: "a later S2 lane, if per-route delivery proof is wanted"
30923
+ }
30924
+ ];
30925
+ if (obs.binding.rejectedFields > 0) {
30926
+ limits.push({
30927
+ id: "observation-provenance-refused",
30928
+ what: "one or more session/runtime/directory values in the file carried control characters or exceeded the length cap and were refused rather than printed, so they read as unknown above",
30929
+ owner: "the reader who selected the file"
30930
+ });
30931
+ }
30932
+ if (obs.indirection) {
30933
+ limits.push({
30934
+ id: "observation-path-indirection",
30935
+ what: "the selected path resolved through a link; the canonical path above is what was read",
30936
+ owner: "the reader who selected the file"
30937
+ });
30938
+ }
30939
+ if (!obs.binding.consistent) {
30940
+ limits.push({
30941
+ id: "observation-binding-inconsistent",
30942
+ what: "session id, runtime version or working directory is missing or varies across records, so this observation is NOT attributed to the workspace inventory and is reported separately",
30943
+ owner: "select a single-session transcript to attribute it"
30944
+ });
30945
+ }
30946
+ if (obs.binding.scope === "below-root") {
30947
+ limits.push({
30948
+ id: "observation-scope-unsupported",
30949
+ what: "the observed session ran below the workspace root, and the inventory's scoped-load class is not resolved per session, so its scoped sources are not matched to this observation",
30950
+ owner: "a later S2 lane, if per-scope resolution is wanted"
30951
+ });
30952
+ }
30953
+ return limits;
30954
+ }
30955
+ function emptyBinding(workspaceMirrorDir) {
30956
+ return new BindingAccumulator().finish(workspaceMirrorDir);
30957
+ }
30958
+ function shell(selectedPath, status, refusalReason, canonicalPath, indirection, opts, extras = {}) {
30959
+ const base2 = {
30960
+ status,
30961
+ refusalReason,
30962
+ selectedPath,
30963
+ canonicalPath,
30964
+ indirection,
30965
+ bytesRead: extras.bytesRead ?? 0,
30966
+ sha256: extras.sha256 ?? null,
30967
+ lines: extras.lines ?? { total: 0, parsed: 0, malformed: 0, truncated: false, cutFinalLine: false },
30968
+ binding: emptyBinding(opts.workspaceMirrorDir),
30969
+ usage: null,
30970
+ deliveries: []
30971
+ };
30972
+ return { ...base2, limits: limitsFor(base2), complete: false };
30973
+ }
30974
+ function buildObservation(selectedPath, opts = {}) {
30975
+ const maxBytes = opts.maxBytes ?? OBSERVATION_MAX_BYTES;
30976
+ const maxLines = opts.maxLines ?? OBSERVATION_MAX_LINES;
30977
+ const opened = openSelected(selectedPath, opts.openHooks ?? {});
30978
+ if (isFailure(opened)) {
30979
+ return shell(selectedPath, opened.status, opened.refusalReason, opened.canonicalPath, opened.indirection, opts);
30980
+ }
30981
+ let read;
30982
+ try {
30983
+ read = readBounded(opened.fd, maxBytes);
30984
+ } catch {
30985
+ return shell(selectedPath, "unreadable", null, opened.canonicalPath, opened.indirection, opts);
30986
+ } finally {
30987
+ try {
30988
+ closeSync2(opened.fd);
30989
+ } catch {}
30990
+ }
30991
+ const pieces = read.text.split(`
30992
+ `);
30993
+ if (pieces.length > 0 && pieces[pieces.length - 1] === "")
30994
+ pieces.pop();
30995
+ let cutFinalLine = false;
30996
+ let truncated = read.truncated;
30997
+ if (read.truncated && pieces.length > 0 && !read.text.endsWith(`
30998
+ `)) {
30999
+ pieces.pop();
31000
+ cutFinalLine = true;
31001
+ }
31002
+ if (pieces.length > maxLines) {
31003
+ pieces.length = maxLines;
31004
+ truncated = true;
31005
+ }
31006
+ const nonBlank = pieces.filter((l) => l.trim() !== "");
31007
+ if (nonBlank.length === 0) {
31008
+ return shell(selectedPath, truncated ? "read" : "empty", null, opened.canonicalPath, opened.indirection, opts, {
31009
+ bytesRead: read.bytesRead,
31010
+ sha256: read.sha256,
31011
+ lines: { total: 0, parsed: 0, malformed: 0, truncated, cutFinalLine }
31012
+ });
31013
+ }
31014
+ const usage = new UsageAccumulator;
31015
+ const deliveries = new DeliveryAccumulator;
31016
+ const binding = new BindingAccumulator;
31017
+ let parsed = 0;
31018
+ let malformed = 0;
31019
+ for (const line of nonBlank) {
31020
+ let record2;
31021
+ try {
31022
+ record2 = JSON.parse(line);
31023
+ } catch {
31024
+ malformed += 1;
31025
+ continue;
31026
+ }
31027
+ if (record2 === null || typeof record2 !== "object" || Array.isArray(record2)) {
31028
+ malformed += 1;
31029
+ continue;
31030
+ }
31031
+ parsed += 1;
31032
+ const rec = record2;
31033
+ binding.add(rec);
31034
+ usage.add(rec);
31035
+ deliveries.add(rec);
31036
+ }
31037
+ const lines = {
31038
+ total: nonBlank.length,
31039
+ parsed,
31040
+ malformed,
31041
+ truncated,
31042
+ cutFinalLine
31043
+ };
31044
+ const status = parsed === 0 ? "malformed" : "read";
31045
+ const finishedUsage = status === "read" ? usage.finish() : null;
31046
+ const base2 = {
31047
+ status,
31048
+ refusalReason: null,
31049
+ selectedPath,
31050
+ canonicalPath: opened.canonicalPath,
31051
+ indirection: opened.indirection,
31052
+ bytesRead: read.bytesRead,
31053
+ sha256: read.sha256,
31054
+ lines,
31055
+ binding: binding.finish(opts.workspaceMirrorDir),
31056
+ usage: finishedUsage,
31057
+ deliveries: status === "read" ? deliveries.finish() : []
31058
+ };
31059
+ const complete = status === "read" && malformed === 0 && !truncated && !cutFinalLine && (finishedUsage === null || !finishedUsage.incomplete);
31060
+ return { ...base2, limits: limitsFor(base2), complete };
31061
+ }
30508
31062
 
30509
31063
  // src/lib/context/context-account.ts
30510
31064
  function localRow(workspaceSlug) {
@@ -30709,13 +31263,13 @@ function collectExternalSources() {
30709
31263
  var STANDING_LIMITS = [
30710
31264
  {
30711
31265
  id: "observed-loading",
30712
- what: "what a session ACTUALLY loaded is not observed. Everything above is bytes on disk and the hook's own rendered output",
30713
- owner: "a later S2 lane: a bounded, explicit observation import (the transcript carries per-turn usage; no adapter is built)"
31266
+ what: "what a session ACTUALLY loaded is not observed here. Everything above is bytes on disk and the hook's own rendered output",
31267
+ owner: "pass `--observed <transcript.jsonl>` to measure one selected session's recorded delivery. Per-source attribution stays unavailable even then"
30714
31268
  },
30715
31269
  {
30716
31270
  id: "usage",
30717
- what: "tokens, cached and billed usage are not measured. The CLI has no token accounting of any kind",
30718
- owner: "the same later S2 lane, with the desktop half for effective-context diagnostics"
31271
+ what: "tokens, cached and billed usage are not measured here",
31272
+ owner: "pass `--observed <transcript.jsonl>` for one session's recorded per-request usage; the packaged/desktop half of effective-context diagnostics is still open"
30719
31273
  },
30720
31274
  {
30721
31275
  id: "user-level-config",
@@ -30767,7 +31321,11 @@ function buildContextAccount(workspaceSlug, deps = {}) {
30767
31321
  collectExternalSources()
30768
31322
  ];
30769
31323
  const sources = parts.flatMap((p) => p.sources);
30770
- const limits = [...parts.flatMap((p) => p.limits), ...STANDING_LIMITS];
31324
+ const limits = [
31325
+ ...parts.flatMap((p) => p.limits),
31326
+ ...STANDING_LIMITS,
31327
+ ...deps.observation?.limits ?? []
31328
+ ];
30771
31329
  const refusedFeedingHook = sources.filter((s) => s.status === "refused" && (s.route === "hook-injection" || s.path === VOICE_FILENAME));
30772
31330
  if (refusedFeedingHook.length > 0) {
30773
31331
  limits.unshift({
@@ -30805,6 +31363,7 @@ function buildContextAccount(workspaceSlug, deps = {}) {
30805
31363
  observedLoadedBytes: null,
30806
31364
  estimatedTokens: null,
30807
31365
  conditionalStanding,
31366
+ observation: deps.observation ?? null,
30808
31367
  limits
30809
31368
  };
30810
31369
  }
@@ -31059,13 +31618,92 @@ function renderAccount(out, account) {
31059
31618
  out.info(` · ${a}`);
31060
31619
  out.info("");
31061
31620
  }
31621
+ if (account.observation !== null)
31622
+ renderObservation(out, account.observation);
31062
31623
  out.info("Not measured here");
31063
- out.info(" Observed loading: not observed. Tokens and billed usage: not measured.");
31624
+ if (account.observation === null) {
31625
+ out.info(" Observed loading: not observed. Tokens and billed usage: not measured.");
31626
+ } else {
31627
+ out.info(" Observed above is ONE selected session's recorded delivery and usage. No token is attributed to any file.");
31628
+ }
31064
31629
  for (const l of account.limits) {
31065
31630
  out.info(` · ${l.what}`);
31066
31631
  out.info(` owed to: ${l.owner}`);
31067
31632
  }
31068
31633
  }
31634
+ var REFUSAL_PROSE = {
31635
+ "not-regular-file": "not a regular file",
31636
+ "target-changed": "the file opened was not the file checked — refused rather than measured",
31637
+ "path-unresolvable": "the path could not be resolved"
31638
+ };
31639
+ var STATUS_PROSE = {
31640
+ absent: "not there",
31641
+ unreadable: "could not be read",
31642
+ empty: "no records",
31643
+ malformed: "records present, none parsed — NOT a measured zero"
31644
+ };
31645
+ function renderObservation(out, obs) {
31646
+ const head = obs.complete ? "Observed" : "Observed (PARTIAL)";
31647
+ if (obs.status !== "read") {
31648
+ const why = REFUSAL_PROSE[obs.refusalReason ?? ""] ?? STATUS_PROSE[obs.status] ?? obs.status;
31649
+ out.info(`${head} ${obs.selectedPath}`);
31650
+ out.info(` ${why}. Nothing was measured, and that is not a zero.`);
31651
+ if (obs.bytesRead > 0 || obs.lines.total > 0) {
31652
+ out.info(` ${fmt(obs.bytesRead)} bytes read · ${fmt(obs.lines.total)} records seen` + (obs.lines.malformed > 0 ? ` · ${fmt(obs.lines.malformed)} malformed` : "") + (obs.lines.truncated ? " · stopped at the read bound" : "") + (obs.sha256 !== null ? ` · sha256 ${obs.sha256.slice(0, 16)}` : ""));
31653
+ }
31654
+ out.info("");
31655
+ return;
31656
+ }
31657
+ const b = obs.binding;
31658
+ out.info(`${head} ${fmt(obs.bytesRead)} bytes read from the selected transcript`);
31659
+ if (obs.canonicalPath !== null && obs.indirection) {
31660
+ out.info(` resolved through a link to ${obs.canonicalPath}`);
31661
+ }
31662
+ out.info(` session ${b.sessionId ?? "unknown"} · runtime ${b.runtimeVersion ?? "unknown"} · scope ${b.scope}`);
31663
+ out.info(` interval ${b.firstTimestamp ?? "unknown"} .. ${b.lastTimestamp ?? "unknown"} · sha256 ${obs.sha256?.slice(0, 16) ?? "unknown"}`);
31664
+ out.info(` ${fmt(obs.lines.parsed)} of ${fmt(obs.lines.total)} records parsed` + (obs.lines.malformed > 0 ? ` · ${fmt(obs.lines.malformed)} malformed` : "") + (obs.lines.truncated ? " · stopped at the read bound" : "") + (obs.lines.cutFinalLine ? " · final record severed by the bound" : ""));
31665
+ if (b.rejectedFields > 0) {
31666
+ out.info(` ${fmt(b.rejectedFields)} provenance value(s) in the file were refused as unsafe or over-long and read as unknown above.`);
31667
+ }
31668
+ if (!b.consistent) {
31669
+ out.info(" NOT attributed to this workspace: session, runtime or directory is missing or varies across records.");
31670
+ }
31671
+ out.info("");
31672
+ const u = obs.usage;
31673
+ if (u === null) {
31674
+ out.info(" Usage — no record carried a usage object. Unknown, not zero.");
31675
+ } else {
31676
+ const n = (v) => v === null ? "unknown" : fmt(v);
31677
+ out.info(` Usage over ${fmt(u.requests)} requests, from ${fmt(u.countedRecords)} usage-bearing records` + (u.duplicateRecords > 0 ? ` (${fmt(u.duplicateRecords)} repeated the same usage)` : ""));
31678
+ out.info(` fresh input ${n(u.inputTokens)} tokens`);
31679
+ out.info(` cache read ${n(u.cacheReadTokens)} tokens`);
31680
+ out.info(` cache written ${n(u.cacheCreationTokens)} tokens`);
31681
+ out.info(` output ${n(u.outputTokens)} tokens`);
31682
+ if (u.conflictingDuplicates > 0) {
31683
+ out.info(` ⚠ ${fmt(u.conflictingDuplicates)} request(s) reported conflicting usage; the figures above are incomplete`);
31684
+ }
31685
+ if (u.untaggedRecords > 0) {
31686
+ out.info(` ⚠ ${fmt(u.untaggedRecords)} record(s) carried usage with no request id; excluded, because they cannot be shown independent`);
31687
+ }
31688
+ if (u.unresolvedRequests > 0) {
31689
+ out.info(` ⚠ ${fmt(u.unresolvedRequests)} of ${fmt(u.requests)} request(s) carried no usage record, so what they cost is unknown — not zero`);
31690
+ }
31691
+ if (u.unresolvableRecords > 0) {
31692
+ out.info(` ⚠ ${fmt(u.unresolvableRecords)} record(s) had neither usage nor a request id; nothing can name or resolve them`);
31693
+ }
31694
+ if (u.incompleteFields.length > 0) {
31695
+ out.info(` ⚠ not every request reported: ${u.incompleteFields.join(", ")}`);
31696
+ }
31697
+ }
31698
+ out.info("");
31699
+ if (obs.deliveries.length > 0) {
31700
+ out.info(" Recorded deliveries — payload bytes as stored, not injected or billed bytes");
31701
+ for (const d of obs.deliveries) {
31702
+ out.info(` ${d.kind.padEnd(16)} ${d.label.padEnd(24)} ${String(d.occurrences).padStart(4)}x ${fmt(d.recordedBytes)} bytes`);
31703
+ }
31704
+ out.info("");
31705
+ }
31706
+ }
31069
31707
  async function runContext(args, deps = {}) {
31070
31708
  const out = new Output({ sink: deps.sink, noColor: deps.noColor });
31071
31709
  const config2 = (deps.loadConfigFn ?? loadConfig)();
@@ -31079,7 +31717,20 @@ async function runContext(args, deps = {}) {
31079
31717
  out.error(`Workspace "${slug}" not found. Run \`plinth login --workspace ${slug}\` first.`);
31080
31718
  return { exitCode: 1 };
31081
31719
  }
31720
+ let observation = null;
31721
+ if (args.observed !== undefined && args.observed !== "") {
31722
+ let mirrorDir;
31723
+ try {
31724
+ mirrorDir = workspaceMirrorPath(slug);
31725
+ } catch {
31726
+ mirrorDir = undefined;
31727
+ }
31728
+ observation = (deps.buildObservationFn ?? buildObservation)(args.observed, {
31729
+ workspaceMirrorDir: mirrorDir
31730
+ });
31731
+ }
31082
31732
  const account = buildContextAccount(slug, {
31733
+ observation,
31083
31734
  hook: deps.hook ?? (() => defaultHook(slug)),
31084
31735
  listMemberCommands: deps.listMemberCommands,
31085
31736
  readStoreModes: deps.readStoreModes ?? readMemoryStoreModesNoWrite
@@ -31110,6 +31761,11 @@ var contextCommand = defineCommand({
31110
31761
  description: "Emit the account as JSON",
31111
31762
  required: false
31112
31763
  },
31764
+ observed: {
31765
+ type: "string",
31766
+ description: "Path to ONE session transcript (.jsonl) to measure recorded delivery and usage from. Explicit: nothing is discovered or crawled, and no token is attributed to any file",
31767
+ required: false
31768
+ },
31113
31769
  "no-color": {
31114
31770
  type: "boolean",
31115
31771
  description: "Disable ANSI colour output",
@@ -31117,7 +31773,7 @@ var contextCommand = defineCommand({
31117
31773
  }
31118
31774
  },
31119
31775
  async run({ args }) {
31120
- const result = await runContext({ workspace: args.workspace, json: args.json === true }, { noColor: noColorFromArgs(args) });
31776
+ const result = await runContext({ workspace: args.workspace, json: args.json === true, observed: args.observed }, { noColor: noColorFromArgs(args) });
31121
31777
  if (result.exitCode !== 0)
31122
31778
  process.exit(result.exitCode);
31123
31779
  }
@@ -31484,14 +32140,14 @@ var loginCommand = defineCommand({
31484
32140
  // src/lib/memory-gate/log.ts
31485
32141
  import {
31486
32142
  appendFileSync,
31487
- closeSync as closeSync2,
32143
+ closeSync as closeSync3,
31488
32144
  mkdirSync as mkdirSync8,
31489
- openSync as openSync2,
32145
+ openSync as openSync3,
31490
32146
  readFileSync as readFileSync12,
31491
- readSync,
32147
+ readSync as readSync2,
31492
32148
  statSync as statSync3
31493
32149
  } from "node:fs";
31494
- import { join as join9 } from "node:path";
32150
+ import { join as join10 } from "node:path";
31495
32151
 
31496
32152
  // src/lib/sessions/registry.ts
31497
32153
  import {
@@ -31503,7 +32159,7 @@ import {
31503
32159
  unlinkSync as unlinkSync6,
31504
32160
  writeFileSync as writeFileSync6
31505
32161
  } from "node:fs";
31506
- import { basename as basename2, dirname as dirname6, join as join8 } from "node:path";
32162
+ import { basename as basename3, dirname as dirname7, join as join9 } from "node:path";
31507
32163
  var SessionRecordSchema = exports_external.object({
31508
32164
  version: exports_external.literal(1),
31509
32165
  session_id: exports_external.string().min(1),
@@ -31524,13 +32180,13 @@ function sessionsDir(workspaceSlug) {
31524
32180
  if (!isSafeSegment(workspaceSlug)) {
31525
32181
  throw new Error(`Refusing unsafe workspace slug: ${workspaceSlug}`);
31526
32182
  }
31527
- return join8(plinthHome(), workspaceSlug, "sessions");
32183
+ return join9(plinthHome(), workspaceSlug, "sessions");
31528
32184
  }
31529
32185
  function sessionRecordPath(workspaceSlug, sessionId) {
31530
32186
  if (!isSafeSegment(sessionId)) {
31531
32187
  throw new Error(`Refusing unsafe session id: ${sessionId}`);
31532
32188
  }
31533
- return join8(sessionsDir(workspaceSlug), `${sessionId}.json`);
32189
+ return join9(sessionsDir(workspaceSlug), `${sessionId}.json`);
31534
32190
  }
31535
32191
  function registerSession(input) {
31536
32192
  const startTime = (input.startTimeFn ?? readPidStartTime)(input.pid);
@@ -31553,7 +32209,7 @@ function registerSession(input) {
31553
32209
  }
31554
32210
  var tmpCounter = 0;
31555
32211
  function writeRecordAtomic(target, record2) {
31556
- const dir = dirname6(target);
32212
+ const dir = dirname7(target);
31557
32213
  mkdirSync7(dir, { recursive: true, mode: 448 });
31558
32214
  const tmp = `${target}.${process.pid}.${tmpCounter++}.tmp`;
31559
32215
  sweepDeadTmpFiles(dir, target);
@@ -31569,7 +32225,7 @@ function writeRecordAtomic(target, record2) {
31569
32225
  }
31570
32226
  }
31571
32227
  function sweepDeadTmpFiles(dir, target) {
31572
- const prefix = `${basename2(target)}.`;
32228
+ const prefix = `${basename3(target)}.`;
31573
32229
  let names;
31574
32230
  try {
31575
32231
  names = readdirSync5(dir);
@@ -31586,7 +32242,7 @@ function sweepDeadTmpFiles(dir, target) {
31586
32242
  if (pid === process.pid || isPidAlive(pid))
31587
32243
  continue;
31588
32244
  try {
31589
- unlinkSync6(join8(dir, name));
32245
+ unlinkSync6(join9(dir, name));
31590
32246
  } catch {}
31591
32247
  }
31592
32248
  }
@@ -31651,7 +32307,7 @@ function listSessions(workspaceSlug, deps = {}) {
31651
32307
  for (const name of names) {
31652
32308
  if (!name.endsWith(".json"))
31653
32309
  continue;
31654
- const path3 = join8(sessionsDir(workspaceSlug), name);
32310
+ const path3 = join9(sessionsDir(workspaceSlug), name);
31655
32311
  const record2 = readSessionRecord(path3);
31656
32312
  if (!record2) {
31657
32313
  continue;
@@ -31710,10 +32366,10 @@ function memoryGateDir(workspaceSlug) {
31710
32366
  if (!isSafeSegment(workspaceSlug)) {
31711
32367
  throw new Error(`Refusing unsafe workspace slug: ${workspaceSlug}`);
31712
32368
  }
31713
- return join9(plinthHome(), "_memory_gate", workspaceSlug);
32369
+ return join10(plinthHome(), "_memory_gate", workspaceSlug);
31714
32370
  }
31715
32371
  function memoryGateLogPath(workspaceSlug) {
31716
- return join9(memoryGateDir(workspaceSlug), "log.jsonl");
32372
+ return join10(memoryGateDir(workspaceSlug), "log.jsonl");
31717
32373
  }
31718
32374
  function buildDecisionRecord(input) {
31719
32375
  const final = input.decision === "accept" ? input.proposed : input.decision === "reject" ? null : input.final ?? null;
@@ -31746,13 +32402,13 @@ function endsMidLine(path3) {
31746
32402
  }
31747
32403
  if (size === 0)
31748
32404
  return false;
31749
- const fd = openSync2(path3, "r");
32405
+ const fd = openSync3(path3, "r");
31750
32406
  try {
31751
32407
  const last = Buffer.alloc(1);
31752
- readSync(fd, last, 0, 1, size - 1);
32408
+ readSync2(fd, last, 0, 1, size - 1);
31753
32409
  return last[0] !== 10;
31754
32410
  } finally {
31755
- closeSync2(fd);
32411
+ closeSync3(fd);
31756
32412
  }
31757
32413
  }
31758
32414
  function appendMemoryGateRecord(workspaceSlug, record2) {
@@ -33017,10 +33673,10 @@ import { existsSync as existsSync9, readFileSync as readFileSync26, statSync as
33017
33673
 
33018
33674
  // src/lib/daemon-log.ts
33019
33675
  import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync9, renameSync as renameSync7, statSync as statSync4 } from "node:fs";
33020
- import { dirname as dirname7, join as join10 } from "node:path";
33676
+ import { dirname as dirname8, join as join11 } from "node:path";
33021
33677
  var DEFAULT_DAEMON_LOG_MAX_BYTES = 5000000;
33022
33678
  function daemonLogPath() {
33023
- return join10(plinthHome(), "daemon.log");
33679
+ return join11(plinthHome(), "daemon.log");
33024
33680
  }
33025
33681
  function daemonLogMaxBytes() {
33026
33682
  const raw = process.env.PLINTH_DAEMON_LOG_MAX_BYTES;
@@ -33042,7 +33698,7 @@ class DaemonLog {
33042
33698
  this.now = opts.now ?? (() => new Date);
33043
33699
  this.maxBytes = opts.maxBytes ?? daemonLogMaxBytes();
33044
33700
  try {
33045
- mkdirSync9(dirname7(this.path), { recursive: true });
33701
+ mkdirSync9(dirname8(this.path), { recursive: true });
33046
33702
  } catch {}
33047
33703
  try {
33048
33704
  this.bytesWritten = statSync4(this.path).size;
@@ -33081,7 +33737,7 @@ class DaemonLog {
33081
33737
  // src/lib/destructive-gate.ts
33082
33738
  var import_gray_matter7 = __toESM(require_gray_matter(), 1);
33083
33739
  import { readFileSync as readFileSync14, statSync as statSync5 } from "node:fs";
33084
- import { basename as basename3 } from "node:path";
33740
+ import { basename as basename4 } from "node:path";
33085
33741
  var GUTTING_RATIO_DEFAULT = 0.5;
33086
33742
  var GUTTING_MIN_PRIOR_BYTES = 200;
33087
33743
  function envFloat(name, def) {
@@ -33146,7 +33802,7 @@ function classifyDestructive(event, entityType, state, deps = {}) {
33146
33802
  return null;
33147
33803
  }
33148
33804
  const liveInode = statInode(event.absolutePath);
33149
- const slug = basename3(event.absolutePath, ".md");
33805
+ const slug = basename4(event.absolutePath, ".md");
33150
33806
  const entry2 = (liveInode !== undefined ? getEntryByInode(state, entityType, liveInode) : undefined) ?? getEntryBySlug(state, entityType, slug);
33151
33807
  if (!entry2)
33152
33808
  return null;
@@ -33261,18 +33917,18 @@ import { readFileSync as readFileSync18 } from "node:fs";
33261
33917
 
33262
33918
  // src/lib/conflicts.ts
33263
33919
  import { mkdirSync as mkdirSync10, readdirSync as readdirSync6, statSync as statSync6, writeFileSync as writeFileSync7 } from "node:fs";
33264
- import { dirname as dirname8, join as join11 } from "node:path";
33920
+ import { dirname as dirname9, join as join12 } from "node:path";
33265
33921
  function conflictsRoot(workspaceSlug) {
33266
- return join11(plinthHome(), "_conflicts", workspaceSlug);
33922
+ return join12(plinthHome(), "_conflicts", workspaceSlug);
33267
33923
  }
33268
33924
  function conflictFilePath(args) {
33269
33925
  const { workspaceSlug, entityType, entitySlug, timestamp, side } = args;
33270
33926
  const iso = timestamp.toISOString().replace(/[:.]/g, "-");
33271
- return join11(conflictsRoot(workspaceSlug), `${entityType}.${entitySlug}.${iso}.${side}.md`);
33927
+ return join12(conflictsRoot(workspaceSlug), `${entityType}.${entitySlug}.${iso}.${side}.md`);
33272
33928
  }
33273
33929
  function stashConflict(args) {
33274
33930
  const target = conflictFilePath(args);
33275
- mkdirSync10(dirname8(target), { recursive: true, mode: 448 });
33931
+ mkdirSync10(dirname9(target), { recursive: true, mode: 448 });
33276
33932
  writeFileSync7(target, args.contents, { mode: 384 });
33277
33933
  return target;
33278
33934
  }
@@ -33280,11 +33936,11 @@ function fileConflictPath(args) {
33280
33936
  const { workspaceSlug, relPath, timestamp, side } = args;
33281
33937
  const iso = timestamp.toISOString().replace(/[:.]/g, "-");
33282
33938
  const safe = relPath.replace(/[/\\]/g, "__");
33283
- return join11(conflictsRoot(workspaceSlug), `files.${safe}.${iso}.${side}`);
33939
+ return join12(conflictsRoot(workspaceSlug), `files.${safe}.${iso}.${side}`);
33284
33940
  }
33285
33941
  function stashFileConflict(args) {
33286
33942
  const target = fileConflictPath(args);
33287
- mkdirSync10(dirname8(target), { recursive: true, mode: 448 });
33943
+ mkdirSync10(dirname9(target), { recursive: true, mode: 448 });
33288
33944
  writeFileSync7(target, args.bytes, { mode: 384 });
33289
33945
  return target;
33290
33946
  }
@@ -33317,7 +33973,7 @@ function listConflictStashes(workspaceSlug) {
33317
33973
  }
33318
33974
  const out = [];
33319
33975
  for (const file2 of names) {
33320
- const absPath = join11(dir, file2);
33976
+ const absPath = join12(dir, file2);
33321
33977
  let st;
33322
33978
  try {
33323
33979
  st = statSync6(absPath);
@@ -33346,9 +34002,9 @@ function listConflictStashes(workspaceSlug) {
33346
34002
  import { readFileSync as readFileSync15, statSync as statSync7 } from "node:fs";
33347
34003
 
33348
34004
  // src/lib/files/content-hash.ts
33349
- import { createHash as createHash2 } from "node:crypto";
34005
+ import { createHash as createHash3 } from "node:crypto";
33350
34006
  function sha256Bytes(bytes) {
33351
- return createHash2("sha256").update(bytes).digest("hex");
34007
+ return createHash3("sha256").update(bytes).digest("hex");
33352
34008
  }
33353
34009
 
33354
34010
  // src/lib/files/mime.ts
@@ -33669,7 +34325,7 @@ class PerIdMutex {
33669
34325
  // src/lib/push.ts
33670
34326
  var import_gray_matter10 = __toESM(require_gray_matter(), 1);
33671
34327
  import { readFileSync as readFileSync17, statSync as statSync8 } from "node:fs";
33672
- import { basename as basename4, relative as relative5 } from "node:path";
34328
+ import { basename as basename5, relative as relative5 } from "node:path";
33673
34329
 
33674
34330
  // src/lib/frontmatter-id.ts
33675
34331
  var import_gray_matter8 = __toESM(require_gray_matter(), 1);
@@ -34150,7 +34806,7 @@ async function pushFile(args) {
34150
34806
  const rel = relative5(workspaceMirrorPath(workspaceSlug), absolutePath);
34151
34807
  parsedSlug = strategy.parseMirrorPath(rel)?.slug ?? null;
34152
34808
  } catch {}
34153
- const slugFromPath = parsedSlug ?? basename4(absolutePath, ".md");
34809
+ const slugFromPath = parsedSlug ?? basename5(absolutePath, ".md");
34154
34810
  const slug = identity === "path" ? slugFromPath : slugFromFm ?? slugFromPath;
34155
34811
  if (!slug) {
34156
34812
  return {
@@ -34239,9 +34895,9 @@ async function reconcileContextDocConflict(args) {
34239
34895
  let fileSlug;
34240
34896
  try {
34241
34897
  const rel = relative5(workspaceMirrorPath(workspaceSlug), absolutePath);
34242
- fileSlug = strategy.parseMirrorPath(rel)?.slug ?? basename4(absolutePath, ".md");
34898
+ fileSlug = strategy.parseMirrorPath(rel)?.slug ?? basename5(absolutePath, ".md");
34243
34899
  } catch {
34244
- fileSlug = basename4(absolutePath, ".md");
34900
+ fileSlug = basename5(absolutePath, ".md");
34245
34901
  }
34246
34902
  if (fileSlug !== existingSlug) {
34247
34903
  const stashPath = stashConflict({
@@ -34997,7 +35653,7 @@ async function runPushDelete(args) {
34997
35653
  const rel = relative5(workspaceMirrorPath(args.workspaceSlug), args.absolutePath);
34998
35654
  parsedSlug = strategy.parseMirrorPath(rel)?.slug ?? null;
34999
35655
  } catch {}
35000
- const lookupSlug = parsedSlug ?? basename4(args.absolutePath, ".md");
35656
+ const lookupSlug = parsedSlug ?? basename5(args.absolutePath, ".md");
35001
35657
  const entry2 = getEntryBySlug(args.state, strategy.type, lookupSlug);
35002
35658
  if (entry2) {
35003
35659
  id = entry2.id;
@@ -35096,9 +35752,9 @@ async function pushRename(args) {
35096
35752
  let toSlug;
35097
35753
  try {
35098
35754
  const rel = relative5(workspaceMirrorPath(workspaceSlug), toPath);
35099
- toSlug = strategy.parseMirrorPath(rel)?.slug ?? basename4(toPath, ".md");
35755
+ toSlug = strategy.parseMirrorPath(rel)?.slug ?? basename5(toPath, ".md");
35100
35756
  } catch {
35101
- toSlug = basename4(toPath, ".md");
35757
+ toSlug = basename5(toPath, ".md");
35102
35758
  }
35103
35759
  return mutex.run(id, async () => {
35104
35760
  const live = getEntry(state, entityType, id);
@@ -35430,7 +36086,7 @@ function opPath(workspaceSlug, op) {
35430
36086
  }
35431
36087
 
35432
36088
  // src/lib/files/classify.ts
35433
- import { relative as relative6, sep as sep4 } from "node:path";
36089
+ import { relative as relative6, sep as sep5 } from "node:path";
35434
36090
  var FILES_SUBTREE = "files";
35435
36091
  function classifyFilesPath(args) {
35436
36092
  let root;
@@ -35440,20 +36096,20 @@ function classifyFilesPath(args) {
35440
36096
  return null;
35441
36097
  }
35442
36098
  const rel = relative6(root, args.absolutePath);
35443
- if (rel.startsWith("..") || rel.startsWith(sep4))
36099
+ if (rel.startsWith("..") || rel.startsWith(sep5))
35444
36100
  return null;
35445
- const prefix = FILES_SUBTREE + sep4;
36101
+ const prefix = FILES_SUBTREE + sep5;
35446
36102
  if (!rel.startsWith(prefix))
35447
36103
  return null;
35448
36104
  const sub = rel.slice(prefix.length);
35449
36105
  if (sub.length === 0)
35450
36106
  return null;
35451
- const posix = sep4 === "/" ? sub : sub.split(sep4).join("/");
36107
+ const posix = sep5 === "/" ? sub : sub.split(sep5).join("/");
35452
36108
  return validateFilesRelPath(posix) ? { relPath: posix } : null;
35453
36109
  }
35454
36110
 
35455
36111
  // src/lib/memory-facts/sync.ts
35456
- import { isAbsolute as isAbsolute2, relative as relative7, sep as sep5 } from "node:path";
36112
+ import { isAbsolute as isAbsolute2, relative as relative7, sep as sep6 } from "node:path";
35457
36113
 
35458
36114
  // src/lib/memory-facts/api.ts
35459
36115
  var FactCommonSchema = exports_external.object({
@@ -35547,6 +36203,10 @@ function isGeneratedMemoryStash(label, deps) {
35547
36203
 
35548
36204
  // src/lib/memory-facts/refuse.ts
35549
36205
  function refuseGeneratedMemoryEdit(args) {
36206
+ if (args.localContent === args.canonicalBody) {
36207
+ args.writeCanonical(args.canonicalBody);
36208
+ return { state: args.state, stashPath: null };
36209
+ }
35550
36210
  const stashPath = stashConflict({
35551
36211
  workspaceSlug: args.workspaceSlug,
35552
36212
  entityType: args.conflictEntity,
@@ -35770,7 +36430,7 @@ function classifyMemoryFactPath(args) {
35770
36430
  const rel = relative7(root, args.absolutePath);
35771
36431
  if (rel === "" || rel.startsWith("..") || isAbsolute2(rel))
35772
36432
  return null;
35773
- const mirrorRel = `${MEMORY_FACTS_DIR}/${rel.split(sep5).join("/")}`;
36433
+ const mirrorRel = `${MEMORY_FACTS_DIR}/${rel.split(sep6).join("/")}`;
35774
36434
  return { relPath: mirrorRel, fact: parseMemoryFactRelPath(mirrorRel) };
35775
36435
  }
35776
36436
  function classifyMemoryFactEvent(args) {
@@ -35929,7 +36589,7 @@ class FileDestructiveGate {
35929
36589
  import { readFileSync as readFileSync19, statSync as statSync10 } from "node:fs";
35930
36590
 
35931
36591
  // src/lib/unsynced.ts
35932
- import { join as join12, relative as relative8 } from "node:path";
36592
+ import { join as join13, relative as relative8 } from "node:path";
35933
36593
  var RECORDABLE_REASONS = new Set([
35934
36594
  "rate_limit",
35935
36595
  "server",
@@ -35991,7 +36651,7 @@ async function drainUnsyncedOps(args) {
35991
36651
  attempted += 1;
35992
36652
  try {
35993
36653
  if (op.target === "entity") {
35994
- const absolutePath = join12(workspaceMirrorPath(workspaceSlug), op.path);
36654
+ const absolutePath = join13(workspaceMirrorPath(workspaceSlug), op.path);
35995
36655
  const classified = classifyMirrorPath({ workspaceSlug, absolutePath });
35996
36656
  if (!classified) {
35997
36657
  clear("entity", op.path);
@@ -36236,10 +36896,10 @@ class ReaddirpStream extends Readable {
36236
36896
  }
36237
36897
  async _formatEntry(dirent, path5) {
36238
36898
  let entry2;
36239
- const basename5 = this._isDirent ? dirent.name : dirent;
36899
+ const basename6 = this._isDirent ? dirent.name : dirent;
36240
36900
  try {
36241
- const fullPath = presolve(pjoin(path5, basename5));
36242
- entry2 = { path: prelative(this._root, fullPath), fullPath, basename: basename5 };
36901
+ const fullPath = presolve(pjoin(path5, basename6));
36902
+ entry2 = { path: prelative(this._root, fullPath), fullPath, basename: basename6 };
36243
36903
  entry2[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
36244
36904
  } catch (err) {
36245
36905
  this._onError(err);
@@ -36766,9 +37426,9 @@ class NodeFsHandler {
36766
37426
  _watchWithNodeFs(path5, listener) {
36767
37427
  const opts = this.fsw.options;
36768
37428
  const directory = sp.dirname(path5);
36769
- const basename6 = sp.basename(path5);
37429
+ const basename7 = sp.basename(path5);
36770
37430
  const parent = this.fsw._getWatchedDir(directory);
36771
- parent.add(basename6);
37431
+ parent.add(basename7);
36772
37432
  const absolutePath = sp.resolve(path5);
36773
37433
  const options2 = {
36774
37434
  persistent: opts.persistent
@@ -36778,7 +37438,7 @@ class NodeFsHandler {
36778
37438
  let closer;
36779
37439
  if (opts.usePolling) {
36780
37440
  const enableBin = opts.interval !== opts.binaryInterval;
36781
- options2.interval = enableBin && isBinaryPath(basename6) ? opts.binaryInterval : opts.interval;
37441
+ options2.interval = enableBin && isBinaryPath(basename7) ? opts.binaryInterval : opts.interval;
36782
37442
  closer = setFsWatchFileListener(path5, absolutePath, options2, {
36783
37443
  listener,
36784
37444
  rawEmitter: this.fsw._emitRaw
@@ -36796,11 +37456,11 @@ class NodeFsHandler {
36796
37456
  if (this.fsw.closed) {
36797
37457
  return;
36798
37458
  }
36799
- const dirname10 = sp.dirname(file2);
36800
- const basename6 = sp.basename(file2);
36801
- const parent = this.fsw._getWatchedDir(dirname10);
37459
+ const dirname11 = sp.dirname(file2);
37460
+ const basename7 = sp.basename(file2);
37461
+ const parent = this.fsw._getWatchedDir(dirname11);
36802
37462
  let prevStats = stats;
36803
- if (parent.has(basename6))
37463
+ if (parent.has(basename7))
36804
37464
  return;
36805
37465
  const listener = async (path5, newStats) => {
36806
37466
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file2, 5))
@@ -36825,9 +37485,9 @@ class NodeFsHandler {
36825
37485
  prevStats = newStats2;
36826
37486
  }
36827
37487
  } catch (error52) {
36828
- this.fsw._remove(dirname10, basename6);
37488
+ this.fsw._remove(dirname11, basename7);
36829
37489
  }
36830
- } else if (parent.has(basename6)) {
37490
+ } else if (parent.has(basename7)) {
36831
37491
  const at = newStats.atimeMs;
36832
37492
  const mt = newStats.mtimeMs;
36833
37493
  if (!at || at <= mt || mt !== prevStats.mtimeMs) {
@@ -36914,7 +37574,7 @@ class NodeFsHandler {
36914
37574
  this._addToNodeFs(path5, initialAdd, wh, depth + 1);
36915
37575
  }
36916
37576
  }).on(EV.ERROR, this._boundHandleError);
36917
- return new Promise((resolve4, reject) => {
37577
+ return new Promise((resolve5, reject) => {
36918
37578
  if (!stream)
36919
37579
  return reject();
36920
37580
  stream.once(STR_END, () => {
@@ -36923,7 +37583,7 @@ class NodeFsHandler {
36923
37583
  return;
36924
37584
  }
36925
37585
  const wasThrottled = throttler ? throttler.clear() : false;
36926
- resolve4(undefined);
37586
+ resolve5(undefined);
36927
37587
  previous.getChildren().filter((item) => {
36928
37588
  return item !== directory && !current.has(item);
36929
37589
  }).forEach((item) => {
@@ -37682,7 +38342,7 @@ var chokidar_default = { watch, FSWatcher };
37682
38342
 
37683
38343
  // src/lib/watcher.ts
37684
38344
  import { statSync as statSync9 } from "node:fs";
37685
- import { sep as sep6 } from "node:path";
38345
+ import { sep as sep7 } from "node:path";
37686
38346
 
37687
38347
  // src/lib/rename-classifier.ts
37688
38348
  class RenameClassifier {
@@ -37813,7 +38473,7 @@ function watcherIgnoreMatcher(workspaceRoot) {
37813
38473
  return (absolutePath) => patterns.some((re) => re.test(absolutePath));
37814
38474
  }
37815
38475
  function escSep() {
37816
- return sep6 === "/" ? "/" : "\\\\";
38476
+ return sep7 === "/" ? "/" : "\\\\";
37817
38477
  }
37818
38478
 
37819
38479
  class DebounceMap {
@@ -38398,7 +39058,7 @@ async function pushArtistMemory(args) {
38398
39058
  };
38399
39059
  return {
38400
39060
  state: persistEntry2(refused.state, stamped),
38401
- outcome: { kind: "generated_refused", slug, stashPath: refused.stashPath }
39061
+ outcome: refused.stashPath === null ? { kind: "noop", slug } : { kind: "generated_refused", slug, stashPath: refused.stashPath }
38402
39062
  };
38403
39063
  }
38404
39064
  const acked = entry2.memory_hash;
@@ -40829,7 +41489,7 @@ async function pushWorkspaceMemory(args) {
40829
41489
  });
40830
41490
  return {
40831
41491
  state: next2,
40832
- outcome: { kind: "generated_refused", stashPath: refused.stashPath }
41492
+ outcome: refused.stashPath === null ? { kind: "noop" } : { kind: "generated_refused", stashPath: refused.stashPath }
40833
41493
  };
40834
41494
  }
40835
41495
  const gate = applySecretGate({
@@ -40897,7 +41557,7 @@ async function pushWorkspaceMemory(args) {
40897
41557
  });
40898
41558
  return {
40899
41559
  state: next2,
40900
- outcome: { kind: "generated_refused", stashPath: refused.stashPath }
41560
+ outcome: refused.stashPath === null ? { kind: "noop" } : { kind: "generated_refused", stashPath: refused.stashPath }
40901
41561
  };
40902
41562
  }
40903
41563
  {
@@ -40946,7 +41606,7 @@ async function pushWorkspaceMemory(args) {
40946
41606
  });
40947
41607
  return {
40948
41608
  state: next2,
40949
- outcome: { kind: "generated_refused", stashPath: refused.stashPath }
41609
+ outcome: refused.stashPath === null ? { kind: "noop" } : { kind: "generated_refused", stashPath: refused.stashPath }
40950
41610
  };
40951
41611
  }
40952
41612
  }
@@ -41221,7 +41881,7 @@ async function pushSingleton(descriptor, args) {
41221
41881
  const next2 = persist2(descriptor, refused.state, ackedFrom(cloud, stableHash(cloud.body_md)));
41222
41882
  return {
41223
41883
  state: next2,
41224
- outcome: { kind: "generated_refused", stashPath: refused.stashPath }
41884
+ outcome: refused.stashPath === null ? { kind: "noop" } : { kind: "generated_refused", stashPath: refused.stashPath }
41225
41885
  };
41226
41886
  }
41227
41887
  let gated = state;
@@ -41284,7 +41944,7 @@ async function pushSingleton(descriptor, args) {
41284
41944
  const next2 = persist2(descriptor, refused.state, ackedFrom(cloud, stableHash(cloud.body_md)));
41285
41945
  return {
41286
41946
  state: next2,
41287
- outcome: { kind: "generated_refused", stashPath: refused.stashPath }
41947
+ outcome: refused.stashPath === null ? { kind: "noop" } : { kind: "generated_refused", stashPath: refused.stashPath }
41288
41948
  };
41289
41949
  }
41290
41950
  {
@@ -41325,7 +41985,7 @@ async function pushSingleton(descriptor, args) {
41325
41985
  const next2 = persist2(descriptor, refused.state, ackedFrom(cloud, stableHash(cloud.body_md)));
41326
41986
  return {
41327
41987
  state: next2,
41328
- outcome: { kind: "generated_refused", stashPath: refused.stashPath }
41988
+ outcome: refused.stashPath === null ? { kind: "noop" } : { kind: "generated_refused", stashPath: refused.stashPath }
41329
41989
  };
41330
41990
  }
41331
41991
  }
@@ -41470,7 +42130,7 @@ class Semaphore {
41470
42130
  this.active += 1;
41471
42131
  return;
41472
42132
  }
41473
- await new Promise((resolve5) => this.waiters.push(resolve5));
42133
+ await new Promise((resolve6) => this.waiters.push(resolve6));
41474
42134
  }
41475
42135
  release() {
41476
42136
  const next = this.waiters.shift();
@@ -41537,11 +42197,11 @@ import {
41537
42197
  statSync as statSync16,
41538
42198
  unlinkSync as unlinkSync8
41539
42199
  } from "node:fs";
41540
- import { join as join16 } from "node:path";
42200
+ import { join as join17 } from "node:path";
41541
42201
 
41542
42202
  // src/lib/conflicts-view.ts
41543
42203
  import { existsSync as existsSync6 } from "node:fs";
41544
- import { join as join15 } from "node:path";
42204
+ import { join as join16 } from "node:path";
41545
42205
  var NO_GENERATED_MEMORY = {
41546
42206
  artistMemoryGenerated: () => false,
41547
42207
  workspaceMemoryGenerated: () => false,
@@ -41587,7 +42247,7 @@ function resolveConflictRows(workspaceSlug, stashes, generatedMemory = NO_GENERA
41587
42247
  if (validateFilesRelPath(rel) === null) {
41588
42248
  return { kind: "unsafe-path", stash };
41589
42249
  }
41590
- const abs = join15(root, "files", rel);
42250
+ const abs = join16(root, "files", rel);
41591
42251
  if (hasSymlinkedComponent(workspaceSlug, abs)) {
41592
42252
  return { kind: "unsafe-path", stash };
41593
42253
  }
@@ -41720,7 +42380,7 @@ function refreshConflictsView(workspaceSlug) {
41720
42380
  import { existsSync as existsSync7, readFileSync as readFileSync23, statSync as statSync14 } from "node:fs";
41721
42381
 
41722
42382
  // src/lib/files/extracted-text.ts
41723
- import { createHash as createHash3 } from "node:crypto";
42383
+ import { createHash as createHash4 } from "node:crypto";
41724
42384
  var DERIVED_TEXT_VERSION = 2;
41725
42385
  function yamlString3(value) {
41726
42386
  return JSON.stringify(value);
@@ -41794,7 +42454,7 @@ ${doc2.text}
41794
42454
  `;
41795
42455
  }
41796
42456
  function extractedTextHash(rendered) {
41797
- return createHash3("sha256").update(rendered, "utf8").digest("hex");
42457
+ return createHash4("sha256").update(rendered, "utf8").digest("hex");
41798
42458
  }
41799
42459
 
41800
42460
  // src/lib/files/pull.ts
@@ -42413,7 +43073,7 @@ function hasExistingContent(workspacePath) {
42413
43073
  if (!e.isDirectory())
42414
43074
  return true;
42415
43075
  try {
42416
- return readdirSync7(join16(workspacePath, e.name)).length > 0;
43076
+ return readdirSync7(join17(workspacePath, e.name)).length > 0;
42417
43077
  } catch {
42418
43078
  return true;
42419
43079
  }
@@ -44592,12 +45252,12 @@ async function runStart(workspaceSlug, deps = {}) {
44592
45252
  try {
44593
45253
  await Promise.race([
44594
45254
  watcher.drainPending().then(() => Promise.all([gate.drain(), fileGate.drain()])),
44595
- new Promise((resolve5) => setTimeout(() => resolve5(-1), SHUTDOWN_DRAIN_TIMEOUT_MS))
45255
+ new Promise((resolve6) => setTimeout(() => resolve6(-1), SHUTDOWN_DRAIN_TIMEOUT_MS))
44596
45256
  ]);
44597
45257
  } finally {
44598
45258
  await Promise.race([
44599
45259
  watcher.stop(),
44600
- new Promise((resolve5) => setTimeout(resolve5, SHUTDOWN_DRAIN_TIMEOUT_MS))
45260
+ new Promise((resolve6) => setTimeout(resolve6, SHUTDOWN_DRAIN_TIMEOUT_MS))
44601
45261
  ]);
44602
45262
  clearDaemonPid(slug);
44603
45263
  releaseDaemonLock(lockHandle);
@@ -45153,11 +45813,11 @@ function assessContextWalls(workspaceSlug, deps = {}) {
45153
45813
  // src/lib/build-stamp.ts
45154
45814
  import { execFileSync as execFileSync4 } from "node:child_process";
45155
45815
  import { existsSync as existsSync10, mkdirSync as mkdirSync11, readFileSync as readFileSync27, writeFileSync as writeFileSync8 } from "node:fs";
45156
- import { dirname as dirname11, join as join17 } from "node:path";
45816
+ import { dirname as dirname12, join as join18 } from "node:path";
45157
45817
  import { fileURLToPath } from "node:url";
45158
45818
  var BUILD_STAMP_FILENAME = "build-stamp.json";
45159
45819
  function stampPath(distDir) {
45160
- return join17(distDir, BUILD_STAMP_FILENAME);
45820
+ return join18(distDir, BUILD_STAMP_FILENAME);
45161
45821
  }
45162
45822
  function readHead(repoDir) {
45163
45823
  try {
@@ -45188,9 +45848,9 @@ function readBuildStamp(distDir) {
45188
45848
  function findRepoRoot(fromDir) {
45189
45849
  let dir = fromDir;
45190
45850
  for (;; ) {
45191
- if (existsSync10(join17(dir, ".git")))
45851
+ if (existsSync10(join18(dir, ".git")))
45192
45852
  return dir;
45193
- const parent = dirname11(dir);
45853
+ const parent = dirname12(dir);
45194
45854
  if (parent === dir)
45195
45855
  return null;
45196
45856
  dir = parent;
@@ -45214,7 +45874,7 @@ function checkBuildStaleness(deps = {}) {
45214
45874
  const metaUrl = deps.metaUrl ?? import.meta.url;
45215
45875
  let distDir;
45216
45876
  try {
45217
- distDir = dirname11(fileURLToPath(metaUrl));
45877
+ distDir = dirname12(fileURLToPath(metaUrl));
45218
45878
  } catch {
45219
45879
  return { kind: "unknown" };
45220
45880
  }
@@ -45238,7 +45898,7 @@ function checkBuildStaleness(deps = {}) {
45238
45898
 
45239
45899
  // src/lib/memory-links.ts
45240
45900
  import { readFileSync as readFileSync28 } from "node:fs";
45241
- import { relative as relative15, sep as sep7 } from "node:path";
45901
+ import { relative as relative15, sep as sep8 } from "node:path";
45242
45902
  var MEMORY_FILE_RE = /^(workspace-memory\.md|user-memory\.md|artists\/[^/]+\/memory\.md|memory\/[^/]+\.md|memory\/private\/[^/]+\.md)$/i;
45243
45903
  function scanMemoryLinks(deps) {
45244
45904
  const listFiles = deps.listFiles ?? ((r) => walkSubtreeFiles(r, isVcsInternal));
@@ -45251,7 +45911,7 @@ function scanMemoryLinks(deps) {
45251
45911
  } catch {
45252
45912
  return { scanned: 0, unreadable: [], dead: [] };
45253
45913
  }
45254
- const relPaths = absPaths.map((p) => relative15(root, p).split(sep7).join("/"));
45914
+ const relPaths = absPaths.map((p) => relative15(root, p).split(sep8).join("/"));
45255
45915
  const artists = buildArtistIndex(relPaths, root, (abs) => readFile(abs));
45256
45916
  const dead = [];
45257
45917
  const unreadable = [];
@@ -46317,7 +46977,7 @@ async function callVoiceGate(req) {
46317
46977
  }
46318
46978
 
46319
46979
  // src/lib/voice-gate/attempts.ts
46320
- import { createHash as createHash4 } from "node:crypto";
46980
+ import { createHash as createHash5 } from "node:crypto";
46321
46981
  import {
46322
46982
  mkdirSync as mkdirSync12,
46323
46983
  readFileSync as readFileSync30,
@@ -46325,7 +46985,7 @@ import {
46325
46985
  unlinkSync as unlinkSync9,
46326
46986
  writeFileSync as writeFileSync9
46327
46987
  } from "node:fs";
46328
- import { join as join18 } from "node:path";
46988
+ import { join as join19 } from "node:path";
46329
46989
  var MAX_REGENS = 2;
46330
46990
  var ENTRY_TTL_MS = 24 * 60 * 60 * 1000;
46331
46991
  var AttemptEntrySchema = exports_external.object({
@@ -46338,13 +46998,13 @@ var AttemptsFileSchema = exports_external.object({
46338
46998
  entries: exports_external.record(exports_external.string(), AttemptEntrySchema)
46339
46999
  });
46340
47000
  function attemptsDir(workspaceSlug) {
46341
- return join18(plinthHome(), "_voice_gate", workspaceSlug);
47001
+ return join19(plinthHome(), "_voice_gate", workspaceSlug);
46342
47002
  }
46343
47003
  function attemptsPath(workspaceSlug) {
46344
- return join18(attemptsDir(workspaceSlug), "attempts.json");
47004
+ return join19(attemptsDir(workspaceSlug), "attempts.json");
46345
47005
  }
46346
47006
  function attemptKey(identity) {
46347
- return createHash4("sha256").update(identity, "utf8").digest("hex").slice(0, 32);
47007
+ return createHash5("sha256").update(identity, "utf8").digest("hex").slice(0, 32);
46348
47008
  }
46349
47009
  function emptyFile() {
46350
47010
  return { version: 1, entries: {} };
@@ -46516,7 +47176,7 @@ function denyUngated(detail) {
46516
47176
  // src/lib/voice-gate/payload.ts
46517
47177
  import { readFileSync as readFileSync31, statSync as statSync20 } from "node:fs";
46518
47178
  import { homedir as homedir2 } from "node:os";
46519
- import { isAbsolute as isAbsolute4, resolve as resolve5 } from "node:path";
47179
+ import { isAbsolute as isAbsolute4, resolve as resolve6 } from "node:path";
46520
47180
  var MAX_BODY_BYTES = 256 * 1024;
46521
47181
  var HELPER_BASENAME = "push_gmail_draft.py";
46522
47182
  var DRAFT_FLAGS = ["--to", "--body-file", "--body-stdin"];
@@ -46710,13 +47370,13 @@ function applyCd(tokens, state) {
46710
47370
  return { dir: expanded, known: true };
46711
47371
  if (!state.known)
46712
47372
  return state;
46713
- return { dir: resolve5(state.dir, expanded), known: true };
47373
+ return { dir: resolve6(state.dir, expanded), known: true };
46714
47374
  }
46715
47375
  function expandHome(path5) {
46716
47376
  if (path5 === "~")
46717
47377
  return homedir2();
46718
47378
  if (path5.startsWith("~/"))
46719
- return resolve5(homedir2(), path5.slice(2));
47379
+ return resolve6(homedir2(), path5.slice(2));
46720
47380
  return path5;
46721
47381
  }
46722
47382
  function classifyHelperSegment(tokens, dirState, readBodyFile) {
@@ -46742,7 +47402,7 @@ function classifyHelperSegment(tokens, dirState, readBodyFile) {
46742
47402
  unreadable: `the draft push uses a relative \`--body-file\` (${bodyFile}) after a \`cd\` ` + `the voice gate cannot resolve, so it cannot tell which file ships. Pass an ` + `absolute \`--body-file\` path.`
46743
47403
  };
46744
47404
  }
46745
- const resolved = isAbsolute4(expanded) ? expanded : resolve5(dirState.dir, expanded);
47405
+ const resolved = isAbsolute4(expanded) ? expanded : resolve6(dirState.dir, expanded);
46746
47406
  let body;
46747
47407
  try {
46748
47408
  body = readBodyFile(resolved);