@mnemosyne_os/forge 1.2.2 → 1.2.3
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/README.md +233 -230
- package/dist/cli.js +145 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,230 +1,233 @@
|
|
|
1
|
-
<div align="center">
|
|
2
|
-
|
|
3
|
-
```
|
|
4
|
-
███╗ ███╗███╗ ██╗███████╗███╗ ███╗ ██████╗ ███████╗ ██████╗ ██████╗ ██████╗ ███████╗
|
|
5
|
-
████╗ ████║████╗ ██║██╔════╝████╗ ████║██╔═══██╗██╔════╝██╔═══██╗██╔══██╗██╔════╝ ██╔════╝
|
|
6
|
-
██╔████╔██║██╔██╗ ██║█████╗ ██╔████╔██║██║ ██║█████╗ ██║ ██║██████╔╝██║ ███╗█████╗
|
|
7
|
-
██║╚██╔╝██║██║╚██╗██║██╔══╝ ██║╚██╔╝██║██║ ██║██╔══╝ ██║ ██║██╔══██╗██║ ██║██╔══╝
|
|
8
|
-
██║ ╚═╝ ██║██║ ╚████║███████╗██║ ╚═╝ ██║╚██████╔╝██║ ╚██████╔╝██║ ██║╚██████╔╝███████╗
|
|
9
|
-
╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
**MnemoForge CLI** — The Inception Engine of the Mnemosyne Neural OS
|
|
13
|
-
|
|
14
|
-
[](https://www.npmjs.com/package/@mnemosyne_os/forge)
|
|
15
|
+
[](#)
|
|
16
|
+
[](./LICENSE)
|
|
17
|
+
[](https://www.typescriptlang.org/)
|
|
18
|
+
[](https://nodejs.org/)
|
|
19
|
+
[](https://github.com/yaka0007/Mnemosyne-Neural-OS)
|
|
20
|
+
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
> **⚠️ This package is in active beta development.** APIs and commands may change between minor versions. We are using it in production on Mnemosyne OS itself — feedback and issues welcome.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## What is MnemoForge?
|
|
28
|
+
|
|
29
|
+
**MnemoForge** is the official CLI for the [Mnemosyne Neural OS](https://github.com/yaka0007/Mnemosyne-Neural-OS) ecosystem.
|
|
30
|
+
|
|
31
|
+
It gives AI agents something they fundamentally lack: **persistent, versionable, IDE-agnostic memory**.
|
|
32
|
+
|
|
33
|
+
Every time an agent starts a new session, it starts from zero. MnemoForge fixes this with two systems:
|
|
34
|
+
|
|
35
|
+
| System | Purpose |
|
|
36
|
+
|---|---|
|
|
37
|
+
| **Chronicles** | Structured memory files capturing key decisions and sessions |
|
|
38
|
+
| **Workspace / Resonance Project** | Project-level rules that any agent reads at session start |
|
|
39
|
+
|
|
40
|
+
> **"Don't just scaffold code. Scaffold intelligence."**
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Install
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm install -g @mnemosyne_os/forge
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Verify:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
mnemoforge --version
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Quick Start
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# 1. Initialize the vault (once per machine)
|
|
62
|
+
mnemoforge chronicle init
|
|
63
|
+
|
|
64
|
+
# 2. Set up a Workspace (ecosystem / org)
|
|
65
|
+
mnemoforge workspace init
|
|
66
|
+
# → Workspace name: Mnemosyne-OS
|
|
67
|
+
|
|
68
|
+
# 3. Create a Resonance Project (feature / component)
|
|
69
|
+
mnemoforge project init
|
|
70
|
+
# → Project: CLI
|
|
71
|
+
# → Chronicles vault: ~/MnemoVault/Mnemosyne-OS/CLI/Antigravity/Anthropic/
|
|
72
|
+
|
|
73
|
+
# 4. Check workspace rules before starting work (agent briefing)
|
|
74
|
+
mnemoforge workspace show
|
|
75
|
+
|
|
76
|
+
# 5. Archive a chronicle written by your agent
|
|
77
|
+
mnemoforge chronicle archive --file "handbook/chronicles/CHRONICLE-2026-04-05-my-decision.md"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Core Concepts
|
|
83
|
+
|
|
84
|
+
### Chronicles
|
|
85
|
+
|
|
86
|
+
Chronicles are structured Markdown files that capture key decisions, sessions, and architectural moments.
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
CHRONICLE-YYYY-MM-DD-short-slug.md
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
They are written by the AI agent at the moment a decision is made — not after. They are archived into a structured vault organized by Workspace → Project → IDE → Provider.
|
|
93
|
+
|
|
94
|
+
**Chronicle styles:** `session` · `decision` · `reflection` · `sweep` · `narcissus`
|
|
95
|
+
|
|
96
|
+
### Workspace & Resonance Project
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
MnemoVault/
|
|
100
|
+
Mnemosyne-OS/ ← Workspace (ecosystem)
|
|
101
|
+
CLI/ ← Resonance Project (feature)
|
|
102
|
+
Antigravity/ ← IDE
|
|
103
|
+
Anthropic/ ← Provider
|
|
104
|
+
CHRONICLE-...md
|
|
105
|
+
Dashboard/
|
|
106
|
+
...
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The `WORKSPACE.json` file stores project-level rules readable by any agent at session start — independent of any IDE, cloud, or session state.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Commands
|
|
114
|
+
|
|
115
|
+
### Scaffold
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
mnemoforge init [module-name] # scaffold a new Mnemosyne module
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Chronicle (Memory)
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
mnemoforge chronicle init # configure vault (IDE, provider, path)
|
|
125
|
+
mnemoforge chronicle archive --file <path> # archive an agent-written chronicle
|
|
126
|
+
mnemoforge chronicle commit # create a chronicle interactively or --auto
|
|
127
|
+
mnemoforge chronicle list # list chronicles in the vault
|
|
128
|
+
mnemoforge chronicle sweep # generate a daily consolidation chronicle
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Workspace
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
mnemoforge workspace init # create WORKSPACE.json in the current project
|
|
135
|
+
mnemoforge workspace show # display rules as an agent briefing
|
|
136
|
+
mnemoforge workspace add-rule "<rule>" [--section <section>]
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Resonance Project
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
mnemoforge project init # link workspace + project + scaffold handbook/chronicles/
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Neural Coding
|
|
148
|
+
|
|
149
|
+
MnemoForge implements **Neural Coding** — a development methodology where:
|
|
150
|
+
|
|
151
|
+
- The **human** holds the intention and understands the system
|
|
152
|
+
- The **agent** understands the context and executes without mechanical re-explanations
|
|
153
|
+
- The **memory** persists outside of any IDE, session, or conversation
|
|
154
|
+
|
|
155
|
+
The code follows the thought. Not the other way around.
|
|
156
|
+
|
|
157
|
+
→ [Read the Neural Coding definition](https://github.com/yaka0007/Mnemosyne-Neural-OS/tree/main/cli/docs/04-neural-coding.md)
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Documentation
|
|
162
|
+
|
|
163
|
+
Full documentation available in the [cli/docs](https://github.com/yaka0007/Mnemosyne-Neural-OS/tree/main/cli/docs) folder:
|
|
164
|
+
|
|
165
|
+
- [Getting Started](https://github.com/yaka0007/Mnemosyne-Neural-OS/blob/main/cli/docs/01-getting-started.md)
|
|
166
|
+
- [Chronicle System](https://github.com/yaka0007/Mnemosyne-Neural-OS/blob/main/cli/docs/02-chronicle.md)
|
|
167
|
+
- [Workspace Memory](https://github.com/yaka0007/Mnemosyne-Neural-OS/blob/main/cli/docs/03-workspace.md)
|
|
168
|
+
- [Neural Coding Principles](https://github.com/yaka0007/Mnemosyne-Neural-OS/blob/main/cli/docs/04-neural-coding.md)
|
|
169
|
+
- [Command Reference](https://github.com/yaka0007/Mnemosyne-Neural-OS/blob/main/cli/docs/05-command-reference.md)
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Roadmap
|
|
174
|
+
|
|
175
|
+
- [x] `mnemoforge init` — module scaffolding with AI governance injection
|
|
176
|
+
- [x] `mnemoforge chronicle init/archive/commit/list/sweep` — agent memory vault
|
|
177
|
+
- [x] `mnemoforge workspace init/show/add-rule` — project safety memory
|
|
178
|
+
- [x] `mnemoforge project init` — Resonance Project hierarchy
|
|
179
|
+
- [ ] `mnemoforge workspace watcher` — auto-archive chronicles on file creation
|
|
180
|
+
- [ ] `mnemoforge canvas` — deploy pre-configured project templates
|
|
181
|
+
- [ ] Chronicle certification — cryptographic signature (Neural Coding P5)
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Development
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
git clone https://github.com/yaka0007/Mnemosyne-Neural-OS.git
|
|
189
|
+
cd Mnemosyne-Neural-OS/cli
|
|
190
|
+
npm install
|
|
191
|
+
npm run build
|
|
192
|
+
npm link
|
|
193
|
+
mnemoforge --version
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Tech Stack
|
|
199
|
+
|
|
200
|
+
| Layer | Technology |
|
|
201
|
+
|---|---|
|
|
202
|
+
| Runtime | Node.js 18+ |
|
|
203
|
+
| Language | TypeScript 5 (strict) |
|
|
204
|
+
| CLI Framework | Commander.js v11 |
|
|
205
|
+
| Prompts | Inquirer.js v8 |
|
|
206
|
+
| Output Styling | Chalk v4 |
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## License
|
|
211
|
+
|
|
212
|
+
MIT © 2026 [XPACEGEMS LLC](https://xpacegems.com) — Tony Trochet
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## About
|
|
217
|
+
|
|
218
|
+
**XPACEGEMS LLC** — Independent AI Software Lab
|
|
219
|
+
Miami, FL 33122, USA
|
|
220
|
+
Founder & Lead Architect: [Tony Trochet](https://www.linkedin.com/in/tony-t-19544650/)
|
|
221
|
+
|
|
222
|
+
Built as part of **Mnemosyne Neural OS** — a sovereign AI operating system.
|
|
223
|
+
Powered by **Antigravity (Google DeepMind)** · **Claude (Anthropic)** · **Cursor**
|
|
224
|
+
|
|
225
|
+
> *"The model may not know who it is. The soul does."*
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
<div align="center">
|
|
230
|
+
|
|
231
|
+
**[⭐ Star on GitHub](https://github.com/yaka0007/Mnemosyne-Neural-OS)** · **[📖 Documentation](https://github.com/yaka0007/Mnemosyne-Neural-OS/tree/main/cli/docs)** · **[🐛 Report Issues](https://github.com/yaka0007/Mnemosyne-Neural-OS/issues)**
|
|
232
|
+
|
|
233
|
+
</div>
|
package/dist/cli.js
CHANGED
|
@@ -521,16 +521,153 @@ chronicle
|
|
|
521
521
|
console.log(chalk_1.default.red('\n ✖ Not initialized. Run: mnemoforge chronicle init\n'));
|
|
522
522
|
process.exit(1);
|
|
523
523
|
}
|
|
524
|
-
const
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
524
|
+
const { resolveChronicleDir } = require('./lib/vault.js');
|
|
525
|
+
const dir = resolveChronicleDir(config);
|
|
526
|
+
const all = (0, vault_js_1.listChronicles)(config);
|
|
527
|
+
const chronicles = all.slice(0, parseInt(opts.count || '10'));
|
|
528
|
+
// ── Color palette ──────────────────────────────────
|
|
529
|
+
const TYPE_COLORS = {
|
|
530
|
+
session: chalk_1.default.hex('#60A5FA'), // blue
|
|
531
|
+
decision: chalk_1.default.hex('#FB923C'), // orange
|
|
532
|
+
reflection: chalk_1.default.hex('#C084FC'), // purple
|
|
533
|
+
sweep: chalk_1.default.hex('#94A3B8'), // slate
|
|
534
|
+
narcissus: chalk_1.default.hex('#FBBF24'), // gold
|
|
535
|
+
};
|
|
536
|
+
const TYPE_ICONS = {
|
|
537
|
+
session: '◈',
|
|
538
|
+
decision: '◆',
|
|
539
|
+
reflection: '◇',
|
|
540
|
+
sweep: '↻',
|
|
541
|
+
narcissus: '✦',
|
|
542
|
+
};
|
|
543
|
+
// ── Helper: parse chronicle metadata from first lines ──
|
|
544
|
+
const parseChronicle = (filename) => {
|
|
545
|
+
const filePath = path_1.default.join(dir, filename);
|
|
546
|
+
const rawSlug = filename.replace(/^CHRONICLE-\d{4}-\d{2}-\d{2}-/, '').replace(/\.md$/, '').replace(/-/g, ' ');
|
|
547
|
+
let title = rawSlug.charAt(0).toUpperCase() + rawSlug.slice(1);
|
|
548
|
+
let type = 'session';
|
|
549
|
+
let tags = [];
|
|
550
|
+
let excerpt = '';
|
|
551
|
+
const dateMatch = filename.match(/CHRONICLE-(\d{4}-\d{2}-\d{2})/);
|
|
552
|
+
let date = dateMatch ? dateMatch[1] : '';
|
|
553
|
+
try {
|
|
554
|
+
const raw = fs_1.default.readFileSync(filePath, 'utf8');
|
|
555
|
+
// Stop before <!--resonance block
|
|
556
|
+
const resonanceIdx = raw.indexOf('<!--resonance');
|
|
557
|
+
const content = resonanceIdx !== -1 ? raw.slice(0, resonanceIdx) : raw;
|
|
558
|
+
const lines = content.split('\n');
|
|
559
|
+
let inFrontmatter = false;
|
|
560
|
+
let frontmatterDone = false;
|
|
561
|
+
let dividerCount = 0;
|
|
562
|
+
const bodyLines = [];
|
|
563
|
+
for (const line of lines.slice(0, 40)) {
|
|
564
|
+
const l = line.trim();
|
|
565
|
+
// YAML frontmatter block (file starts with ---)
|
|
566
|
+
if (l === '---' && !frontmatterDone) {
|
|
567
|
+
dividerCount++;
|
|
568
|
+
if (dividerCount === 1) {
|
|
569
|
+
inFrontmatter = true;
|
|
570
|
+
continue;
|
|
571
|
+
}
|
|
572
|
+
if (dividerCount === 2) {
|
|
573
|
+
inFrontmatter = false;
|
|
574
|
+
frontmatterDone = true;
|
|
575
|
+
continue;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
if (inFrontmatter) {
|
|
579
|
+
// Extract from YAML frontmatter
|
|
580
|
+
if (l.startsWith('title:'))
|
|
581
|
+
title = l.replace('title:', '').trim().replace(/^['"]|['"]$/g, '');
|
|
582
|
+
if (l.startsWith('type:'))
|
|
583
|
+
type = l.replace('type:', '').trim();
|
|
584
|
+
if (l.startsWith('date:') && l.match(/\d{4}-\d{2}-\d{2}/))
|
|
585
|
+
date = l.match(/\d{4}-\d{2}-\d{2}/)[0];
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
588
|
+
// Structured chronicle format (** bold fields **)
|
|
589
|
+
if (l.startsWith('# ')) {
|
|
590
|
+
title = l.slice(2).trim();
|
|
591
|
+
continue;
|
|
592
|
+
}
|
|
593
|
+
if (l.startsWith('**Type**:')) {
|
|
594
|
+
type = l.replace('**Type**:', '').trim().toLowerCase();
|
|
595
|
+
continue;
|
|
596
|
+
}
|
|
597
|
+
if (l.startsWith('**Date**:')) {
|
|
598
|
+
const d = l.replace('**Date**:', '').trim();
|
|
599
|
+
if (d.match(/\d{4}-\d{2}-\d{2}/))
|
|
600
|
+
date = d.match(/\d{4}-\d{2}-\d{2}/)[0];
|
|
601
|
+
continue;
|
|
602
|
+
}
|
|
603
|
+
if (l.match(/^\*\*\w/))
|
|
604
|
+
continue; // skip any other **Field**: lines
|
|
605
|
+
if (l.match(/^#[a-z]/i) && !l.startsWith('# ')) {
|
|
606
|
+
tags = l.match(/#\w+/g) ?? [];
|
|
607
|
+
continue;
|
|
608
|
+
}
|
|
609
|
+
// Body content — skip dividers, metadata-looking lines, empty
|
|
610
|
+
if (l === '---')
|
|
611
|
+
continue;
|
|
612
|
+
if (l.match(/^\w[\w_\s]+:\s+\S/))
|
|
613
|
+
continue; // skip key: value lines
|
|
614
|
+
// Only push real body lines — skip headings, YAML-like keys
|
|
615
|
+
if (l.length > 8 && frontmatterDone && !l.startsWith('#') && !l.match(/^[\w_]+:\s*/))
|
|
616
|
+
bodyLines.push(l);
|
|
617
|
+
}
|
|
618
|
+
// For structured chronicles (no YAML), body is after the header divider
|
|
619
|
+
if (!frontmatterDone) {
|
|
620
|
+
// Find content between the two horizontal rules
|
|
621
|
+
const dividers = lines.reduce((acc, l, i) => l.trim() === '---' ? [...acc, i] : acc, []);
|
|
622
|
+
if (dividers.length >= 2) {
|
|
623
|
+
const between = lines.slice(dividers[0] + 1, dividers[1]);
|
|
624
|
+
for (const l of between) {
|
|
625
|
+
const lt = l.trim();
|
|
626
|
+
if (lt.length > 8 && !lt.startsWith('**') && !lt.startsWith('#') && !lt.match(/^[\w_]+:\s*/))
|
|
627
|
+
bodyLines.push(lt);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
const firstMeaningful = bodyLines.find(l => l.length > 10);
|
|
632
|
+
if (firstMeaningful)
|
|
633
|
+
excerpt = firstMeaningful.slice(0, 92) + (firstMeaningful.length > 92 ? '…' : '');
|
|
634
|
+
}
|
|
635
|
+
catch { /* file unreadable — use defaults */ }
|
|
636
|
+
return { title, type, tags, excerpt, date };
|
|
637
|
+
};
|
|
638
|
+
// ── Separator ──────────────────────────────────────
|
|
639
|
+
const SEP = chalk_1.default.hex('#312E81')(' ' + '─'.repeat(72));
|
|
640
|
+
// ── Header ────────────────────────────────────────
|
|
641
|
+
console.log(chalk_1.default.hex('#8B5CF6').bold(`\n ⬡ MnemoChronicle — Vault\n`));
|
|
642
|
+
if (config.workspace && config.resonanceProject) {
|
|
643
|
+
console.log(chalk_1.default.gray(' Workspace : ') + chalk_1.default.hex('#A78BFA')(config.workspace) +
|
|
644
|
+
chalk_1.default.gray(' · Project : ') + chalk_1.default.hex('#A78BFA')(config.resonanceProject));
|
|
529
645
|
}
|
|
530
|
-
|
|
531
|
-
|
|
646
|
+
console.log(chalk_1.default.gray(' Agent : ') + chalk_1.default.white(config.ide) + chalk_1.default.gray(' / ') + chalk_1.default.white(config.provider));
|
|
647
|
+
console.log(chalk_1.default.gray(` Vault : `) + chalk_1.default.hex('#64748B')(dir));
|
|
648
|
+
console.log(chalk_1.default.gray(` Total : `) + chalk_1.default.white(String(all.length)) + chalk_1.default.gray(` chronicles · showing ${chronicles.length}\n`));
|
|
649
|
+
console.log(SEP);
|
|
650
|
+
// ── Chronicle cards ───────────────────────────────
|
|
651
|
+
chronicles.forEach((filename, i) => {
|
|
652
|
+
const { title, type, tags, excerpt, date } = parseChronicle(filename);
|
|
653
|
+
const typeColor = TYPE_COLORS[type] ?? chalk_1.default.white;
|
|
654
|
+
const icon = TYPE_ICONS[type] ?? '○';
|
|
655
|
+
const badge = typeColor(`[${type}]`);
|
|
656
|
+
const num = chalk_1.default.hex('#6B7280')(String(i + 1).padStart(2, ' '));
|
|
657
|
+
console.log(`\n ${num} ${badge} ` +
|
|
658
|
+
chalk_1.default.hex('#94A3B8')('📅 ') + chalk_1.default.hex('#CBD5E1')(date) +
|
|
659
|
+
chalk_1.default.hex('#475569')(' ') + typeColor(icon));
|
|
660
|
+
console.log(chalk_1.default.white(` ${title}`));
|
|
661
|
+
if (excerpt) {
|
|
662
|
+
console.log(chalk_1.default.hex('#64748B')(` "${excerpt}"`));
|
|
663
|
+
}
|
|
664
|
+
if (tags.length > 0) {
|
|
665
|
+
const tagStr = tags.map(t => chalk_1.default.hex('#7C3AED')(t)).join(' ');
|
|
666
|
+
console.log(' ' + tagStr);
|
|
667
|
+
}
|
|
532
668
|
});
|
|
533
|
-
console.log();
|
|
669
|
+
console.log('\n' + SEP + '\n');
|
|
670
|
+
console.log(chalk_1.default.gray(' Tip: ') + chalk_1.default.white('mnemoforge chronicle list -n 20') + chalk_1.default.gray(' to show more\n'));
|
|
534
671
|
});
|
|
535
672
|
// ── chronicle switch ───────────────────────────────────────────
|
|
536
673
|
chronicle
|
package/package.json
CHANGED