@remnic/core 9.3.689 → 9.3.690

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 (158) hide show
  1. package/dist/access-boundary.d.ts +5 -4
  2. package/dist/access-boundary.js +10 -9
  3. package/dist/access-cli.js +86 -22
  4. package/dist/access-cli.js.map +1 -1
  5. package/dist/access-http.d.ts +4 -3
  6. package/dist/access-http.js +13 -12
  7. package/dist/access-mcp.d.ts +11 -3
  8. package/dist/access-mcp.js +12 -11
  9. package/dist/access-operations.d.ts +11 -5
  10. package/dist/access-operations.js +13 -10
  11. package/dist/{access-service-DmCHJ4cH.d.ts → access-service-Dujr3MTm.d.ts} +62 -2
  12. package/dist/access-service.d.ts +4 -3
  13. package/dist/access-service.js +9 -8
  14. package/dist/access-surface-catalog.d.ts +4 -3
  15. package/dist/access-surface-catalog.js +2 -0
  16. package/dist/access-surface-catalog.js.map +1 -1
  17. package/dist/bootstrap.d.ts +3 -2
  18. package/dist/briefing.d.ts +1 -0
  19. package/dist/briefing.js +3 -2
  20. package/dist/buffer.d.ts +1 -0
  21. package/dist/{catalog-COqWZlZ6.d.ts → catalog-CKPtJ114.d.ts} +1 -1
  22. package/dist/causal-consolidation.js +4 -3
  23. package/dist/causal-consolidation.js.map +1 -1
  24. package/dist/{chunk-B4XVLHJA.js → chunk-2N6UNJSX.js} +2 -2
  25. package/dist/{chunk-OWFY6NGQ.js → chunk-46URPRE6.js} +2 -2
  26. package/dist/chunk-46URPRE6.js.map +1 -0
  27. package/dist/{chunk-4N3TFFPH.js → chunk-54PVJDO5.js} +2 -2
  28. package/dist/{chunk-PH3HOKYW.js → chunk-67MMWC74.js} +2 -2
  29. package/dist/{chunk-STOEE37X.js → chunk-BKAMHZYR.js} +2 -2
  30. package/dist/{chunk-JZBFL7RI.js → chunk-CE6CBRCV.js} +429 -2237
  31. package/dist/chunk-CE6CBRCV.js.map +1 -0
  32. package/dist/{chunk-UHUZXWDX.js → chunk-CP2NZQLT.js} +15 -4
  33. package/dist/chunk-CP2NZQLT.js.map +1 -0
  34. package/dist/{chunk-BLIWOONZ.js → chunk-CUNTLEJP.js} +4 -12
  35. package/dist/chunk-CUNTLEJP.js.map +1 -0
  36. package/dist/{chunk-W63OY3J7.js → chunk-CWE74HRG.js} +3 -3
  37. package/dist/{chunk-VX6OBUDW.js → chunk-GR77Z2BM.js} +2 -2
  38. package/dist/{chunk-SAEZIIID.js → chunk-LXIEXSHU.js} +2 -2
  39. package/dist/{chunk-Z2M6YTAJ.js → chunk-NSVXK7M5.js} +33 -4
  40. package/dist/chunk-NSVXK7M5.js.map +1 -0
  41. package/dist/{chunk-UXLZOVCN.js → chunk-OMKUJTVJ.js} +37 -5
  42. package/dist/chunk-OMKUJTVJ.js.map +1 -0
  43. package/dist/{chunk-GS55WYRL.js → chunk-PHZKALOE.js} +2 -2
  44. package/dist/{chunk-6O6A6YUO.js → chunk-RGNEARXW.js} +3 -3
  45. package/dist/{chunk-4FE2K57M.js → chunk-RTFAZOIR.js} +2 -2
  46. package/dist/{chunk-UTYBJR7M.js → chunk-SB6CQTKP.js} +2 -2
  47. package/dist/chunk-SVOZFLIQ.js +16 -0
  48. package/dist/chunk-SVOZFLIQ.js.map +1 -0
  49. package/dist/{chunk-JPETDXED.js → chunk-TYF3D4MS.js} +2 -2
  50. package/dist/{chunk-WIHPNY65.js → chunk-UD5OKH4J.js} +2 -2
  51. package/dist/{chunk-QANVLERJ.js → chunk-UPIBE2DK.js} +2 -2
  52. package/dist/{chunk-RHXFYIHA.js → chunk-WROKD3XC.js} +33 -18
  53. package/dist/chunk-WROKD3XC.js.map +1 -0
  54. package/dist/{chunk-2SNKUSQC.js → chunk-X5J3JZR3.js} +4 -4
  55. package/dist/{chunk-OV4D5T7V.js → chunk-X7RLU5CR.js} +2 -2
  56. package/dist/{chunk-QSQW54U5.js → chunk-XKUKJIOY.js} +30 -7
  57. package/dist/chunk-XKUKJIOY.js.map +1 -0
  58. package/dist/{chunk-XU7363OX.js → chunk-Z7KILAOU.js} +603 -9
  59. package/dist/chunk-Z7KILAOU.js.map +1 -0
  60. package/dist/chunk-ZU7N3S6V.js +2190 -0
  61. package/dist/chunk-ZU7N3S6V.js.map +1 -0
  62. package/dist/{chunk-T422SYM6.js → chunk-ZUDM75KG.js} +5 -5
  63. package/dist/{cli-D8nZ2MPH.d.ts → cli-BkDp6WNi.d.ts} +2 -2
  64. package/dist/cli.d.ts +5 -4
  65. package/dist/cli.js +25 -23
  66. package/dist/compounding/engine.d.ts +1 -0
  67. package/dist/compounding/engine.js +3 -2
  68. package/dist/connectors/codex-materialize-runner.js +3 -2
  69. package/dist/connectors/index.js +3 -2
  70. package/dist/consolidation-provenance-check.d.ts +1 -0
  71. package/dist/consolidation-undo.d.ts +1 -0
  72. package/dist/contradiction/index.d.ts +1 -0
  73. package/dist/conversation-index/backend.js +2 -2
  74. package/dist/entity-retrieval.d.ts +1 -0
  75. package/dist/entity-retrieval.js +3 -2
  76. package/dist/explicit-capture.d.ts +3 -2
  77. package/dist/index.d.ts +6 -5
  78. package/dist/index.js +34 -31
  79. package/dist/index.js.map +1 -1
  80. package/dist/lcm/engine.js +2 -2
  81. package/dist/lcm/index.js +2 -2
  82. package/dist/maintenance/memory-governance.js +3 -2
  83. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -2
  84. package/dist/maintenance/rebuild-memory-projection.js +4 -3
  85. package/dist/mcp-memory-inspector-app.d.ts +4 -3
  86. package/dist/memory-worth-outcomes.d.ts +1 -0
  87. package/dist/namespaces/migrate.d.ts +2 -1
  88. package/dist/namespaces/migrate.js +8 -7
  89. package/dist/namespaces/search.js +4 -4
  90. package/dist/namespaces/storage.d.ts +2 -1
  91. package/dist/namespaces/storage.js +3 -2
  92. package/dist/operator-toolkit.d.ts +1 -0
  93. package/dist/operator-toolkit.js +11 -9
  94. package/dist/{orchestrator-CA6ouzBn.d.ts → orchestrator-B7ixmUkP.d.ts} +145 -1
  95. package/dist/orchestrator.d.ts +3 -2
  96. package/dist/orchestrator.js +18 -16
  97. package/dist/schemas.d.ts +10 -10
  98. package/dist/search/factory.js +3 -3
  99. package/dist/search/index.js +3 -3
  100. package/dist/semantic-consolidation.js +4 -3
  101. package/dist/semantic-rule-promotion.js +3 -2
  102. package/dist/semantic-rule-verifier.js +3 -2
  103. package/dist/storage.d.ts +3 -27
  104. package/dist/storage.js +5 -3
  105. package/dist/structured-attributes.d.ts +29 -0
  106. package/dist/structured-attributes.js +8 -0
  107. package/dist/structured-attributes.js.map +1 -0
  108. package/dist/temporal-supersession.d.ts +1 -0
  109. package/dist/tier-migration.d.ts +1 -0
  110. package/dist/verified-recall.js +3 -2
  111. package/package.json +2 -2
  112. package/src/access-boundary.ts +2 -1
  113. package/src/access-cli.test.ts +40 -0
  114. package/src/access-cli.ts +90 -2
  115. package/src/access-http.ts +35 -6
  116. package/src/access-mcp.ts +34 -0
  117. package/src/access-operations.ts +45 -0
  118. package/src/access-service.ts +60 -0
  119. package/src/access-surface-catalog.test.ts +1 -1
  120. package/src/access-surface-catalog.ts +2 -0
  121. package/src/cli.ts +18 -0
  122. package/src/coding/architecture-card.test.ts +544 -0
  123. package/src/coding/architecture-card.ts +687 -0
  124. package/src/coding/architecture-surfaces.test.ts +579 -0
  125. package/src/coding/architecture-surfaces.ts +457 -0
  126. package/src/maintenance/namespace-maintenance-fanout.test.ts +595 -0
  127. package/src/maintenance/namespace-maintenance-fanout.ts +318 -0
  128. package/src/maintenance/namespace-planner.ts +74 -16
  129. package/src/operator-toolkit.ts +25 -0
  130. package/src/orchestrator.ts +144 -0
  131. package/src/storage.ts +6 -20
  132. package/src/structured-attributes.ts +39 -0
  133. package/dist/chunk-BLIWOONZ.js.map +0 -1
  134. package/dist/chunk-JZBFL7RI.js.map +0 -1
  135. package/dist/chunk-OWFY6NGQ.js.map +0 -1
  136. package/dist/chunk-QSQW54U5.js.map +0 -1
  137. package/dist/chunk-RHXFYIHA.js.map +0 -1
  138. package/dist/chunk-UHUZXWDX.js.map +0 -1
  139. package/dist/chunk-UXLZOVCN.js.map +0 -1
  140. package/dist/chunk-XU7363OX.js.map +0 -1
  141. package/dist/chunk-Z2M6YTAJ.js.map +0 -1
  142. /package/dist/{chunk-B4XVLHJA.js.map → chunk-2N6UNJSX.js.map} +0 -0
  143. /package/dist/{chunk-4N3TFFPH.js.map → chunk-54PVJDO5.js.map} +0 -0
  144. /package/dist/{chunk-PH3HOKYW.js.map → chunk-67MMWC74.js.map} +0 -0
  145. /package/dist/{chunk-STOEE37X.js.map → chunk-BKAMHZYR.js.map} +0 -0
  146. /package/dist/{chunk-W63OY3J7.js.map → chunk-CWE74HRG.js.map} +0 -0
  147. /package/dist/{chunk-VX6OBUDW.js.map → chunk-GR77Z2BM.js.map} +0 -0
  148. /package/dist/{chunk-SAEZIIID.js.map → chunk-LXIEXSHU.js.map} +0 -0
  149. /package/dist/{chunk-GS55WYRL.js.map → chunk-PHZKALOE.js.map} +0 -0
  150. /package/dist/{chunk-6O6A6YUO.js.map → chunk-RGNEARXW.js.map} +0 -0
  151. /package/dist/{chunk-4FE2K57M.js.map → chunk-RTFAZOIR.js.map} +0 -0
  152. /package/dist/{chunk-UTYBJR7M.js.map → chunk-SB6CQTKP.js.map} +0 -0
  153. /package/dist/{chunk-JPETDXED.js.map → chunk-TYF3D4MS.js.map} +0 -0
  154. /package/dist/{chunk-WIHPNY65.js.map → chunk-UD5OKH4J.js.map} +0 -0
  155. /package/dist/{chunk-QANVLERJ.js.map → chunk-UPIBE2DK.js.map} +0 -0
  156. /package/dist/{chunk-2SNKUSQC.js.map → chunk-X5J3JZR3.js.map} +0 -0
  157. /package/dist/{chunk-OV4D5T7V.js.map → chunk-X7RLU5CR.js.map} +0 -0
  158. /package/dist/{chunk-T422SYM6.js.map → chunk-ZUDM75KG.js.map} +0 -0
@@ -58,10 +58,10 @@ import {
58
58
  listMemoryGovernanceRuns,
59
59
  readMemoryGovernanceRunArtifact,
60
60
  runMemoryGovernance
61
- } from "./chunk-4N3TFFPH.js";
61
+ } from "./chunk-54PVJDO5.js";
62
62
  import {
63
63
  namespaceCollectionName
64
- } from "./chunk-SAEZIIID.js";
64
+ } from "./chunk-LXIEXSHU.js";
65
65
  import {
66
66
  namespaceIdentityFromToken
67
67
  } from "./chunk-ZFXCQPNO.js";
@@ -101,10 +101,13 @@ import {
101
101
  buildBriefing,
102
102
  parseBriefingFocus,
103
103
  parseBriefingWindow
104
- } from "./chunk-OV4D5T7V.js";
104
+ } from "./chunk-X7RLU5CR.js";
105
105
  import {
106
106
  parseEntityFile
107
- } from "./chunk-BLIWOONZ.js";
107
+ } from "./chunk-CUNTLEJP.js";
108
+ import {
109
+ stripAttributesSuffix
110
+ } from "./chunk-SVOZFLIQ.js";
108
111
  import {
109
112
  DEFAULT_RECALL_DISCLOSURE,
110
113
  isRecallDisclosure
@@ -123,6 +126,9 @@ import {
123
126
  normalizeProjectionPreview,
124
127
  normalizeProjectionTags
125
128
  } from "./chunk-SCU65EZI.js";
129
+ import {
130
+ createVersion
131
+ } from "./chunk-VF4XKTX3.js";
126
132
  import {
127
133
  exportCapsule
128
134
  } from "./chunk-KQAFEZQX.js";
@@ -149,6 +155,9 @@ import {
149
155
  recallNamespacesForPrincipal,
150
156
  resolvePrincipal
151
157
  } from "./chunk-UZYLX7M6.js";
158
+ import {
159
+ expandTildePath
160
+ } from "./chunk-EYIEWJNI.js";
152
161
  import {
153
162
  log
154
163
  } from "./chunk-NU3CSQ4H.js";
@@ -609,10 +618,550 @@ function raiseInvalidStatus(value, ctx) {
609
618
  );
610
619
  }
611
620
 
621
+ // src/coding/architecture-card.ts
622
+ import { readFile, readdir, lstat } from "fs/promises";
623
+ import path from "path";
624
+ var ARCHITECTURE_CARD_MAX_BYTES = 4096;
625
+ var ARCHITECTURE_CARD_TRUNCATION_MARKER = "\u2026 card truncated to fit size cap \u2026";
626
+ var ARCHITECTURE_CARD_MAX_SUMMARY_BYTES = 1024;
627
+ var KNOWN_MANIFEST_FILES = [
628
+ "package.json",
629
+ "Cargo.toml",
630
+ "go.mod",
631
+ "pyproject.toml",
632
+ "setup.py",
633
+ "pom.xml",
634
+ "build.gradle",
635
+ "build.gradle.kts",
636
+ "Gemfile",
637
+ "composer.json",
638
+ "mix.exs",
639
+ "deno.json"
640
+ ];
641
+ var SCAN_IGNORE_DIRS = /* @__PURE__ */ new Set([
642
+ "node_modules",
643
+ ".git",
644
+ ".svn",
645
+ ".hg",
646
+ "vendor",
647
+ "__pycache__",
648
+ ".venv",
649
+ "venv",
650
+ "env",
651
+ "dist",
652
+ "build",
653
+ "target",
654
+ "out",
655
+ ".next",
656
+ ".nuxt",
657
+ "coverage",
658
+ ".cache",
659
+ ".turbo",
660
+ ".idea",
661
+ ".vscode"
662
+ ]);
663
+ var ARCHITECTURE_CARD_SUMMARY_SYSTEM_PROMPT = `You write a concise overview for a repository architecture card.
664
+ Given the deterministic card (languages, manifests, entry points), produce a 3-5 sentence plain-text overview naming the dominant language, the primary entry point, and the project's shape.
665
+ Rules:
666
+ - Never invent facts absent from the input.
667
+ - No headings, no markdown \u2014 just sentences.
668
+ - Keep it under 600 characters.`;
669
+ function createArchitectureCardSummariser(client) {
670
+ if (!client) return void 0;
671
+ return async (deterministicCard, repoRoot) => {
672
+ const response = await client.chatCompletion(
673
+ [
674
+ { role: "system", content: ARCHITECTURE_CARD_SUMMARY_SYSTEM_PROMPT },
675
+ { role: "user", content: `Repository: ${path.basename(repoRoot) || repoRoot}
676
+
677
+ ${deterministicCard}` }
678
+ ],
679
+ {
680
+ temperature: 0.2,
681
+ maxTokens: 512,
682
+ operation: "architecture-card-summary",
683
+ priority: "background"
684
+ }
685
+ );
686
+ return response?.content ?? null;
687
+ };
688
+ }
689
+ async function buildArchitectureCard(repoRoot, options = {}) {
690
+ if (typeof repoRoot !== "string" || repoRoot.length === 0) {
691
+ return { ok: false, code: "invalid_root", detail: "repoRoot must be a non-empty string" };
692
+ }
693
+ const absoluteRoot = path.resolve(expandTildePath(repoRoot));
694
+ try {
695
+ const rootStat = await lstat(absoluteRoot);
696
+ if (!rootStat.isDirectory()) {
697
+ return { ok: false, code: "invalid_root", detail: `not a directory: ${absoluteRoot}` };
698
+ }
699
+ } catch (err) {
700
+ return {
701
+ ok: false,
702
+ code: "invalid_root",
703
+ detail: `repoRoot not accessible: ${err instanceof Error ? err.message : String(err)}`
704
+ };
705
+ }
706
+ try {
707
+ await readdir(absoluteRoot);
708
+ } catch (err) {
709
+ return {
710
+ ok: false,
711
+ code: "scan_failed",
712
+ detail: `repoRoot not readable: ${err instanceof Error ? err.message : String(err)}`
713
+ };
714
+ }
715
+ try {
716
+ const scan = await scanRepository(absoluteRoot);
717
+ const deterministic = renderCard(scan, options.now ?? /* @__PURE__ */ new Date());
718
+ const maxBytes = options.maxBytes ?? ARCHITECTURE_CARD_MAX_BYTES;
719
+ let content = deterministic;
720
+ if (options.llmSummary === true && options.summariser) {
721
+ try {
722
+ const summary = await options.summariser(deterministic, absoluteRoot);
723
+ if (typeof summary === "string" && summary.trim().length > 0) {
724
+ const separator = "\n\n---\n\n";
725
+ const detBytes = Buffer.byteLength(deterministic, "utf-8");
726
+ const sepBytes = Buffer.byteLength(separator, "utf-8");
727
+ const summaryBudget = Math.min(
728
+ ARCHITECTURE_CARD_MAX_SUMMARY_BYTES,
729
+ maxBytes - detBytes - sepBytes
730
+ );
731
+ if (summaryBudget > 0) {
732
+ const clampedSummary = clampSummaryToBytes(summary.trim(), summaryBudget);
733
+ if (clampedSummary.length > 0) {
734
+ content = `${clampedSummary}${separator}${deterministic}`;
735
+ }
736
+ }
737
+ }
738
+ } catch (err) {
739
+ void err;
740
+ }
741
+ }
742
+ const { text: truncatedContent, truncated } = capToBytes(content, maxBytes);
743
+ return {
744
+ ok: true,
745
+ card: {
746
+ content: truncatedContent,
747
+ generatedAt: (options.now ?? /* @__PURE__ */ new Date()).toISOString(),
748
+ byteSize: Buffer.byteLength(truncatedContent, "utf-8"),
749
+ truncated
750
+ }
751
+ };
752
+ } catch (err) {
753
+ return {
754
+ ok: false,
755
+ code: "scan_failed",
756
+ detail: err instanceof Error ? err.message : String(err)
757
+ };
758
+ }
759
+ }
760
+ async function scanRepository(root) {
761
+ const topEntries = await readSortedDirEntries(root);
762
+ const topDirs = topEntries.filter((e) => e.isDirectory && !SCAN_IGNORE_DIRS.has(e.name)).map((e) => e.name);
763
+ const manifestFiles = topEntries.filter((e) => e.isFile && KNOWN_MANIFEST_FILES.includes(e.name)).map((e) => e.name);
764
+ const manifests = [];
765
+ for (const mf of sortStrings(manifestFiles)) {
766
+ const parsed = await parseManifest(path.join(root, mf));
767
+ manifests.push({ filename: mf, name: parsed.name, entryPoints: sortStrings(parsed.entryPoints) });
768
+ }
769
+ const languageHistogram = await computeLanguageHistogram(root, topEntries);
770
+ return {
771
+ root: path.basename(root) || root,
772
+ topDirs: sortStrings(topDirs),
773
+ manifests,
774
+ languageHistogram: sortLanguageHistogram(languageHistogram)
775
+ };
776
+ }
777
+ async function readSortedDirEntries(dir) {
778
+ let names;
779
+ try {
780
+ names = await readdir(dir);
781
+ } catch {
782
+ return [];
783
+ }
784
+ const entries = [];
785
+ for (const name of sortStrings(names)) {
786
+ try {
787
+ const s = await lstat(path.join(dir, name));
788
+ if (s.isSymbolicLink()) continue;
789
+ entries.push({ name, isDirectory: s.isDirectory(), isFile: s.isFile() });
790
+ } catch {
791
+ }
792
+ }
793
+ return entries;
794
+ }
795
+ async function computeLanguageHistogram(root, topEntries) {
796
+ const counts = /* @__PURE__ */ new Map();
797
+ const dirsToScan = topEntries.filter((e) => e.isDirectory && !SCAN_IGNORE_DIRS.has(e.name)).map((e) => path.join(root, e.name));
798
+ const rootFiles = topEntries.filter((e) => e.isFile);
799
+ const visitDir = async (dir, depth) => {
800
+ if (depth > 2) return;
801
+ let entries;
802
+ try {
803
+ entries = await readSortedDirEntries(dir);
804
+ } catch {
805
+ return;
806
+ }
807
+ for (const entry of entries) {
808
+ if (entry.isDirectory) {
809
+ if (!SCAN_IGNORE_DIRS.has(entry.name)) {
810
+ await visitDir(path.join(dir, entry.name), depth + 1);
811
+ }
812
+ } else if (entry.isFile) {
813
+ const ext = path.extname(entry.name).toLowerCase();
814
+ if (ext.length > 0) {
815
+ counts.set(ext, (counts.get(ext) ?? 0) + 1);
816
+ }
817
+ }
818
+ }
819
+ };
820
+ for (const f of rootFiles) {
821
+ const ext = path.extname(f.name).toLowerCase();
822
+ if (ext.length > 0) counts.set(ext, (counts.get(ext) ?? 0) + 1);
823
+ }
824
+ for (const dir of dirsToScan) {
825
+ await visitDir(dir, 0);
826
+ }
827
+ return Array.from(counts.entries()).map(([ext, count]) => ({ ext, count }));
828
+ }
829
+ async function parseManifest(filePath) {
830
+ const filename = path.basename(filePath);
831
+ try {
832
+ const raw = await readFile(filePath, "utf-8");
833
+ switch (filename) {
834
+ case "package.json":
835
+ return parsePackageJson(raw);
836
+ case "pyproject.toml":
837
+ case "setup.py":
838
+ return parsePythonProject(raw, filename);
839
+ case "go.mod":
840
+ return parseGoMod(raw);
841
+ case "Cargo.toml":
842
+ return parseCargoToml(raw);
843
+ default:
844
+ return { name: null, entryPoints: [] };
845
+ }
846
+ } catch {
847
+ return { name: null, entryPoints: [] };
848
+ }
849
+ }
850
+ function parsePackageJson(raw) {
851
+ let parsed;
852
+ try {
853
+ parsed = JSON.parse(raw);
854
+ } catch {
855
+ return { name: null, entryPoints: [] };
856
+ }
857
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
858
+ return { name: null, entryPoints: [] };
859
+ }
860
+ const obj = parsed;
861
+ const name = typeof obj["name"] === "string" ? obj["name"] : null;
862
+ const entryPoints = [];
863
+ const bin = obj["bin"];
864
+ if (typeof bin === "string") {
865
+ entryPoints.push(bin);
866
+ } else if (typeof bin === "object" && bin !== null && !Array.isArray(bin)) {
867
+ for (const [key, value] of Object.entries(bin)) {
868
+ entryPoints.push(typeof value === "string" ? value : `bin/${key}`);
869
+ }
870
+ }
871
+ const main = typeof obj["main"] === "string" ? obj["main"] : null;
872
+ if (main) entryPoints.push(main);
873
+ const module = typeof obj["module"] === "string" ? obj["module"] : null;
874
+ if (module) entryPoints.push(module);
875
+ const scripts = obj["scripts"];
876
+ if (typeof scripts === "object" && scripts !== null && !Array.isArray(scripts)) {
877
+ const scriptKeys = Object.keys(scripts);
878
+ for (const key of ["start", "dev", "serve"]) {
879
+ if (scriptKeys.includes(key)) entryPoints.push(`scripts.${key}`);
880
+ }
881
+ }
882
+ return { name, entryPoints };
883
+ }
884
+ function parsePythonProject(raw, _filename) {
885
+ const entryPoints = [];
886
+ let name = null;
887
+ const nameMatch = raw.match(/^name\s*=\s*["']([^"']+)["']/m);
888
+ if (nameMatch) name = nameMatch[1] ?? null;
889
+ const scriptsMatch = raw.match(/\[project\.scripts\]([\s\S]*?)(?:\n\[|$)/);
890
+ if (scriptsMatch && scriptsMatch[1]) {
891
+ for (const line of scriptsMatch[1].split("\n")) {
892
+ const m = line.match(/^([a-zA-Z0-9_-]+)\s*=/);
893
+ if (m && m[1]) entryPoints.push(`scripts.${m[1]}`);
894
+ }
895
+ }
896
+ return { name, entryPoints };
897
+ }
898
+ function parseGoMod(raw) {
899
+ const moduleMatch = raw.match(/^module\s+(\S+)/m);
900
+ const name = moduleMatch && moduleMatch[1] ? moduleMatch[1] : null;
901
+ return { name, entryPoints: name ? ["main.go"] : [] };
902
+ }
903
+ function parseCargoToml(raw) {
904
+ const nameMatch = raw.match(/^name\s*=\s*"([^"]+)"/m);
905
+ const name = nameMatch && nameMatch[1] ? nameMatch[1] : null;
906
+ const entryPoints = [];
907
+ if (/\[\[bin\]\]/.test(raw)) entryPoints.push("src/bin/");
908
+ if (name) entryPoints.push("src/main.rs");
909
+ return { name, entryPoints };
910
+ }
911
+ function renderCard(scan, now) {
912
+ const lines = [];
913
+ lines.push(`# Architecture Card \u2014 ${scan.root}`);
914
+ lines.push("");
915
+ lines.push(`_Generated ${now.toISOString()}_`);
916
+ lines.push("");
917
+ const namedManifest = scan.manifests.find((m) => m.name !== null);
918
+ if (namedManifest && namedManifest.name) {
919
+ lines.push(`**Project:** ${namedManifest.name}`);
920
+ lines.push("");
921
+ }
922
+ if (scan.manifests.length > 0) {
923
+ lines.push("## Manifests");
924
+ for (const m of scan.manifests) {
925
+ const label = m.name ? `${m.filename} (${m.name})` : m.filename;
926
+ lines.push(`- ${label}`);
927
+ }
928
+ lines.push("");
929
+ }
930
+ if (scan.topDirs.length > 0) {
931
+ lines.push("## Top-level directories");
932
+ const cols = 4;
933
+ for (let i = 0; i < scan.topDirs.length; i += cols) {
934
+ const row = scan.topDirs.slice(i, i + cols).join(" \xB7 ");
935
+ lines.push(`- ${row}`);
936
+ }
937
+ lines.push("");
938
+ }
939
+ if (scan.languageHistogram.length > 0) {
940
+ lines.push("## Languages (by file count)");
941
+ const top = scan.languageHistogram.slice(0, 10);
942
+ for (const entry of top) {
943
+ lines.push(`- ${entry.ext}: ${entry.count}`);
944
+ }
945
+ lines.push("");
946
+ }
947
+ const allEntryPoints = sortStrings(scan.manifests.flatMap((m) => m.entryPoints));
948
+ if (allEntryPoints.length > 0) {
949
+ lines.push("## Entry points");
950
+ for (const ep of allEntryPoints) {
951
+ lines.push(`- ${ep}`);
952
+ }
953
+ lines.push("");
954
+ }
955
+ return lines.join("\n").trimEnd() + "\n";
956
+ }
957
+ function sortStrings(values) {
958
+ return [...values].sort((a, b) => a.localeCompare(b));
959
+ }
960
+ function sortLanguageHistogram(entries) {
961
+ return [...entries].sort((a, b) => {
962
+ if (b.count !== a.count) return b.count - a.count;
963
+ return a.ext.localeCompare(b.ext);
964
+ });
965
+ }
966
+ function capToBytes(text, maxBytes) {
967
+ const byteLen = Buffer.byteLength(text, "utf-8");
968
+ if (byteLen <= maxBytes) {
969
+ return { text, truncated: false };
970
+ }
971
+ const marker = `
972
+
973
+ _${ARCHITECTURE_CARD_TRUNCATION_MARKER}_`;
974
+ const markerBytes = Buffer.byteLength(marker, "utf-8");
975
+ const budget = maxBytes - markerBytes;
976
+ if (budget <= 0) {
977
+ return { text: marker.trimStart(), truncated: true };
978
+ }
979
+ let cut = 0;
980
+ let running = 0;
981
+ const chars = [...text];
982
+ for (let i = 0; i < chars.length; i++) {
983
+ const charBytes = Buffer.byteLength(chars[i], "utf-8");
984
+ if (running + charBytes > budget) break;
985
+ running += charBytes;
986
+ cut = i + 1;
987
+ }
988
+ return { text: chars.slice(0, cut).join("") + marker, truncated: true };
989
+ }
990
+ function clampSummaryToBytes(text, maxBytes) {
991
+ if (maxBytes <= 0) return "";
992
+ if (Buffer.byteLength(text, "utf-8") <= maxBytes) return text;
993
+ const ellipsis = " \u2026";
994
+ const budget = maxBytes - Buffer.byteLength(ellipsis, "utf-8");
995
+ if (budget <= 0) return "";
996
+ let cut = 0;
997
+ let running = 0;
998
+ const chars = [...text];
999
+ for (let i = 0; i < chars.length; i++) {
1000
+ const charBytes = Buffer.byteLength(chars[i], "utf-8");
1001
+ if (running + charBytes > budget) break;
1002
+ running += charBytes;
1003
+ cut = i + 1;
1004
+ }
1005
+ return chars.slice(0, cut).join("") + ellipsis;
1006
+ }
1007
+
1008
+ // src/coding/architecture-surfaces.ts
1009
+ function isArchitectureCardSurfaceEnabled(config, codingContext) {
1010
+ return config.enabled === true && config.architectureCard === true && codingContext !== null && codingContext !== void 0;
1011
+ }
1012
+ var ARCHITECTURE_CARD_TAG = "architecture-card";
1013
+ var ARCHITECTURE_CARD_KIND = "architecture";
1014
+ async function handleCodingArchitecture(request, ctx) {
1015
+ const codingContext = request.sessionKey ? ctx.getCodingContext(request.sessionKey) : null;
1016
+ if (codingContext === null || !isArchitectureCardSurfaceEnabled(ctx.codingKnowledge, codingContext)) {
1017
+ ctx.throwInputError(
1018
+ "coding_architecture requires codingKnowledge.enabled, codingKnowledge.architectureCard, and an attached coding context"
1019
+ );
1020
+ }
1021
+ switch (request.subcommand) {
1022
+ case "get":
1023
+ return architectureGet(request, ctx);
1024
+ case "refresh":
1025
+ return architectureRefresh(request, ctx, codingContext);
1026
+ }
1027
+ }
1028
+ async function architectureGet(request, ctx) {
1029
+ const storage = await ctx.resolveStorage(request);
1030
+ const existing = await findArchitectureCardMemory(storage);
1031
+ if (!existing) {
1032
+ return { subcommand: "get", found: false };
1033
+ }
1034
+ const content = stripAttributesSuffix(existing.content);
1035
+ return {
1036
+ subcommand: "get",
1037
+ found: true,
1038
+ card: {
1039
+ content,
1040
+ generatedAt: existing.frontmatter.updated ?? existing.frontmatter.created,
1041
+ byteSize: Buffer.byteLength(content, "utf-8"),
1042
+ // Derive truncation from the CONTENT marker, not a frontmatter tag —
1043
+ // the refresh update path changes content without rewriting tags, so
1044
+ // a tag-based check goes stale (cursor review: stale truncated tag).
1045
+ truncated: content.includes(ARCHITECTURE_CARD_TRUNCATION_MARKER)
1046
+ }
1047
+ };
1048
+ }
1049
+ async function architectureRefresh(request, ctx, codingContext) {
1050
+ const repoRoot = codingContext.rootPath ?? codingContext.projectId;
1051
+ const storage = await ctx.resolveStorage(request);
1052
+ const buildResult = await ctx.buildCard(repoRoot);
1053
+ if (!buildResult.ok) {
1054
+ log.warn(
1055
+ `coding_architecture/refresh: card build failed (code=${buildResult.code}): ${buildResult.detail}`
1056
+ );
1057
+ ctx.throwInputError(
1058
+ `coding_architecture refresh failed: card build returned ${buildResult.code}`
1059
+ );
1060
+ }
1061
+ const cardContent = buildResult.card.content;
1062
+ const tags = [ARCHITECTURE_CARD_TAG];
1063
+ if (buildResult.card.truncated) tags.push("truncated");
1064
+ const existing = await findArchitectureCardMemory(storage);
1065
+ if (existing) {
1066
+ await ctx.versioning.snapshotIfExists(existing);
1067
+ const updated = await storage.updateMemory(existing.frontmatter.id, cardContent, {
1068
+ actor: "coding-architecture-refresh"
1069
+ });
1070
+ if (!updated) {
1071
+ log.warn(
1072
+ `coding_architecture/refresh: updateMemory returned false for id=${existing.frontmatter.id} \u2014 falling back to writeMemory`
1073
+ );
1074
+ const memoryId2 = await storage.writeMemory("fact", cardContent, {
1075
+ confidence: 1,
1076
+ tags,
1077
+ source: "coding-architecture",
1078
+ structuredAttributes: { cardKind: ARCHITECTURE_CARD_KIND }
1079
+ });
1080
+ log.info(
1081
+ `access-write op=coding_architecture/refresh memoryId=${memoryId2} (fallback write) byteSize=${buildResult.card.byteSize}`
1082
+ );
1083
+ return {
1084
+ subcommand: "refresh",
1085
+ refreshed: true,
1086
+ memoryId: memoryId2,
1087
+ byteSize: buildResult.card.byteSize,
1088
+ truncated: buildResult.card.truncated
1089
+ };
1090
+ }
1091
+ log.info(
1092
+ `access-write op=coding_architecture/refresh memoryId=${existing.frontmatter.id} (updated) byteSize=${buildResult.card.byteSize}`
1093
+ );
1094
+ return {
1095
+ subcommand: "refresh",
1096
+ refreshed: true,
1097
+ memoryId: existing.frontmatter.id,
1098
+ byteSize: buildResult.card.byteSize,
1099
+ truncated: buildResult.card.truncated
1100
+ };
1101
+ }
1102
+ const memoryId = await storage.writeMemory("fact", cardContent, {
1103
+ confidence: 1,
1104
+ tags,
1105
+ source: "coding-architecture",
1106
+ structuredAttributes: { cardKind: ARCHITECTURE_CARD_KIND }
1107
+ });
1108
+ log.info(
1109
+ `access-write op=coding_architecture/refresh memoryId=${memoryId} (new) byteSize=${buildResult.card.byteSize}`
1110
+ );
1111
+ return {
1112
+ subcommand: "refresh",
1113
+ refreshed: true,
1114
+ memoryId,
1115
+ byteSize: buildResult.card.byteSize,
1116
+ truncated: buildResult.card.truncated
1117
+ };
1118
+ }
1119
+ async function findArchitectureCardMemory(storage) {
1120
+ const memories = await storage.readAllMemories();
1121
+ const cards = memories.filter((m) => {
1122
+ if (m.frontmatter.category !== "fact") return false;
1123
+ const tags = m.frontmatter.tags ?? [];
1124
+ if (!tags.includes(ARCHITECTURE_CARD_TAG)) return false;
1125
+ if (m.frontmatter.structuredAttributes?.cardKind !== ARCHITECTURE_CARD_KIND) return false;
1126
+ const outer = m.frontmatter.status;
1127
+ if (outer !== void 0 && outer !== "active") return false;
1128
+ if (m.frontmatter.archivedAt !== void 0 && m.frontmatter.archivedAt !== null) return false;
1129
+ return true;
1130
+ });
1131
+ if (cards.length === 0) return null;
1132
+ cards.sort((a, b) => {
1133
+ const aUpdated = a.frontmatter.updated ?? a.frontmatter.created;
1134
+ const bUpdated = b.frontmatter.updated ?? b.frontmatter.created;
1135
+ if (aUpdated !== bUpdated) return bUpdated.localeCompare(aUpdated);
1136
+ return b.frontmatter.id.localeCompare(a.frontmatter.id);
1137
+ });
1138
+ return cards[0] ?? null;
1139
+ }
1140
+ function createArchitectureVersioningHook(enabled, maxVersionsPerPage, sidecarDir, memoryDir, readFile3, writeVersion) {
1141
+ return {
1142
+ async snapshotIfExists(memory) {
1143
+ if (!enabled) return;
1144
+ try {
1145
+ const fullContent = await readFile3(memory.path);
1146
+ await writeVersion(
1147
+ memory.path,
1148
+ fullContent,
1149
+ "manual",
1150
+ { enabled: true, maxVersionsPerPage, sidecarDir },
1151
+ void 0,
1152
+ "architecture-card-refresh",
1153
+ memoryDir
1154
+ );
1155
+ } catch {
1156
+ }
1157
+ }
1158
+ };
1159
+ }
1160
+
612
1161
  // src/procedural/procedure-miner.ts
613
1162
  import { createHash } from "crypto";
614
1163
  import { mkdir, rm, stat } from "fs/promises";
615
- import path from "path";
1164
+ import path2 from "path";
616
1165
  var PROCEDURE_CLUSTER_ATTR_MAX = 500;
617
1166
  var PROCEDURE_CLUSTER_LOCK_STALE_MS = 12e4;
618
1167
  var PROCEDURE_CLUSTER_LOCK_TIMEOUT_MS = 3e4;
@@ -632,8 +1181,8 @@ function sleep(ms) {
632
1181
  return new Promise((resolve2) => setTimeout(resolve2, ms));
633
1182
  }
634
1183
  async function acquireClusterWriteLock(memoryDir, clusterHash) {
635
- const lockRoot = path.join(path.resolve(memoryDir), "state", "procedure-miner-locks");
636
- const lockDir = path.join(lockRoot, `${clusterHash}.lock`);
1184
+ const lockRoot = path2.join(path2.resolve(memoryDir), "state", "procedure-miner-locks");
1185
+ const lockDir = path2.join(lockRoot, `${clusterHash}.lock`);
637
1186
  await mkdir(lockRoot, { recursive: true });
638
1187
  const startedAt = Date.now();
639
1188
  let attempts = 0;
@@ -664,7 +1213,7 @@ async function acquireClusterWriteLock(memoryDir, clusterHash) {
664
1213
  }
665
1214
  }
666
1215
  async function withClusterWriteLock(memoryDir, clusterHash, fn) {
667
- const inProcessKey = `${path.resolve(memoryDir)}:${clusterHash}`;
1216
+ const inProcessKey = `${path2.resolve(memoryDir)}:${clusterHash}`;
668
1217
  const previous = inProcessClusterWriteLocks.get(inProcessKey) ?? Promise.resolve();
669
1218
  let releaseInProcess;
670
1219
  const current = previous.catch(() => void 0).then(
@@ -3255,6 +3804,51 @@ var EngramAccessService = class {
3255
3804
  }
3256
3805
  });
3257
3806
  }
3807
+ /** Whether the coding_architecture tool should appear in tools/list (rule 39). */
3808
+ get architectureCardSurfaceVisible() {
3809
+ return this.orchestrator.config.codingKnowledge?.enabled === true && this.orchestrator.config.codingKnowledge?.architectureCard === true;
3810
+ }
3811
+ /**
3812
+ * Thin delegate — handler logic in coding/architecture-surfaces.ts (#1548 PR3).
3813
+ * All three surfaces (MCP/HTTP/CLI) arrive here via the boundary operation.
3814
+ * Namespace resolution uses the SAME coding-scoped path as decision records.
3815
+ */
3816
+ async codingArchitecture(request, authenticatedPrincipal) {
3817
+ const resolvedConfig = this.orchestrator.config;
3818
+ return handleCodingArchitecture(request, {
3819
+ codingKnowledge: this.orchestrator.config.codingKnowledge,
3820
+ getCodingContext: (sk) => this.orchestrator.getCodingContextForSession(sk),
3821
+ resolveStorage: async (req) => {
3822
+ const isWrite = req.subcommand === "refresh";
3823
+ const ns = isWrite ? await this.resolveCodingScopedWriteNamespace({
3824
+ namespace: req.namespace,
3825
+ sessionKey: req.sessionKey,
3826
+ authenticatedPrincipal
3827
+ }) : await this.resolveCodingScopedReadableNamespace({
3828
+ namespace: req.namespace,
3829
+ sessionKey: req.sessionKey,
3830
+ authenticatedPrincipal
3831
+ });
3832
+ const storage = await this.orchestrator.getStorage(ns);
3833
+ return Object.assign(storage, { namespace: ns });
3834
+ },
3835
+ buildCard: async (repoRoot) => buildArchitectureCard(repoRoot, {
3836
+ llmSummary: this.orchestrator.config.codingKnowledge?.architectureCardLlmSummary === true,
3837
+ summariser: createArchitectureCardSummariser(this.fallbackLlmRef ?? this.localLlmRef)
3838
+ }),
3839
+ versioning: createArchitectureVersioningHook(
3840
+ resolvedConfig.versioningEnabled === true,
3841
+ resolvedConfig.versioningMaxPerPage,
3842
+ resolvedConfig.versioningSidecarDir,
3843
+ resolvedConfig.memoryDir,
3844
+ (p) => nodeFs.readFile(p, "utf-8"),
3845
+ createVersion
3846
+ ),
3847
+ throwInputError: (msg) => {
3848
+ throw new EngramAccessInputError(msg);
3849
+ }
3850
+ });
3851
+ }
3258
3852
  async memoryBrowse(request = {}) {
3259
3853
  const resolvedNamespace = this.resolveReadableNamespace(
3260
3854
  request.namespace,
@@ -6066,4 +6660,4 @@ export {
6066
6660
  shapeMemorySummary,
6067
6661
  EngramAccessService
6068
6662
  };
6069
- //# sourceMappingURL=chunk-XU7363OX.js.map
6663
+ //# sourceMappingURL=chunk-Z7KILAOU.js.map