memnant 0.1.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 (151) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +101 -0
  3. package/dist/cli/ask.d.ts +9 -0
  4. package/dist/cli/ask.d.ts.map +1 -0
  5. package/dist/cli/ask.js +103 -0
  6. package/dist/cli/ask.js.map +1 -0
  7. package/dist/cli/check-copy.d.ts +8 -0
  8. package/dist/cli/check-copy.d.ts.map +1 -0
  9. package/dist/cli/check-copy.js +68 -0
  10. package/dist/cli/check-copy.js.map +1 -0
  11. package/dist/cli/check-design.d.ts +8 -0
  12. package/dist/cli/check-design.d.ts.map +1 -0
  13. package/dist/cli/check-design.js +100 -0
  14. package/dist/cli/check-design.js.map +1 -0
  15. package/dist/cli/default-action.d.ts +10 -0
  16. package/dist/cli/default-action.d.ts.map +1 -0
  17. package/dist/cli/default-action.js +94 -0
  18. package/dist/cli/default-action.js.map +1 -0
  19. package/dist/cli/export.d.ts +10 -0
  20. package/dist/cli/export.d.ts.map +1 -0
  21. package/dist/cli/export.js +109 -0
  22. package/dist/cli/export.js.map +1 -0
  23. package/dist/cli/index.d.ts +12 -0
  24. package/dist/cli/index.d.ts.map +1 -0
  25. package/dist/cli/index.js +77 -0
  26. package/dist/cli/index.js.map +1 -0
  27. package/dist/cli/init.d.ts +10 -0
  28. package/dist/cli/init.d.ts.map +1 -0
  29. package/dist/cli/init.js +157 -0
  30. package/dist/cli/init.js.map +1 -0
  31. package/dist/cli/instructions.d.ts +12 -0
  32. package/dist/cli/instructions.d.ts.map +1 -0
  33. package/dist/cli/instructions.js +117 -0
  34. package/dist/cli/instructions.js.map +1 -0
  35. package/dist/cli/lint.d.ts +9 -0
  36. package/dist/cli/lint.d.ts.map +1 -0
  37. package/dist/cli/lint.js +131 -0
  38. package/dist/cli/lint.js.map +1 -0
  39. package/dist/cli/log.d.ts +10 -0
  40. package/dist/cli/log.d.ts.map +1 -0
  41. package/dist/cli/log.js +83 -0
  42. package/dist/cli/log.js.map +1 -0
  43. package/dist/cli/promote.d.ts +9 -0
  44. package/dist/cli/promote.d.ts.map +1 -0
  45. package/dist/cli/promote.js +70 -0
  46. package/dist/cli/promote.js.map +1 -0
  47. package/dist/cli/recall.d.ts +10 -0
  48. package/dist/cli/recall.d.ts.map +1 -0
  49. package/dist/cli/recall.js +98 -0
  50. package/dist/cli/recall.js.map +1 -0
  51. package/dist/cli/serve.d.ts +10 -0
  52. package/dist/cli/serve.d.ts.map +1 -0
  53. package/dist/cli/serve.js +17 -0
  54. package/dist/cli/serve.js.map +1 -0
  55. package/dist/cli/session.d.ts +10 -0
  56. package/dist/cli/session.d.ts.map +1 -0
  57. package/dist/cli/session.js +226 -0
  58. package/dist/cli/session.js.map +1 -0
  59. package/dist/cli/setup.d.ts +11 -0
  60. package/dist/cli/setup.d.ts.map +1 -0
  61. package/dist/cli/setup.js +103 -0
  62. package/dist/cli/setup.js.map +1 -0
  63. package/dist/cli/snapshot.d.ts +9 -0
  64. package/dist/cli/snapshot.d.ts.map +1 -0
  65. package/dist/cli/snapshot.js +126 -0
  66. package/dist/cli/snapshot.js.map +1 -0
  67. package/dist/cli/specs.d.ts +8 -0
  68. package/dist/cli/specs.d.ts.map +1 -0
  69. package/dist/cli/specs.js +96 -0
  70. package/dist/cli/specs.js.map +1 -0
  71. package/dist/cli/status.d.ts +8 -0
  72. package/dist/cli/status.d.ts.map +1 -0
  73. package/dist/cli/status.js +40 -0
  74. package/dist/cli/status.js.map +1 -0
  75. package/dist/cli/telegram.d.ts +8 -0
  76. package/dist/cli/telegram.d.ts.map +1 -0
  77. package/dist/cli/telegram.js +40 -0
  78. package/dist/cli/telegram.js.map +1 -0
  79. package/dist/cli/test-persona.d.ts +9 -0
  80. package/dist/cli/test-persona.d.ts.map +1 -0
  81. package/dist/cli/test-persona.js +176 -0
  82. package/dist/cli/test-persona.js.map +1 -0
  83. package/dist/config/defaults.d.ts +9 -0
  84. package/dist/config/defaults.d.ts.map +1 -0
  85. package/dist/config/defaults.js +56 -0
  86. package/dist/config/defaults.js.map +1 -0
  87. package/dist/context/compile.d.ts +29 -0
  88. package/dist/context/compile.d.ts.map +1 -0
  89. package/dist/context/compile.js +415 -0
  90. package/dist/context/compile.js.map +1 -0
  91. package/dist/governor/copy-check.d.ts +24 -0
  92. package/dist/governor/copy-check.d.ts.map +1 -0
  93. package/dist/governor/copy-check.js +75 -0
  94. package/dist/governor/copy-check.js.map +1 -0
  95. package/dist/governor/design-check.d.ts +20 -0
  96. package/dist/governor/design-check.d.ts.map +1 -0
  97. package/dist/governor/design-check.js +40 -0
  98. package/dist/governor/design-check.js.map +1 -0
  99. package/dist/governor/specs.d.ts +58 -0
  100. package/dist/governor/specs.d.ts.map +1 -0
  101. package/dist/governor/specs.js +183 -0
  102. package/dist/governor/specs.js.map +1 -0
  103. package/dist/ledger/database.d.ts +12 -0
  104. package/dist/ledger/database.d.ts.map +1 -0
  105. package/dist/ledger/database.js +56 -0
  106. package/dist/ledger/database.js.map +1 -0
  107. package/dist/ledger/records.d.ts +19 -0
  108. package/dist/ledger/records.d.ts.map +1 -0
  109. package/dist/ledger/records.js +40 -0
  110. package/dist/ledger/records.js.map +1 -0
  111. package/dist/ledger/sessions.d.ts +15 -0
  112. package/dist/ledger/sessions.d.ts.map +1 -0
  113. package/dist/ledger/sessions.js +54 -0
  114. package/dist/ledger/sessions.js.map +1 -0
  115. package/dist/mcp/server.d.ts +9 -0
  116. package/dist/mcp/server.d.ts.map +1 -0
  117. package/dist/mcp/server.js +295 -0
  118. package/dist/mcp/server.js.map +1 -0
  119. package/dist/orchestrator/context.d.ts +22 -0
  120. package/dist/orchestrator/context.d.ts.map +1 -0
  121. package/dist/orchestrator/context.js +142 -0
  122. package/dist/orchestrator/context.js.map +1 -0
  123. package/dist/orchestrator/providers.d.ts +17 -0
  124. package/dist/orchestrator/providers.d.ts.map +1 -0
  125. package/dist/orchestrator/providers.js +57 -0
  126. package/dist/orchestrator/providers.js.map +1 -0
  127. package/dist/orchestrator/router.d.ts +30 -0
  128. package/dist/orchestrator/router.d.ts.map +1 -0
  129. package/dist/orchestrator/router.js +83 -0
  130. package/dist/orchestrator/router.js.map +1 -0
  131. package/dist/snapshot/scanner.d.ts +63 -0
  132. package/dist/snapshot/scanner.d.ts.map +1 -0
  133. package/dist/snapshot/scanner.js +293 -0
  134. package/dist/snapshot/scanner.js.map +1 -0
  135. package/dist/telegram/bot.d.ts +14 -0
  136. package/dist/telegram/bot.d.ts.map +1 -0
  137. package/dist/telegram/bot.js +139 -0
  138. package/dist/telegram/bot.js.map +1 -0
  139. package/dist/types.d.ts +99 -0
  140. package/dist/types.d.ts.map +1 -0
  141. package/dist/types.js +16 -0
  142. package/dist/types.js.map +1 -0
  143. package/dist/vector/embeddings.d.ts +11 -0
  144. package/dist/vector/embeddings.d.ts.map +1 -0
  145. package/dist/vector/embeddings.js +30 -0
  146. package/dist/vector/embeddings.js.map +1 -0
  147. package/dist/vector/search.d.ts +26 -0
  148. package/dist/vector/search.d.ts.map +1 -0
  149. package/dist/vector/search.js +51 -0
  150. package/dist/vector/search.js.map +1 -0
  151. package/package.json +57 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 peureka
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,101 @@
1
+ # memnant
2
+
3
+ Your agent forgets everything between sessions. memnant is the structured ledger that survives.
4
+
5
+ Context windows die. Conversations end. Three weeks later you're re-explaining decisions your agent already made with you. memnant gives your agent a typed, searchable, staleness-aware decision ledger — and it already knows how to use it.
6
+
7
+ **[memnant.vercel.app](https://memnant.vercel.app)**
8
+
9
+ ## Get started
10
+
11
+ ```bash
12
+ cd your-project
13
+ npx memnant
14
+ ```
15
+
16
+ That's it. First run walks you through setup — project name, agent config, starter specs. Every run after that starts a session and prints compiled context. Open your agent, start building.
17
+
18
+ ## How it works
19
+
20
+ 1. **Run one command.** `npx memnant` in any project. It auto-detects what to do: first time → guided setup, no session → start one, in session → show status.
21
+
22
+ 2. **Open your agent.** memnant registers as an MCP server. Your agent gets 7 tools — recall, log, session context, session close, copy check, design check, status. It already knows when to call them.
23
+
24
+ 3. **Build.** Your agent checks prior decisions before making new ones. Logs what it decides. Catches stale records when the codebase drifts. Closes the session with a summary when you're done — through conversation, not CLI.
25
+
26
+ ## What the agent gets
27
+
28
+ ### Decision Ledger
29
+ Append-only records with vector embeddings. Decisions, framework fixes, spec snapshots — all semantically searchable. The agent calls `memnant_recall` and finds what it needs.
30
+
31
+ ### Session Lifecycle
32
+ Compiled context at session start: last session's log, open TODOs, relevant decisions, framework fixes, spec constraints. Session close happens through the agent via `memnant_session_close`. No CLI needed.
33
+
34
+ ### Staleness Detection
35
+ Codebase snapshots track file hashes. When a file changes after a decision was logged about it, that record is flagged `[stale]` in recall and session context.
36
+
37
+ ### Spec Governor
38
+ Copy audits catch banned phrases. Design system checks catch banned components. The agent validates via MCP tools. Also runs in CI with `memnant lint`.
39
+
40
+ ### Model Orchestrator
41
+ Three tiers: triage (Haiku), analysis (Sonnet), build (Opus). Each gets tier-appropriate context.
42
+
43
+ ## MCP Tools
44
+
45
+ memnant exposes 7 tools via MCP (stdio transport):
46
+
47
+ | Tool | Description |
48
+ |------|-------------|
49
+ | `memnant_recall` | Semantic search across all records |
50
+ | `memnant_log` | Log a decision, framework fix, or session log |
51
+ | `memnant_session_context` | Get compiled session context |
52
+ | `memnant_session_close` | Close the active session with a summary |
53
+ | `memnant_status` | Project status |
54
+ | `memnant_check_copy` | Copy audit against spec |
55
+ | `memnant_check_design` | Design system validation |
56
+
57
+ MCP is auto-configured by `npx memnant` on first run. Works with Claude Code, Codex, and any MCP-compatible agent.
58
+
59
+ ## Advanced CLI
60
+
61
+ All commands are still available for scripts, CI, and power users:
62
+
63
+ ```
64
+ memnant init memnant session start memnant check-copy
65
+ memnant setup claude-code memnant session close memnant check-design
66
+ memnant setup codex memnant session status memnant test-persona
67
+ memnant log memnant snapshot memnant lint
68
+ memnant recall memnant export memnant serve
69
+ memnant ask memnant specs memnant instructions
70
+ ```
71
+
72
+ ## Stack
73
+
74
+ - TypeScript, Node.js (ESM)
75
+ - SQLite via node-sqlite3-wasm
76
+ - Local vector embeddings via @xenova/transformers (all-MiniLM-L6-v2)
77
+ - CLI via Commander.js
78
+ - MCP server via @modelcontextprotocol/sdk
79
+ - 192 tests via vitest
80
+
81
+ ## Development
82
+
83
+ ```bash
84
+ git clone https://github.com/peureka/memnant.git
85
+ cd memnant
86
+ npm install
87
+ npm run build
88
+ npm test
89
+ ```
90
+
91
+ ## Documentation
92
+
93
+ - [`docs/PRODUCT.md`](docs/PRODUCT.md) — What memnant is, what it isn't, why it's different
94
+ - [`docs/SPEC.md`](docs/SPEC.md) — Data model and system behaviours
95
+ - [`docs/PLAN.md`](docs/PLAN.md) — Build plan with epics, stories, and acceptance criteria
96
+ - [`docs/PROJECT_INSTRUCTIONS.md`](docs/PROJECT_INSTRUCTIONS.md) — Decision framework
97
+ - [`docs/PERSONA_KAI.md`](docs/PERSONA_KAI.md) — Primary persona
98
+
99
+ ## License
100
+
101
+ MIT
@@ -0,0 +1,9 @@
1
+ /**
2
+ * memnant ask — Route a task to the appropriate model tier.
3
+ *
4
+ * Story 4.1: Intent classification, tier routing, context injection,
5
+ * and model provider integration.
6
+ */
7
+ import { Command } from 'commander';
8
+ export declare function registerAskCommand(program: Command): void;
9
+ //# sourceMappingURL=ask.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask.d.ts","sourceRoot":"","sources":["../../src/cli/ask.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAqGzD"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * memnant ask — Route a task to the appropriate model tier.
3
+ *
4
+ * Story 4.1: Intent classification, tier routing, context injection,
5
+ * and model provider integration.
6
+ */
7
+ import { existsSync, readFileSync } from 'fs';
8
+ import { join } from 'path';
9
+ import yaml from 'js-yaml';
10
+ import { openDatabase } from '../ledger/database.js';
11
+ import { insertRecord } from '../ledger/records.js';
12
+ import { generateEmbedding, serializeEmbedding } from '../vector/embeddings.js';
13
+ import { getActiveSession } from '../ledger/sessions.js';
14
+ import { classifyIntent, getApiKeyEnvVar } from '../orchestrator/router.js';
15
+ import { callModel } from '../orchestrator/providers.js';
16
+ import { buildTierContext } from '../orchestrator/context.js';
17
+ export function registerAskCommand(program) {
18
+ program
19
+ .command('ask')
20
+ .description('Send a task to memnant for routing and execution')
21
+ .argument('<message>', 'The task or question to route')
22
+ .option('--tier <n>', 'Override automatic tier routing (1, 2, or 3)')
23
+ .option('--dry-run', 'Show routing decision and context without calling the model')
24
+ .action(async (message, opts) => {
25
+ const cwd = process.cwd();
26
+ const configPath = join(cwd, 'memnant.yaml');
27
+ if (!existsSync(configPath)) {
28
+ console.error('No memnant project found. Run `memnant init` first.');
29
+ process.exit(1);
30
+ }
31
+ const config = yaml.load(readFileSync(configPath, 'utf-8'));
32
+ const dbPath = join(cwd, config.memory.db_path);
33
+ if (!existsSync(dbPath)) {
34
+ console.error(`Ledger database not found at ${config.memory.db_path}. Run \`memnant init\` to recreate.`);
35
+ process.exit(1);
36
+ }
37
+ // Determine tier
38
+ let tier;
39
+ let routingReason;
40
+ if (opts.tier) {
41
+ const n = parseInt(opts.tier, 10);
42
+ if (![1, 2, 3].includes(n)) {
43
+ console.error(`Invalid tier '${opts.tier}'. Must be 1, 2, or 3.`);
44
+ process.exit(1);
45
+ }
46
+ tier = n;
47
+ routingReason = 'manual override';
48
+ }
49
+ else {
50
+ const routing = classifyIntent(message);
51
+ tier = routing.tier;
52
+ routingReason = routing.reason;
53
+ }
54
+ // Get tier config
55
+ const tierNames = { 1: 'triage', 2: 'analysis', 3: 'build' };
56
+ const tierName = tierNames[tier];
57
+ const tierConfig = config.orchestrator.tiers[tierName];
58
+ // Check API key
59
+ const envVar = getApiKeyEnvVar(tierConfig.provider);
60
+ if (!process.env[envVar]) {
61
+ console.error(`Set ${envVar} to use Tier ${tier}.`);
62
+ process.exit(1);
63
+ }
64
+ const db = openDatabase(dbPath);
65
+ try {
66
+ // Build context
67
+ const docsPath = join(cwd, config.governor.docs_path);
68
+ const ctx = await buildTierContext(db, config, tier, message, docsPath, cwd);
69
+ // Dry run — show routing and context
70
+ if (opts.dryRun) {
71
+ console.log(`Tier: ${tier} (${tierName})`);
72
+ console.log(`Reason: ${routingReason}`);
73
+ console.log(`Model: ${tierConfig.provider}/${tierConfig.model}`);
74
+ console.log(`Context: ~${ctx.tokenEstimate} tokens, ${ctx.recordCount} records`);
75
+ console.log('');
76
+ console.log(ctx.systemPrompt);
77
+ return;
78
+ }
79
+ // Call model
80
+ const response = await callModel(tierConfig, ctx.systemPrompt, message);
81
+ // Log orchestrator_task record
82
+ const taskSummary = `Task: ${message}\nTier: ${tier} (${tierName})\nModel: ${tierConfig.model}\nResponse: ${response.text.slice(0, 500)}`;
83
+ const taskEmbedding = await generateEmbedding(taskSummary);
84
+ const taskEmbeddingBuffer = serializeEmbedding(taskEmbedding);
85
+ const activeSession = getActiveSession(db, config.project.id);
86
+ insertRecord(db, {
87
+ projectId: config.project.id,
88
+ type: 'orchestrator_task',
89
+ contentText: taskSummary,
90
+ embedding: taskEmbeddingBuffer,
91
+ sourceSession: activeSession?.id ?? null,
92
+ });
93
+ // Output response
94
+ console.log(response.text);
95
+ console.log('');
96
+ console.log(`[Tier ${tier}: ${tierConfig.model}, ~${response.input_tokens + response.output_tokens} tokens, ${ctx.recordCount} records injected]`);
97
+ }
98
+ finally {
99
+ db.close();
100
+ }
101
+ });
102
+ }
103
+ //# sourceMappingURL=ask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask.js","sourceRoot":"","sources":["../../src/cli/ask.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * memnant check-copy — Copy audit check command.
3
+ *
4
+ * Story 5.2: Checks text against copy audit rules.
5
+ */
6
+ import { Command } from 'commander';
7
+ export declare function registerCheckCopyCommand(program: Command): void;
8
+ //# sourceMappingURL=check-copy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-copy.d.ts","sourceRoot":"","sources":["../../src/cli/check-copy.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6D/D"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * memnant check-copy — Copy audit check command.
3
+ *
4
+ * Story 5.2: Checks text against copy audit rules.
5
+ */
6
+ import { existsSync, readFileSync } from 'fs';
7
+ import { join } from 'path';
8
+ import yaml from 'js-yaml';
9
+ import { checkCopy } from '../governor/copy-check.js';
10
+ import { scanSpecs } from '../governor/specs.js';
11
+ export function registerCheckCopyCommand(program) {
12
+ program
13
+ .command('check-copy')
14
+ .description('Check text against the copy audit spec')
15
+ .argument('[text]', 'Text to check (or use --file)')
16
+ .option('--file <path>', 'Check an entire file')
17
+ .action((text, opts) => {
18
+ const cwd = process.cwd();
19
+ const configPath = join(cwd, 'memnant.yaml');
20
+ if (!existsSync(configPath)) {
21
+ console.error('No memnant project found. Run `memnant init` first.');
22
+ process.exit(1);
23
+ }
24
+ const config = yaml.load(readFileSync(configPath, 'utf-8'));
25
+ const docsPath = join(cwd, config.governor.docs_path);
26
+ // Check if copy audit spec exists
27
+ const specs = scanSpecs(docsPath);
28
+ const copySpec = specs.find((s) => s.frontmatter.type === 'copy_audit');
29
+ if (!copySpec) {
30
+ console.log(`No copy audit spec found in ${config.governor.docs_path}. Create one with type: copy_audit frontmatter.`);
31
+ return;
32
+ }
33
+ // Get text to check
34
+ let content;
35
+ if (opts.file) {
36
+ const filePath = join(cwd, opts.file);
37
+ if (!existsSync(filePath)) {
38
+ console.error(`File not found: ${opts.file}`);
39
+ process.exit(1);
40
+ }
41
+ content = readFileSync(filePath, 'utf-8');
42
+ }
43
+ else if (text) {
44
+ content = text;
45
+ }
46
+ else if (!process.stdin.isTTY) {
47
+ content = readFileSync(0, 'utf-8');
48
+ }
49
+ else {
50
+ console.error('Provide text as an argument, via --file, or pipe from stdin.');
51
+ process.exit(1);
52
+ }
53
+ const result = checkCopy(content, docsPath);
54
+ if (result.violations.length === 0) {
55
+ console.log('No copy violations found.');
56
+ return;
57
+ }
58
+ for (const v of result.violations) {
59
+ const lineInfo = v.line ? `:${v.line}` : '';
60
+ const prefix = opts.file ? `${opts.file}${lineInfo} ` : '';
61
+ console.log(`${prefix}${v.message}`);
62
+ }
63
+ if (result.hasBanned) {
64
+ process.exit(1);
65
+ }
66
+ });
67
+ }
68
+ //# sourceMappingURL=check-copy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-copy.js","sourceRoot":"","sources":["../../src/cli/check-copy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * memnant check-design — Design system validation command.
3
+ *
4
+ * Story 5.3: Scans source files for banned components from the design system spec.
5
+ */
6
+ import { Command } from 'commander';
7
+ export declare function registerCheckDesignCommand(program: Command): void;
8
+ //# sourceMappingURL=check-design.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-design.d.ts","sourceRoot":"","sources":["../../src/cli/check-design.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2DjE"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * memnant check-design — Design system validation command.
3
+ *
4
+ * Story 5.3: Scans source files for banned components from the design system spec.
5
+ */
6
+ import { existsSync, readFileSync, readdirSync, statSync } from 'fs';
7
+ import { join, relative } from 'path';
8
+ import yaml from 'js-yaml';
9
+ import { checkDesign } from '../governor/design-check.js';
10
+ import { scanSpecs } from '../governor/specs.js';
11
+ export function registerCheckDesignCommand(program) {
12
+ program
13
+ .command('check-design')
14
+ .description('Check source files for banned components from the design system spec')
15
+ .argument('<path>', 'File or directory to check')
16
+ .action((targetPath) => {
17
+ const cwd = process.cwd();
18
+ const configPath = join(cwd, 'memnant.yaml');
19
+ if (!existsSync(configPath)) {
20
+ console.error('No memnant project found. Run `memnant init` first.');
21
+ process.exit(1);
22
+ }
23
+ const config = yaml.load(readFileSync(configPath, 'utf-8'));
24
+ const docsPath = join(cwd, config.governor.docs_path);
25
+ // Check if design system spec exists
26
+ const specs = scanSpecs(docsPath);
27
+ const designSpec = specs.find((s) => s.frontmatter.type === 'design_system');
28
+ if (!designSpec) {
29
+ console.log(`No design system spec found in ${config.governor.docs_path}. Create one with type: design_system frontmatter.`);
30
+ return;
31
+ }
32
+ const absPath = join(cwd, targetPath);
33
+ if (!existsSync(absPath)) {
34
+ console.error(`Path not found: ${targetPath}`);
35
+ process.exit(1);
36
+ }
37
+ const allViolations = [];
38
+ const stat = statSync(absPath);
39
+ if (stat.isFile()) {
40
+ const code = readFileSync(absPath, 'utf-8');
41
+ const result = checkDesign(code, targetPath, docsPath);
42
+ allViolations.push(...result.violations);
43
+ }
44
+ else if (stat.isDirectory()) {
45
+ const files = collectSourceFiles(absPath);
46
+ for (const file of files) {
47
+ const relPath = relative(cwd, file);
48
+ const code = readFileSync(file, 'utf-8');
49
+ const result = checkDesign(code, relPath, docsPath);
50
+ allViolations.push(...result.violations);
51
+ }
52
+ }
53
+ if (allViolations.length === 0) {
54
+ console.log('No design system violations found.');
55
+ return;
56
+ }
57
+ for (const v of allViolations) {
58
+ console.log(`${v.file}:${v.line} ${v.message}`);
59
+ }
60
+ process.exit(1);
61
+ });
62
+ }
63
+ const SOURCE_EXTENSIONS = new Set([
64
+ '.ts', '.tsx', '.js', '.jsx', '.vue', '.svelte',
65
+ '.html', '.css', '.scss',
66
+ ]);
67
+ function collectSourceFiles(dir) {
68
+ const results = [];
69
+ const skipDirs = new Set(['node_modules', '.git', '.memnant', 'dist', '.next']);
70
+ let entries;
71
+ try {
72
+ entries = readdirSync(dir);
73
+ }
74
+ catch {
75
+ return results;
76
+ }
77
+ for (const entry of entries) {
78
+ if (skipDirs.has(entry))
79
+ continue;
80
+ const absPath = join(dir, entry);
81
+ let stat;
82
+ try {
83
+ stat = statSync(absPath);
84
+ }
85
+ catch {
86
+ continue;
87
+ }
88
+ if (stat.isDirectory()) {
89
+ results.push(...collectSourceFiles(absPath));
90
+ }
91
+ else if (stat.isFile()) {
92
+ const ext = entry.slice(entry.lastIndexOf('.'));
93
+ if (SOURCE_EXTENSIONS.has(ext)) {
94
+ results.push(absPath);
95
+ }
96
+ }
97
+ }
98
+ return results;
99
+ }
100
+ //# sourceMappingURL=check-design.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-design.js","sourceRoot":"","sources":["../../src/cli/check-design.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * memnant default action — State detection and routing.
3
+ *
4
+ * Story 6.1: When `memnant` is invoked with no subcommand, detect state and route:
5
+ * 1. No memnant.yaml → run interactive init
6
+ * 2. memnant.yaml exists, no active session → start session + print context
7
+ * 3. Active session exists → show session status
8
+ */
9
+ export declare function defaultAction(): Promise<void>;
10
+ //# sourceMappingURL=default-action.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-action.d.ts","sourceRoot":"","sources":["../../src/cli/default-action.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAWH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CA6EnD"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * memnant default action — State detection and routing.
3
+ *
4
+ * Story 6.1: When `memnant` is invoked with no subcommand, detect state and route:
5
+ * 1. No memnant.yaml → run interactive init
6
+ * 2. memnant.yaml exists, no active session → start session + print context
7
+ * 3. Active session exists → show session status
8
+ */
9
+ import { existsSync, readFileSync } from 'fs';
10
+ import { join } from 'path';
11
+ import yaml from 'js-yaml';
12
+ import { openDatabase } from '../ledger/database.js';
13
+ import { createSession, getActiveSession, getSessionRecordCounts } from '../ledger/sessions.js';
14
+ import { compileContext, formatContextAsMarkdown } from '../context/compile.js';
15
+ import { getLastSnapshotDate } from '../snapshot/scanner.js';
16
+ export async function defaultAction() {
17
+ const cwd = process.cwd();
18
+ const configPath = join(cwd, 'memnant.yaml');
19
+ // State 1: Not initialised → run init
20
+ if (!existsSync(configPath)) {
21
+ // Import init module and invoke directly
22
+ const initModule = await import('./init.js');
23
+ // Trigger init via registered command by re-parsing with 'init' arg
24
+ const { Command } = await import('commander');
25
+ const tempProgram = new Command();
26
+ tempProgram.exitOverride(); // Don't call process.exit
27
+ initModule.registerInitCommand(tempProgram);
28
+ await tempProgram.parseAsync(['init'], { from: 'user' });
29
+ return;
30
+ }
31
+ const config = yaml.load(readFileSync(configPath, 'utf-8'));
32
+ const dbPath = join(cwd, config.memory.db_path);
33
+ if (!existsSync(dbPath)) {
34
+ console.error(`Ledger database not found at ${config.memory.db_path}. Run \`memnant init\` to recreate.`);
35
+ process.exit(1);
36
+ }
37
+ const db = openDatabase(dbPath);
38
+ try {
39
+ const active = getActiveSession(db, config.project.id);
40
+ if (active) {
41
+ // State 3: Active session → show status
42
+ const duration = formatDuration(new Date(active.started_at), new Date());
43
+ const counts = getSessionRecordCounts(db, active.id);
44
+ const total = Object.values(counts).reduce((a, b) => a + b, 0);
45
+ console.log(`Session: ${active.id.slice(0, 8)}`);
46
+ console.log(`Started: ${active.started_at.slice(0, 19).replace('T', ' ')}`);
47
+ console.log(`Duration: ${duration}`);
48
+ if (active.epic) {
49
+ console.log(`Epic: ${active.epic}`);
50
+ }
51
+ console.log(`Records: ${total}`);
52
+ if (total > 0) {
53
+ for (const [type, count] of Object.entries(counts)) {
54
+ console.log(` ${type}: ${count}`);
55
+ }
56
+ }
57
+ }
58
+ else {
59
+ // State 2: No active session → start session + print context
60
+ const docsPath = join(cwd, config.governor.docs_path);
61
+ const ctx = compileContext(db, { docsPath, projectRoot: cwd });
62
+ // Snapshot age reminder
63
+ if (config.memory.snapshot_interval === 'monthly') {
64
+ const lastDate = getLastSnapshotDate(db);
65
+ if (lastDate) {
66
+ const daysSince = Math.floor((Date.now() - new Date(lastDate).getTime()) / (1000 * 60 * 60 * 24));
67
+ if (daysSince > 30) {
68
+ ctx.warnings.push(`Last codebase snapshot is ${daysSince} days old. Run \`memnant snapshot\` to update staleness tracking.`);
69
+ }
70
+ }
71
+ }
72
+ const session = createSession(db, config.project.id);
73
+ process.stderr.write(`Session ${session.id.slice(0, 8)} started.\n`);
74
+ console.log(formatContextAsMarkdown(ctx));
75
+ }
76
+ }
77
+ finally {
78
+ db.close();
79
+ }
80
+ }
81
+ function formatDuration(start, end) {
82
+ const ms = end.getTime() - start.getTime();
83
+ const seconds = Math.floor(ms / 1000);
84
+ const minutes = Math.floor(seconds / 60);
85
+ const hours = Math.floor(minutes / 60);
86
+ if (hours > 0) {
87
+ return `${hours}h ${minutes % 60}m`;
88
+ }
89
+ if (minutes > 0) {
90
+ return `${minutes}m ${seconds % 60}s`;
91
+ }
92
+ return `${seconds}s`;
93
+ }
94
+ //# sourceMappingURL=default-action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-action.js","sourceRoot":"","sources":["../../src/cli/default-action.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * memnant export — Export the ledger to portable formats.
3
+ *
4
+ * Story 1.5: Exports all records as markdown (one file per record, organised
5
+ * by type subdirectory) or as a single JSON file. Supports --since date filtering.
6
+ * Export is a full snapshot — previous files are overwritten.
7
+ */
8
+ import { Command } from 'commander';
9
+ export declare function registerExportCommand(program: Command): void;
10
+ //# sourceMappingURL=export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../src/cli/export.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyBpC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoE5D"}