@a-company/paradigm 3.1.5 → 3.5.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.
Files changed (80) hide show
  1. package/dist/{accept-orchestration-CWZNCGZX.js → accept-orchestration-DIGPJVUR.js} +6 -5
  2. package/dist/{aggregate-W7Q6VIM2.js → aggregate-V4KPR3RW.js} +2 -2
  3. package/dist/{beacon-B47XSTL7.js → beacon-XRXL5KZB.js} +2 -2
  4. package/dist/{chunk-4LGLU2LO.js → chunk-2E2RTBSM.js} +533 -182
  5. package/dist/{chunk-YCLN7WXV.js → chunk-2QNZ6PVD.js} +219 -35
  6. package/dist/{chunk-UM54F7G5.js → chunk-4N6AYEEA.js} +1 -1
  7. package/dist/{chunk-MVXJVRFI.js → chunk-5TUAVVIG.js} +65 -1
  8. package/dist/{chunk-5C4SGQKH.js → chunk-6P4IFIK2.js} +4 -2
  9. package/dist/{chunk-WS5KM7OL.js → chunk-6RNYVBSG.js} +1 -1
  10. package/dist/{chunk-N6PJAPDE.js → chunk-AK5M6KJB.js} +18 -0
  11. package/dist/{chunk-VZ7CXFRZ.js → chunk-CRICL4FQ.js} +1004 -17
  12. package/dist/{chunk-MC7XC7XQ.js → chunk-GZDFVP2N.js} +20 -13
  13. package/dist/chunk-HPC3JAUP.js +42 -0
  14. package/dist/chunk-IRVA7NKV.js +657 -0
  15. package/dist/{chunk-ZPN7MXRA.js → chunk-KFHK6EBI.js} +184 -1
  16. package/dist/{chunk-UUZ2DMG5.js → chunk-KWDTBXP2.js} +1 -1
  17. package/dist/{chunk-DRUDZKIT.js → chunk-M2XMTJHQ.js} +693 -70
  18. package/dist/{chunk-PW2EXJQT.js → chunk-MRENOFTR.js} +24 -1
  19. package/dist/{chunk-QS36NGWV.js → chunk-QHJGB5TV.js} +1 -1
  20. package/dist/chunk-UI3XXVJ6.js +449 -0
  21. package/dist/{chunk-AD2LSCHB.js → chunk-Y4XZWCHK.js} +40 -74
  22. package/dist/{constellation-K3CIQCHI.js → constellation-GNK5DIMH.js} +2 -2
  23. package/dist/{cost-AEK6R7HK.js → cost-AGO5N7DD.js} +1 -1
  24. package/dist/{cursorrules-KI5QWHIX.js → cursorrules-LQFA7M62.js} +2 -2
  25. package/dist/{delete-W67IVTLJ.js → delete-3YXAJ5AA.js} +12 -1
  26. package/dist/{diff-AJJ5H6HV.js → diff-J6C5IHPV.js} +6 -5
  27. package/dist/{dist-2F7NO4H4-KSL6SJIO.js → dist-AG5JNIZU-XSEZ2LLK.js} +28 -3
  28. package/dist/dist-JOHRYQUA.js +7294 -0
  29. package/dist/{dist-NHJQVVUW.js → dist-Q6SAZI7X.js} +2 -2
  30. package/dist/{dist-GPQ4LAY3.js → dist-YP2CO4TG.js} +24 -6
  31. package/dist/{doctor-JBIV5PMN.js → doctor-TQYRF7KK.js} +2 -2
  32. package/dist/{edit-Y7XPYSMK.js → edit-EOMPXOG5.js} +1 -1
  33. package/dist/flow-7JUH6D4H.js +185 -0
  34. package/dist/global-AXILUM5X.js +136 -0
  35. package/dist/{habits-FA65W77Y.js → habits-CHP4EW5H.js} +234 -5
  36. package/dist/{hooks-JKWO44WH.js → hooks-DLZEYHI3.js} +1 -1
  37. package/dist/index.js +125 -100
  38. package/dist/{lint-HXKTWRNO.js → lint-N4LMMEXH.js} +141 -1
  39. package/dist/{list-R3QWW4SC.js → list-JKBJ7ESH.js} +1 -1
  40. package/dist/mcp.js +9273 -6515
  41. package/dist/{orchestrate-4ZH5GUQH.js → orchestrate-FAV64G2R.js} +6 -5
  42. package/dist/{probe-OYCP4JYG.js → probe-X3J2JX62.js} +18 -3
  43. package/dist/{promote-E6NBZ3BK.js → promote-HZH5E5CO.js} +1 -1
  44. package/dist/{providers-4PGPZEWP.js → providers-NQ67LO2Z.js} +1 -1
  45. package/dist/{record-OHQNWOUP.js → record-EECZ3E4I.js} +1 -1
  46. package/dist/{remember-6VZ74B7E.js → remember-3KJZGDUG.js} +1 -1
  47. package/dist/{review-RUHX25A5.js → review-BF26ILZB.js} +1 -1
  48. package/dist/{ripple-SBQOSTZD.js → ripple-JIUAMBLA.js} +2 -2
  49. package/dist/sentinel-ZTL224IG.js +63 -0
  50. package/dist/{server-MV4HNFVF.js → server-MZBYDXJY.js} +4193 -9
  51. package/dist/{setup-DF4F3ICN.js → setup-363IB6MO.js} +1 -1
  52. package/dist/{setup-JHBPZAG7.js → setup-UKJ3VGHI.js} +4 -4
  53. package/dist/{shift-2LQFQP4P.js → shift-KDVYB6CR.js} +16 -13
  54. package/dist/{show-WTOJXUTN.js → show-SAMTXEHG.js} +1 -1
  55. package/dist/{snapshot-GTVPRYZG.js → snapshot-KCMONZAO.js} +2 -2
  56. package/dist/{spawn-BJRQA2NR.js → spawn-EO7B2UM3.js} +2 -2
  57. package/dist/{summary-5SBFO7QK.js → summary-E2PU4UN2.js} +3 -3
  58. package/dist/{switch-6EANJ7O6.js → switch-CC2KACXO.js} +1 -1
  59. package/dist/{sync-5KSTPJ4B.js → sync-5VJPZQNX.js} +2 -2
  60. package/dist/sync-llms-7QDA3ZWC.js +166 -0
  61. package/dist/{team-NWP2KJAB.js → team-6CCNANKE.js} +7 -6
  62. package/dist/{test-MA5TWJQV.js → test-DK2RWLTK.js} +91 -8
  63. package/dist/{thread-JCJVRUQR.js → thread-RNSLADXN.js} +18 -2
  64. package/dist/{timeline-P7BARFLI.js → timeline-TJDVVVA3.js} +1 -1
  65. package/dist/{triage-TBIWJA6R.js → triage-PXMU3RWV.js} +2 -2
  66. package/dist/university-content/courses/para-101.json +2 -1
  67. package/dist/university-content/courses/para-201.json +102 -3
  68. package/dist/university-content/courses/para-301.json +14 -11
  69. package/dist/university-content/courses/para-401.json +57 -3
  70. package/dist/university-content/courses/para-501.json +204 -6
  71. package/dist/university-content/plsat/v3.0.json +808 -3
  72. package/dist/university-content/reference.json +270 -0
  73. package/dist/{upgrade-TIYFQYPO.js → upgrade-RBSE4M6I.js} +1 -1
  74. package/dist/{validate-QEEY6KFS.js → validate-2LTHHORX.js} +1 -1
  75. package/dist/{watch-4LT4O6K7.js → watch-NBPOMOEX.js} +76 -0
  76. package/dist/{watch-2XEYUH43.js → watch-PAEH6MOG.js} +1 -1
  77. package/package.json +1 -1
  78. package/dist/chunk-GWM2WRXL.js +0 -1095
  79. package/dist/sentinel-WB7GIK4V.js +0 -43
  80. /package/dist/{chunk-TAP5N3HH.js → chunk-CCG6KYBT.js} +0 -0
@@ -9,7 +9,7 @@ import {
9
9
  mcpSetupCommand,
10
10
  mcpStatusCommand,
11
11
  writeConfig
12
- } from "./chunk-MC7XC7XQ.js";
12
+ } from "./chunk-GZDFVP2N.js";
13
13
  import "./chunk-4NCFWYGG.js";
14
14
  import "./chunk-MO4EEYFW.js";
15
15
  export {
@@ -2,14 +2,14 @@
2
2
  import {
3
3
  cursorrrulesExists,
4
4
  writeCursorrules
5
- } from "./chunk-UUZ2DMG5.js";
6
- import "./chunk-N6PJAPDE.js";
5
+ } from "./chunk-KWDTBXP2.js";
6
+ import "./chunk-AK5M6KJB.js";
7
7
  import {
8
8
  getDefaultPremiseContent
9
- } from "./chunk-5C4SGQKH.js";
9
+ } from "./chunk-6P4IFIK2.js";
10
10
  import {
11
11
  getDefaultPurposeContent
12
- } from "./chunk-PW2EXJQT.js";
12
+ } from "./chunk-MRENOFTR.js";
13
13
  import "./chunk-IRKUEJVW.js";
14
14
  import {
15
15
  DEFAULT_CONVENTIONS,
@@ -1,36 +1,39 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  teamInitCommand
4
- } from "./chunk-UM54F7G5.js";
5
- import "./chunk-AD2LSCHB.js";
4
+ } from "./chunk-4N6AYEEA.js";
5
+ import "./chunk-Y4XZWCHK.js";
6
6
  import "./chunk-6QC3YGB6.js";
7
- import "./chunk-WS5KM7OL.js";
7
+ import "./chunk-HPC3JAUP.js";
8
+ import "./chunk-6RNYVBSG.js";
8
9
  import "./chunk-PBHIFAL4.js";
9
- import "./chunk-TAP5N3HH.js";
10
+ import "./chunk-CCG6KYBT.js";
10
11
  import {
11
12
  agentsConfigured
12
13
  } from "./chunk-PMXRGPRQ.js";
13
14
  import {
14
15
  hooksInstallCommand
15
- } from "./chunk-DRUDZKIT.js";
16
+ } from "./chunk-M2XMTJHQ.js";
16
17
  import {
17
- indexCommand,
18
18
  initCommand
19
- } from "./chunk-GWM2WRXL.js";
19
+ } from "./chunk-IRVA7NKV.js";
20
+ import {
21
+ indexCommand
22
+ } from "./chunk-UI3XXVJ6.js";
20
23
  import {
21
24
  detectDiscipline
22
25
  } from "./chunk-CHSHON3O.js";
23
- import "./chunk-N6PJAPDE.js";
24
- import "./chunk-5C4SGQKH.js";
25
- import "./chunk-PW2EXJQT.js";
26
+ import "./chunk-AK5M6KJB.js";
27
+ import "./chunk-6P4IFIK2.js";
28
+ import "./chunk-MRENOFTR.js";
26
29
  import "./chunk-IRKUEJVW.js";
27
30
  import {
28
31
  syncCommand
29
- } from "./chunk-QS36NGWV.js";
32
+ } from "./chunk-QHJGB5TV.js";
30
33
  import {
31
34
  doctorCommand
32
- } from "./chunk-ZPN7MXRA.js";
33
- import "./chunk-YCLN7WXV.js";
35
+ } from "./chunk-KFHK6EBI.js";
36
+ import "./chunk-2QNZ6PVD.js";
34
37
  import {
35
38
  log
36
39
  } from "./chunk-4NCFWYGG.js";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  loadLoreEntry
4
- } from "./chunk-MVXJVRFI.js";
4
+ } from "./chunk-5TUAVVIG.js";
5
5
  import "./chunk-MO4EEYFW.js";
6
6
 
7
7
  // src/commands/lore/show.ts
@@ -3,8 +3,8 @@ import {
3
3
  createSnapshot,
4
4
  parsePremiseFile,
5
5
  serializePremiseFile
6
- } from "./chunk-5C4SGQKH.js";
7
- import "./chunk-PW2EXJQT.js";
6
+ } from "./chunk-6P4IFIK2.js";
7
+ import "./chunk-MRENOFTR.js";
8
8
  import "./chunk-IRKUEJVW.js";
9
9
  import "./chunk-MO4EEYFW.js";
10
10
 
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  AgentSpawner
4
- } from "./chunk-WS5KM7OL.js";
4
+ } from "./chunk-6RNYVBSG.js";
5
5
  import "./chunk-PBHIFAL4.js";
6
6
  import {
7
7
  getBestProvider
8
- } from "./chunk-TAP5N3HH.js";
8
+ } from "./chunk-CCG6KYBT.js";
9
9
  import {
10
10
  loadAgentsManifest
11
11
  } from "./chunk-PMXRGPRQ.js";
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  aggregateFromDirectory
4
- } from "./chunk-5C4SGQKH.js";
5
- import "./chunk-PW2EXJQT.js";
4
+ } from "./chunk-6P4IFIK2.js";
5
+ import "./chunk-MRENOFTR.js";
6
6
  import "./chunk-IRKUEJVW.js";
7
7
  import {
8
8
  detectIDE,
9
9
  getAdapter
10
- } from "./chunk-YCLN7WXV.js";
10
+ } from "./chunk-2QNZ6PVD.js";
11
11
  import "./chunk-YO6DVTL7.js";
12
12
  import "./chunk-MO4EEYFW.js";
13
13
 
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  detectAllClients,
4
4
  getServersFromConfig
5
- } from "./chunk-MC7XC7XQ.js";
5
+ } from "./chunk-GZDFVP2N.js";
6
6
  import "./chunk-4NCFWYGG.js";
7
7
  import "./chunk-MO4EEYFW.js";
8
8
 
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  syncCommand
4
- } from "./chunk-QS36NGWV.js";
5
- import "./chunk-YCLN7WXV.js";
4
+ } from "./chunk-QHJGB5TV.js";
5
+ import "./chunk-2QNZ6PVD.js";
6
6
  import "./chunk-4NCFWYGG.js";
7
7
  import "./chunk-YO6DVTL7.js";
8
8
  import "./chunk-MO4EEYFW.js";
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ loadParadigmFiles
4
+ } from "./chunk-2QNZ6PVD.js";
5
+ import {
6
+ log
7
+ } from "./chunk-4NCFWYGG.js";
8
+ import "./chunk-YO6DVTL7.js";
9
+ import "./chunk-MO4EEYFW.js";
10
+
11
+ // src/commands/sync-llms.ts
12
+ import * as fs from "fs";
13
+ import * as path from "path";
14
+ import * as yaml from "js-yaml";
15
+ import chalk from "chalk";
16
+ import ora from "ora";
17
+ async function syncLlmsCommand(options) {
18
+ const rootDir = process.cwd();
19
+ const spinner = ora();
20
+ console.log(chalk.blue("\n Paradigm Sync LLMs\n"));
21
+ spinner.start("Loading .paradigm/ configuration...");
22
+ const files = loadParadigmFiles(rootDir);
23
+ if (!files) {
24
+ spinner.fail("No .paradigm/ directory found");
25
+ console.log(chalk.gray("\nRun `paradigm init` to initialize Paradigm in this project.\n"));
26
+ log.command("sync-llms").error("Missing .paradigm/ directory");
27
+ process.exit(1);
28
+ }
29
+ spinner.succeed(`Loaded configuration for ${chalk.cyan(files.projectName)}`);
30
+ log.command("sync-llms").debug("Configuration loaded", { projectName: files.projectName });
31
+ spinner.start("Reading navigator.yaml...");
32
+ let navigator = null;
33
+ const navigatorPath = path.join(rootDir, ".paradigm", "navigator.yaml");
34
+ if (fs.existsSync(navigatorPath)) {
35
+ try {
36
+ const content2 = fs.readFileSync(navigatorPath, "utf8");
37
+ navigator = yaml.load(content2);
38
+ spinner.succeed("Loaded navigator.yaml");
39
+ } catch {
40
+ spinner.warn("Could not parse navigator.yaml, skipping key files section");
41
+ log.command("sync-llms").warn("Failed to parse navigator.yaml");
42
+ }
43
+ } else {
44
+ spinner.info("No navigator.yaml found, skipping key files section");
45
+ }
46
+ let flows = null;
47
+ const flowsPath = path.join(rootDir, ".paradigm", "flows.yaml");
48
+ if (fs.existsSync(flowsPath)) {
49
+ try {
50
+ const content2 = fs.readFileSync(flowsPath, "utf8");
51
+ flows = yaml.load(content2);
52
+ } catch {
53
+ log.command("sync-llms").warn("Failed to parse flows.yaml");
54
+ }
55
+ }
56
+ let portal = null;
57
+ const portalPath = path.join(rootDir, "portal.yaml");
58
+ if (fs.existsSync(portalPath)) {
59
+ try {
60
+ const content2 = fs.readFileSync(portalPath, "utf8");
61
+ portal = yaml.load(content2);
62
+ } catch {
63
+ log.command("sync-llms").warn("Failed to parse portal.yaml");
64
+ }
65
+ }
66
+ spinner.start("Generating llms.txt...");
67
+ const content = generateLlmsTxt(files, navigator, flows, portal);
68
+ const outputPath = options.output ? path.resolve(rootDir, options.output) : path.join(rootDir, "llms.txt");
69
+ try {
70
+ fs.writeFileSync(outputPath, content, "utf8");
71
+ spinner.succeed(chalk.green(`Generated llms.txt`));
72
+ console.log(chalk.gray(`
73
+ Path: ${path.relative(rootDir, outputPath)}`));
74
+ console.log("");
75
+ log.command("sync-llms").success("llms.txt generated", { path: outputPath });
76
+ } catch (error) {
77
+ spinner.fail(chalk.red(`Failed to write llms.txt`));
78
+ log.command("sync-llms").error("Write failed", { error: error.message });
79
+ process.exit(1);
80
+ }
81
+ }
82
+ function generateLlmsTxt(files, navigator, flows, portal) {
83
+ const { config, projectName } = files;
84
+ const sections = [];
85
+ sections.push(`# ${config.project || projectName}`);
86
+ const overview = config["agent-guidelines"]?.overview?.trim();
87
+ if (overview) {
88
+ sections.push(`> ${overview.replace(/\n/g, "\n> ")}`);
89
+ }
90
+ const symbolSystem = config["symbol-system"];
91
+ if (symbolSystem) {
92
+ const symbolLines = ["## Symbols", ""];
93
+ symbolLines.push("| Prefix | Name | Description |");
94
+ symbolLines.push("|--------|------|-------------|");
95
+ for (const [prefix, def] of Object.entries(symbolSystem)) {
96
+ if (["#", "$", "^", "!", "~"].includes(prefix)) {
97
+ symbolLines.push(`| \`${prefix}\` | ${def.name} | ${def.description} |`);
98
+ }
99
+ }
100
+ sections.push(symbolLines.join("\n"));
101
+ }
102
+ if (navigator?.key_files) {
103
+ const keyFileLines = ["## Key Files", ""];
104
+ for (const [category, paths] of Object.entries(navigator.key_files)) {
105
+ if (paths && paths.length > 0) {
106
+ keyFileLines.push(`### ${category.charAt(0).toUpperCase() + category.slice(1)}`);
107
+ keyFileLines.push("");
108
+ for (const p of paths) {
109
+ keyFileLines.push(`- \`${p}\``);
110
+ }
111
+ keyFileLines.push("");
112
+ }
113
+ }
114
+ if (keyFileLines.length > 2) {
115
+ sections.push(keyFileLines.join("\n").trimEnd());
116
+ }
117
+ }
118
+ if (flows?.flows && Object.keys(flows.flows).length > 0) {
119
+ const flowLines = ["## Flows", ""];
120
+ for (const [id, flow] of Object.entries(flows.flows)) {
121
+ const name = flow.name || flow.description || id;
122
+ const trigger = flow.trigger ? ` (trigger: \`${flow.trigger}\`)` : "";
123
+ flowLines.push(`- **$${id}**: ${name}${trigger}`);
124
+ }
125
+ sections.push(flowLines.join("\n"));
126
+ }
127
+ if (portal?.gates && Object.keys(portal.gates).length > 0) {
128
+ const gateLines = ["## Gates", ""];
129
+ gateLines.push("| Gate | Description |");
130
+ gateLines.push("|------|-------------|");
131
+ for (const [id, gate] of Object.entries(portal.gates)) {
132
+ const desc = gate.description || "";
133
+ gateLines.push(`| \`^${id}\` | ${desc} |`);
134
+ }
135
+ if (portal.routes && Object.keys(portal.routes).length > 0) {
136
+ gateLines.push("");
137
+ gateLines.push("### Protected Routes");
138
+ gateLines.push("");
139
+ for (const [route, gates] of Object.entries(portal.routes)) {
140
+ gateLines.push(`- \`${route}\`: ${gates.join(", ")}`);
141
+ }
142
+ }
143
+ sections.push(gateLines.join("\n"));
144
+ }
145
+ const conventions = config.conventions;
146
+ if (conventions && conventions.length > 0) {
147
+ const convLines = ["## Conventions", ""];
148
+ for (const conv of conventions) {
149
+ convLines.push(`- ${conv}`);
150
+ }
151
+ sections.push(convLines.join("\n"));
152
+ }
153
+ const furtherReading = [
154
+ "## Further Reading",
155
+ "",
156
+ "- `.paradigm/specs/` - Detailed specifications",
157
+ "- `.paradigm/docs/` - Commands, patterns, troubleshooting",
158
+ "- `CLAUDE.md` - AI agent instructions (Claude Code)",
159
+ "- `AGENTS.md` - Universal agent instructions"
160
+ ];
161
+ sections.push(furtherReading.join("\n"));
162
+ return sections.join("\n\n") + "\n";
163
+ }
164
+ export {
165
+ syncLlmsCommand
166
+ };
@@ -8,15 +8,16 @@ import {
8
8
  teamModelsCommand,
9
9
  teamResetCommand,
10
10
  teamStatusCommand
11
- } from "./chunk-UM54F7G5.js";
12
- import "./chunk-AD2LSCHB.js";
11
+ } from "./chunk-4N6AYEEA.js";
12
+ import "./chunk-Y4XZWCHK.js";
13
13
  import "./chunk-6QC3YGB6.js";
14
- import "./chunk-WS5KM7OL.js";
14
+ import "./chunk-HPC3JAUP.js";
15
+ import "./chunk-6RNYVBSG.js";
15
16
  import "./chunk-PBHIFAL4.js";
16
- import "./chunk-TAP5N3HH.js";
17
+ import "./chunk-CCG6KYBT.js";
17
18
  import "./chunk-PMXRGPRQ.js";
18
- import "./chunk-5C4SGQKH.js";
19
- import "./chunk-PW2EXJQT.js";
19
+ import "./chunk-6P4IFIK2.js";
20
+ import "./chunk-MRENOFTR.js";
20
21
  import "./chunk-IRKUEJVW.js";
21
22
  import "./chunk-5JGJACDU.js";
22
23
  import "./chunk-MO4EEYFW.js";
@@ -831,6 +831,96 @@ var enableValidation = typeof process !== "undefined" ? process.env.PORTAL_VALID
831
831
  var isTestMode = typeof process !== "undefined" ? process.env.PORTAL_TEST_MODE === "true" : typeof import.meta !== "undefined" && import.meta.env?.VITE_TEST_MODE === "true";
832
832
 
833
833
  // src/commands/portal/test.ts
834
+ function extractPropertiesFromExpression(expr) {
835
+ const propPattern = /\b([a-zA-Z_$][\w$]*(?:\.[a-zA-Z_$][\w$]*)+)/g;
836
+ const matches = /* @__PURE__ */ new Set();
837
+ let match;
838
+ while ((match = propPattern.exec(expr)) !== null) {
839
+ matches.add(match[1]);
840
+ }
841
+ return [...matches];
842
+ }
843
+ function buildEntityFromPath(path4) {
844
+ const parts = path4.split(".");
845
+ const root = {};
846
+ let current = root;
847
+ for (let i = 0; i < parts.length; i++) {
848
+ const part = parts[i];
849
+ if (i === parts.length - 1) {
850
+ current[part] = "test-value";
851
+ } else {
852
+ const next = {};
853
+ current[part] = next;
854
+ current = next;
855
+ }
856
+ }
857
+ return root;
858
+ }
859
+ function deepMerge(target, source) {
860
+ const result = { ...target };
861
+ for (const [key, value] of Object.entries(source)) {
862
+ if (value && typeof value === "object" && !Array.isArray(value) && result[key] && typeof result[key] === "object" && !Array.isArray(result[key])) {
863
+ result[key] = deepMerge(
864
+ result[key],
865
+ value
866
+ );
867
+ } else {
868
+ result[key] = value;
869
+ }
870
+ }
871
+ return result;
872
+ }
873
+ function generateTestCasesFromLocks(gate) {
874
+ const cases = [];
875
+ if (!gate.locks || gate.locks.length === 0) {
876
+ cases.push({
877
+ name: `${gate.id}: no locks (should pass)`,
878
+ entity: { user: { id: "test-user" } },
879
+ expected: true
880
+ });
881
+ return cases;
882
+ }
883
+ let fullEntity = {};
884
+ for (const lock of gate.locks) {
885
+ for (const key of lock.keys) {
886
+ const paths = extractPropertiesFromExpression(key.expression);
887
+ for (const p of paths) {
888
+ const partial = buildEntityFromPath(p);
889
+ fullEntity = deepMerge(fullEntity, partial);
890
+ }
891
+ }
892
+ }
893
+ cases.push({
894
+ name: `${gate.id}: entity satisfying all locks (should pass)`,
895
+ entity: fullEntity,
896
+ expected: true
897
+ });
898
+ for (const lock of gate.locks) {
899
+ const lockPaths = [];
900
+ for (const key of lock.keys) {
901
+ lockPaths.push(...extractPropertiesFromExpression(key.expression));
902
+ }
903
+ if (lockPaths.length > 0) {
904
+ const missingEntity = {};
905
+ for (const otherLock of gate.locks) {
906
+ if (otherLock.id === lock.id) continue;
907
+ for (const key of otherLock.keys) {
908
+ const paths = extractPropertiesFromExpression(key.expression);
909
+ for (const p of paths) {
910
+ const partial = buildEntityFromPath(p);
911
+ Object.assign(missingEntity, deepMerge(missingEntity, partial));
912
+ }
913
+ }
914
+ }
915
+ cases.push({
916
+ name: `${gate.id}: missing lock "${lock.id}" properties (should fail)`,
917
+ entity: gate.locks.length === 1 ? {} : missingEntity,
918
+ expected: false
919
+ });
920
+ }
921
+ }
922
+ return cases;
923
+ }
834
924
  async function gateTestCommand(targetPath, options) {
835
925
  const rootDir = targetPath ? path3.resolve(targetPath) : process.cwd();
836
926
  const gateConfigPath = path3.join(rootDir, "portal.yaml");
@@ -896,14 +986,7 @@ async function gateTestCommand(targetPath, options) {
896
986
  entity: {},
897
987
  expected: false
898
988
  },
899
- {
900
- name: "Entity with required properties",
901
- entity: {
902
- // TODO: Add properties based on gate locks
903
- user: { id: "test-user" }
904
- },
905
- expected: true
906
- }
989
+ ...generateTestCasesFromLocks(gate)
907
990
  ];
908
991
  const result = await validateGateway(options.gate, testCases, client);
909
992
  if (result.passed) {
@@ -5,6 +5,7 @@ import "./chunk-MO4EEYFW.js";
5
5
  import * as fs from "fs";
6
6
  import * as path from "path";
7
7
  import chalk from "chalk";
8
+ import * as yaml from "js-yaml";
8
9
  var THREAD_TEMPLATE = `# Thread - Session Continuity
9
10
 
10
11
  > Pass context between AI agent sessions. Updated by \`paradigm thread save\`.
@@ -24,6 +25,21 @@ var THREAD_TEMPLATE = `# Thread - Session Continuity
24
25
  *Run \`paradigm thread save "message"\` to update*
25
26
  *Run \`paradigm thread clear\` to reset*
26
27
  `;
28
+ function getThreadTrailMax() {
29
+ try {
30
+ const configPath = path.join(process.cwd(), ".paradigm", "config.yaml");
31
+ if (fs.existsSync(configPath)) {
32
+ const content = fs.readFileSync(configPath, "utf8");
33
+ const config = yaml.load(content);
34
+ const limits = config?.limits;
35
+ if (limits?.threadTrailMax && typeof limits.threadTrailMax === "number") {
36
+ return limits.threadTrailMax;
37
+ }
38
+ }
39
+ } catch {
40
+ }
41
+ return 10;
42
+ }
27
43
  function parseThread(content) {
28
44
  const data = {
29
45
  trail: [],
@@ -75,7 +91,7 @@ function generateThread(data) {
75
91
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").split(".")[0];
76
92
  let trailContent = "_No activity recorded yet_";
77
93
  if (data.trail.length > 0) {
78
- trailContent = data.trail.slice(-10).map((entry) => `- ${entry.message}`).join("\n");
94
+ trailContent = data.trail.slice(-getThreadTrailMax()).map((entry) => `- ${entry.message}`).join("\n");
79
95
  }
80
96
  let looseEndsContent = "_No pending tasks_";
81
97
  if (data.looseEnds.length > 0) {
@@ -83,7 +99,7 @@ function generateThread(data) {
83
99
  }
84
100
  let breadcrumbsContent = "_No notes yet_";
85
101
  if (data.breadcrumbs.length > 0) {
86
- breadcrumbsContent = data.breadcrumbs.slice(-10).map((item) => `- ${item}`).join("\n");
102
+ breadcrumbsContent = data.breadcrumbs.slice(-getThreadTrailMax()).map((item) => `- ${item}`).join("\n");
87
103
  }
88
104
  return THREAD_TEMPLATE.replace("{timestamp}", timestamp).replace("{trail}", trailContent).replace("{looseEnds}", looseEndsContent).replace("{breadcrumbs}", breadcrumbsContent);
89
105
  }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  loadLoreEntries
4
- } from "./chunk-MVXJVRFI.js";
4
+ } from "./chunk-5TUAVVIG.js";
5
5
  import "./chunk-MO4EEYFW.js";
6
6
 
7
7
  // src/commands/lore/timeline.ts
@@ -6,10 +6,10 @@ import {
6
6
  StatsCalculator,
7
7
  TimelineBuilder,
8
8
  loadAllSeedPatterns
9
- } from "./chunk-4LGLU2LO.js";
9
+ } from "./chunk-2E2RTBSM.js";
10
10
  import {
11
11
  SentinelStorage
12
- } from "./chunk-VZ7CXFRZ.js";
12
+ } from "./chunk-CRICL4FQ.js";
13
13
  import "./chunk-MO4EEYFW.js";
14
14
 
15
15
  // src/commands/triage/index.ts
@@ -355,7 +355,8 @@
355
355
  "config.yaml defines discipline, conventions, and agent preferences",
356
356
  "navigator.yaml is generated by 'paradigm scan' for fast symbol lookup",
357
357
  "wisdom/ captures team decisions, preferences, and antipatterns",
358
- "portal.yaml lives at the project root, not inside .paradigm/"
358
+ "portal.yaml lives at the project root, not inside .paradigm/",
359
+ "llms.txt at project root is an LLM-readable project summary — regenerate with 'paradigm sync-llms'"
359
360
  ],
360
361
  "quiz": [
361
362
  {