@latysh-development/monolith 0.1.0-alpha.0 → 0.1.0-alpha.2

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 (114) hide show
  1. package/README.md +63 -16
  2. package/dist/brief/collect.d.ts.map +1 -1
  3. package/dist/brief/collect.js +41 -1
  4. package/dist/brief/constants.d.ts +2 -0
  5. package/dist/brief/constants.d.ts.map +1 -1
  6. package/dist/brief/constants.js +2 -0
  7. package/dist/brief/render.d.ts +7 -0
  8. package/dist/brief/render.d.ts.map +1 -1
  9. package/dist/brief/render.js +52 -1
  10. package/dist/brief/types.d.ts +17 -1
  11. package/dist/brief/types.d.ts.map +1 -1
  12. package/dist/cli/index.js +45 -0
  13. package/dist/discovery/compose.d.ts +28 -0
  14. package/dist/discovery/compose.d.ts.map +1 -0
  15. package/dist/discovery/compose.js +159 -0
  16. package/dist/discovery/contracts.d.ts +211 -0
  17. package/dist/discovery/contracts.d.ts.map +1 -0
  18. package/dist/discovery/contracts.js +555 -0
  19. package/dist/discovery/docs.d.ts +278 -0
  20. package/dist/discovery/docs.d.ts.map +1 -0
  21. package/dist/discovery/docs.js +1182 -0
  22. package/dist/discovery/facts.d.ts +49 -0
  23. package/dist/discovery/facts.d.ts.map +1 -0
  24. package/dist/discovery/facts.js +541 -0
  25. package/dist/discovery/index.d.ts +8 -0
  26. package/dist/discovery/index.d.ts.map +1 -0
  27. package/dist/discovery/index.js +9 -0
  28. package/dist/discovery/orchestrate.d.ts +35 -0
  29. package/dist/discovery/orchestrate.d.ts.map +1 -0
  30. package/dist/discovery/orchestrate.js +32 -0
  31. package/dist/discovery/render.d.ts +36 -0
  32. package/dist/discovery/render.d.ts.map +1 -0
  33. package/dist/discovery/render.js +278 -0
  34. package/dist/discovery/traverse.d.ts +197 -0
  35. package/dist/discovery/traverse.d.ts.map +1 -0
  36. package/dist/discovery/traverse.js +510 -0
  37. package/dist/durable/errors.d.ts +6 -2
  38. package/dist/durable/errors.d.ts.map +1 -1
  39. package/dist/durable/errors.js +9 -3
  40. package/dist/durable/fs-store.d.ts +21 -0
  41. package/dist/durable/fs-store.d.ts.map +1 -1
  42. package/dist/durable/fs-store.js +103 -3
  43. package/dist/durable/prune-check.d.ts +17 -0
  44. package/dist/durable/prune-check.d.ts.map +1 -1
  45. package/dist/durable/prune-check.js +27 -0
  46. package/dist/durable/runtime.d.ts +5 -3
  47. package/dist/durable/runtime.d.ts.map +1 -1
  48. package/dist/durable/runtime.js +23 -6
  49. package/dist/durable/seams.d.ts +4 -0
  50. package/dist/durable/seams.d.ts.map +1 -1
  51. package/dist/durable/testing.js +2 -2
  52. package/dist/finalize/cli.d.ts +10 -0
  53. package/dist/finalize/cli.d.ts.map +1 -0
  54. package/dist/finalize/cli.js +134 -0
  55. package/dist/finalize/core.d.ts +108 -0
  56. package/dist/finalize/core.d.ts.map +1 -0
  57. package/dist/finalize/core.js +767 -0
  58. package/dist/finalize/index.d.ts +5 -0
  59. package/dist/finalize/index.d.ts.map +1 -0
  60. package/dist/finalize/index.js +2 -0
  61. package/dist/finalize/proposal.d.ts +97 -0
  62. package/dist/finalize/proposal.d.ts.map +1 -0
  63. package/dist/finalize/proposal.js +213 -0
  64. package/dist/ideas/cli.d.ts +33 -0
  65. package/dist/ideas/cli.d.ts.map +1 -0
  66. package/dist/ideas/cli.js +158 -0
  67. package/dist/ideas/format.d.ts +38 -0
  68. package/dist/ideas/format.d.ts.map +1 -0
  69. package/dist/ideas/format.js +194 -0
  70. package/dist/ideas/index.d.ts +6 -0
  71. package/dist/ideas/index.d.ts.map +1 -0
  72. package/dist/ideas/index.js +3 -0
  73. package/dist/ideas/store.d.ts +55 -0
  74. package/dist/ideas/store.d.ts.map +1 -0
  75. package/dist/ideas/store.js +262 -0
  76. package/dist/ideas/types.d.ts +54 -0
  77. package/dist/ideas/types.d.ts.map +1 -0
  78. package/dist/ideas/types.js +26 -0
  79. package/dist/index.d.ts +1 -0
  80. package/dist/index.d.ts.map +1 -1
  81. package/dist/index.js +2 -0
  82. package/dist/init/scaffold.d.ts +4 -0
  83. package/dist/init/scaffold.d.ts.map +1 -1
  84. package/dist/init/scaffold.js +6 -2
  85. package/dist/managed/index.d.ts +73 -0
  86. package/dist/managed/index.d.ts.map +1 -0
  87. package/dist/managed/index.js +222 -0
  88. package/dist/root/index.d.ts +7 -0
  89. package/dist/root/index.d.ts.map +1 -1
  90. package/dist/root/index.js +13 -1
  91. package/dist/update/cli.d.ts +8 -0
  92. package/dist/update/cli.d.ts.map +1 -0
  93. package/dist/update/cli.js +115 -0
  94. package/dist/update/index.d.ts +78 -0
  95. package/dist/update/index.d.ts.map +1 -0
  96. package/dist/update/index.js +285 -0
  97. package/dist/version.d.ts +1 -1
  98. package/dist/version.js +1 -1
  99. package/package.json +1 -1
  100. package/templates/default-instance/instruction/.cursorrules +6 -0
  101. package/templates/default-instance/instruction/.windsurfrules +6 -0
  102. package/templates/default-instance/instruction/CLAUDE.md +4 -0
  103. package/templates/default-instance/managed/agent.md +20 -0
  104. package/templates/default-instance/managed/bootstrap.md +7 -0
  105. package/templates/default-instance/managed/index-idea.md +5 -0
  106. package/templates/default-instance/managed/routing-idea.md +14 -0
  107. package/templates/default-instance/monolith/AGENT.md +1 -0
  108. package/templates/default-instance/monolith/context/maps/routing-map.md +4 -0
  109. package/templates/default-instance/monolith/context/maps/semantic-map.md +2 -0
  110. package/templates/default-instance/monolith/memory/working/active.md +11 -0
  111. package/templates/default-instance/monolith/skills/INDEX.md +4 -0
  112. package/templates/default-instance/monolith/skills/finalize-story/SKILL.md +51 -1
  113. package/templates/default-instance/monolith/skills/idea-capture/SKILL.md +157 -0
  114. package/templates/default-instance/projectroot/AGENTS.md +4 -0
package/README.md CHANGED
@@ -29,34 +29,64 @@ decisions — instead of relying on an assistant's unaided memory.
29
29
 
30
30
  ## Why MONOLITH?
31
31
 
32
- AI assistants lose context between sessions, and what a project "knows" ends up
33
- scattered across chats, notes and habits. MONOLITH keeps that knowledge in the
34
- project itself, in a form both a person and an assistant can read, check and
35
- trust — using mechanisms that are deterministic and testable.
32
+ You are deep in a task when a good idea arrives — one that has nothing to do
33
+ with what you are doing right now. Switching to it would break your focus, so
34
+ you postpone it. A few hours later it is buried in a long chat, or simply gone.
35
+
36
+ A conversation history is a poor place to keep it. It is tied to one session,
37
+ it is hard to search, and an AI assistant that starts a new session does not
38
+ carry it over. A thought that only lives in a chat lasts as long as the chat.
39
+
40
+ MONOLITH keeps that knowledge in the project itself: ideas, structured project
41
+ context and recorded decisions, as plain Markdown that both a person and an
42
+ assistant can read, check and commit. You save the idea, and keep working.
43
+
44
+ > **Your AI assistant may forget the conversation. Your project shouldn't forget the ideas.**
45
+
46
+ Ideas are where MONOLITH started, not where it ends: the same approach — durable,
47
+ inspectable, deterministic — also covers project state and execution governance.
36
48
 
37
49
  ## What MONOLITH Does
38
50
 
51
+ - **Idea Capture** — save a thought that is unrelated to the current task, without losing focus. You decide what to save; ideas are stored as one Markdown file each in `.monolith/memory/long-term/ideas/`, independent of the active story, and are managed with `monolith idea add|list|show` or by an assistant that follows your project's instructions.
39
52
  - **Observable** — `monolith brief` summarizes project state in the terminal, including whether it looks stale; Mission Control shows it in a local, read-only web interface.
40
53
  - **Structured** — structure is extracted from a project's own markdown (frontmatter, headings, explicit links) into an explicit relationship graph. No embeddings, no LLM, no fuzzy matching.
41
54
  - **Governed** — protocols, skills and cognitive modes describe how an assistant reads and updates project memory; missions and checkpoints record progress. This is a recorded discipline, not a runtime gate.
42
55
  - **Reproducible** — same input, same output. State lives in a schema-versioned file written with a lock and atomic replace; Durable State adds a hash-chained event log.
43
56
  - **Bounded** — managed files are read and written through strict primitives that refuse symlinks; `monolith validate` never executes project code; Mission Control has no write endpoint.
44
57
 
58
+ ## Idea Capture Example
59
+
60
+ ```bash
61
+ monolith idea add \
62
+ --title 'Automatic Tool Tests' \
63
+ --description 'Generate tests from business tool contracts'
64
+
65
+ monolith idea list
66
+ monolith idea show IDEA-001
67
+ ```
68
+
69
+ `IDEA-001` is a demonstration ID; the real ID is printed by `idea add`, and
70
+ `idea list` shows every saved idea.
71
+
72
+ With an AI assistant, you can simply say: *"Save this idea for later."* The
73
+ assistant then saves it by running `monolith idea add` — it does not edit idea
74
+ files itself. This works because `monolith init` installs instructions and an
75
+ `idea-capture` skill for the assistant; it is not guaranteed for an arbitrary
76
+ model without that setup. Details and limits: [`monolith idea` in the CLI reference](./docs/reference/cli.md#monolith-idea).
77
+
78
+ Ideas are saved and recalled **manually**. There is no automatic idea detection,
79
+ no automatic recall or reminders, no idea status management and no idea UI yet.
80
+
45
81
  ## Quick Start
46
82
 
47
- Requires Node.js >= 20. MONOLITH is an alpha package that is **not published
48
- to npm**. Build it from a clone:
83
+ Requires Node.js >= 20. Install the published alpha package from npm:
49
84
 
50
85
  ```bash
51
- git clone https://github.com/Demion-L/the_monolith.git
52
- cd the_monolith
53
- pnpm install
54
- pnpm build
55
- npm link # exposes the `monolith` command (or run: node dist/cli/index.js)
86
+ npm install -g @latysh-development/monolith@alpha
56
87
  ```
57
88
 
58
- Once the first alpha is published, `npm install -g @latysh-development/monolith@alpha`
59
- becomes the primary install path ([release notes](./docs/release/alpha-installation.md)).
89
+ To build from source instead, see the [installation and release guide](./docs/release/alpha-installation.md).
60
90
 
61
91
  Then, in a project directory:
62
92
 
@@ -71,6 +101,23 @@ monolith ui # Mission Control at http://127.0.0.1:4173 ; Ctrl+C to stop
71
101
  instance, and it does not open a browser — open the printed address yourself.
72
102
  All commands: [CLI reference](./docs/reference/cli.md).
73
103
 
104
+ ## Updating an Existing Project
105
+
106
+ If a project was initialised with an earlier MONOLITH version, bring it up to the current agent integration (agent entry point and Idea Capture) with:
107
+
108
+ ```bash
109
+ monolith update # preview: shows the plan, writes nothing
110
+ monolith update --apply # applies the safe changes
111
+ ```
112
+
113
+ - The first command only prints a plan and does not modify the project.
114
+ - The second applies the safe changes (missing MONOLITH-owned files and managed blocks).
115
+ - Your project memory (`active.md`, `decisions.md`, roadmap, stories, ideas) and your own files are preserved.
116
+ - A managed block you have edited is never overwritten automatically.
117
+ - On a conflict the command writes nothing to that file and reports that manual resolution is required.
118
+
119
+ Details and the full list of verdicts: [`monolith update` in the CLI reference](./docs/reference/cli.md#monolith-update).
120
+
74
121
  ## Architecture
75
122
 
76
123
  ```text
@@ -104,7 +151,7 @@ listing — not an official partnership, endorsement or certification.
104
151
 
105
152
  ## Documentation
106
153
 
107
- - [CLI reference](./docs/reference/cli.md) — every command, `init`, `validate`, `brief`, `mission`, `durable`, `ui`
154
+ - [CLI reference](./docs/reference/cli.md) — every command, `init`, `validate`, `brief`, `idea`, `mission`, `durable`, `ui`
108
155
  - [Mission Control](./docs/reference/mission-control.md) — sections, LIVE/DEMO, skins, limitations
109
156
  - [Security & Limitations](./docs/reference/security-and-limitations.md) — threat model, platform and filesystem caveats
110
157
  - [Programmatic API](./docs/reference/write-scope-api.md) · [Development](./docs/reference/development.md)
@@ -113,8 +160,8 @@ listing — not an official partnership, endorsement or certification.
113
160
 
114
161
  ## Project Status
115
162
 
116
- **Alpha** (`0.1.0-alpha.0`). The API and CLI are experimental and may change
117
- without notice. Not published to npm. Durable State and the Coordinatorium
163
+ **Alpha** (`0.1.0-alpha.2`). The API and CLI are experimental and may change
164
+ without notice. Published to npm under the alpha dist-tag. Durable State and the Coordinatorium
118
165
  (`monolith durable`, `monolith mission`) are experimental and are not part of
119
166
  the Quick Start.
120
167
 
@@ -1 +1 @@
1
- {"version":3,"file":"collect.d.ts","sourceRoot":"","sources":["../../src/brief/collect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAwBH,OAAO,KAAK,EACV,UAAU,EAMX,MAAM,YAAY,CAAC;AAepB,kFAAkF;AAClF,eAAO,MAAM,wBAAwB,QAAa,CAAC;AAsRnD,wBAAsB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAkEpE"}
1
+ {"version":3,"file":"collect.d.ts","sourceRoot":"","sources":["../../src/brief/collect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAwBH,OAAO,KAAK,EACV,UAAU,EAOX,MAAM,YAAY,CAAC;AAiBpB,kFAAkF;AAClF,eAAO,MAAM,wBAAwB,QAAa,CAAC;AA8TnD,wBAAsB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAqEpE"}
@@ -18,9 +18,11 @@ import { discoverDocs } from './docs.js';
18
18
  import { extractCurrentStory } from './story.js';
19
19
  import { selectActiveMissions, selectRecentFinishedMissions, selectLatestCheckpoint, hasCheckpointOrderMismatch, } from './selectors.js';
20
20
  import { stateFilePath, validateState, createInitialState, MAX_STATE_BYTES } from '../coordinatorium/index.js';
21
- import { ACTIVE_MD_REL, PROTOCOLS_DIR, ROADMAP_INDEX_REL, STORY_INDEX_REL, HANDOFF_REL } from './constants.js';
21
+ import { ACTIVE_MD_REL, PARKED_IDEAS_LIMIT, PROTOCOLS_DIR, ROADMAP_INDEX_REL, STORY_INDEX_REL, HANDOFF_REL } from './constants.js';
22
22
  import { evaluateFreshness, parseActiveStoryClaim, parseRoadmapActiveStory, parseRoadmapStatuses, parseStoryIndexStatuses, } from './freshness.js';
23
23
  import { readGitSignals } from './git-signals.js';
24
+ import { ideaStore, listIdeas } from '../ideas/index.js';
25
+ import { ideaNumber } from '../ideas/format.js';
24
26
  const RECENT_FINISHED_MISSIONS_LIMIT = 5;
25
27
  /** SEC-001B.1: `active.md` is a short hand-written context file (~3 KB today). */
26
28
  export const MAX_ACTIVE_CONTEXT_BYTES = 256 * 1024;
@@ -211,6 +213,42 @@ function collectStory(targetDir, monolithRoot, root, diagnostics) {
211
213
  provenance: { source: extraction.lineRange ? `${relPath}:${extraction.lineRange}` : relPath },
212
214
  };
213
215
  }
216
+ const IDEAS_UNREADABLE_LISTED = 3;
217
+ /**
218
+ * IDEA-002A: the `inbox` ideas, via the Idea Capture reader (`listIdeas`: bounded,
219
+ * symlink/hardlink/special-file refusing, never writes). A file that cannot be read
220
+ * as an idea is not counted and is reported as one warning — it never breaks the
221
+ * brief. Idea content is untrusted; only ids and titles are kept.
222
+ */
223
+ function collectParkedIdeas(targetDir, diagnostics) {
224
+ const empty = { total: 0, items: [] };
225
+ let entries;
226
+ try {
227
+ entries = listIdeas(ideaStore(targetDir));
228
+ }
229
+ catch (err) {
230
+ const code = err instanceof Error && 'code' in err ? String(err.code) : 'ERROR';
231
+ diagnostics.push({
232
+ code: 'IDEAS_UNREADABLE',
233
+ severity: 'warn',
234
+ message: `The ideas directory was not read (${code}); parked ideas are not shown.`,
235
+ });
236
+ return empty;
237
+ }
238
+ const inbox = entries.flatMap((e) => (e.ok && e.idea.status === 'inbox' ? [e.idea] : []));
239
+ inbox.sort((a, b) => ideaNumber(b.id) - ideaNumber(a.id));
240
+ const bad = entries.flatMap((e) => (e.ok ? [] : [e]));
241
+ if (bad.length > 0) {
242
+ const listed = bad.slice(0, IDEAS_UNREADABLE_LISTED).map((e) => `${e.id} (${e.code})`).join(', ');
243
+ const more = bad.length > IDEAS_UNREADABLE_LISTED ? `, and ${bad.length - IDEAS_UNREADABLE_LISTED} more` : '';
244
+ diagnostics.push({
245
+ code: 'IDEAS_UNREADABLE',
246
+ severity: 'warn',
247
+ message: `${bad.length} idea file(s) could not be read and are not counted as parked: ${listed}${more}. Run \`monolith idea show <id>\`.`,
248
+ });
249
+ }
250
+ return { total: inbox.length, items: inbox.slice(0, PARKED_IDEAS_LIMIT).map((i) => ({ id: i.id, title: i.title })) };
251
+ }
214
252
  /**
215
253
  * Best-effort read of one state document for the freshness check. A missing,
216
254
  * refused or unreadable file simply contributes no evidence — freshness never
@@ -286,6 +324,7 @@ export async function collect(targetDir) {
286
324
  items: discoverDocs(targetDir, adrDirs, (fields) => fields.get('status') === 'accepted', diagnostics),
287
325
  provenance: { source: adrDirs.join(', ') },
288
326
  };
327
+ const parkedIdeas = monolithInitialized ? collectParkedIdeas(targetDir, diagnostics) : { total: 0, items: [] };
289
328
  return {
290
329
  identity,
291
330
  monolithInitialized,
@@ -295,6 +334,7 @@ export async function collect(targetDir) {
295
334
  story,
296
335
  mandatoryProtocols,
297
336
  adrs,
337
+ parkedIdeas,
298
338
  diagnostics,
299
339
  freshness,
300
340
  freshnessEvidence,
@@ -7,4 +7,6 @@ export declare const PROTOCOLS_DIR = "protocols";
7
7
  export declare const ROADMAP_INDEX_REL = "context/maps/roadmap-index.md";
8
8
  export declare const STORY_INDEX_REL = "memory/working/story-index.md";
9
9
  export declare const HANDOFF_REL = "context/boot/HANDOFF.md";
10
+ /** IDEA-002A: most parked ideas the brief ever lists; the rest is a "+N more" count. */
11
+ export declare const PARKED_IDEAS_LIMIT = 3;
10
12
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/brief/constants.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,eAAO,MAAM,aAAa,6BAA6B,CAAC;AACxD,sIAAsI;AACtI,eAAO,MAAM,eAAe,aAAa,CAAC;AAC1C,eAAO,MAAM,aAAa,cAAc,CAAC;AACzC,qGAAqG;AACrG,eAAO,MAAM,iBAAiB,kCAAkC,CAAC;AACjE,eAAO,MAAM,eAAe,kCAAkC,CAAC;AAC/D,eAAO,MAAM,WAAW,4BAA4B,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/brief/constants.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,eAAO,MAAM,aAAa,6BAA6B,CAAC;AACxD,sIAAsI;AACtI,eAAO,MAAM,eAAe,aAAa,CAAC;AAC1C,eAAO,MAAM,aAAa,cAAc,CAAC;AACzC,qGAAqG;AACrG,eAAO,MAAM,iBAAiB,kCAAkC,CAAC;AACjE,eAAO,MAAM,eAAe,kCAAkC,CAAC;AAC/D,eAAO,MAAM,WAAW,4BAA4B,CAAC;AACrD,wFAAwF;AACxF,eAAO,MAAM,kBAAkB,IAAI,CAAC"}
@@ -7,3 +7,5 @@ export const PROTOCOLS_DIR = 'protocols';
7
7
  export const ROADMAP_INDEX_REL = 'context/maps/roadmap-index.md';
8
8
  export const STORY_INDEX_REL = 'memory/working/story-index.md';
9
9
  export const HANDOFF_REL = 'context/boot/HANDOFF.md';
10
+ /** IDEA-002A: most parked ideas the brief ever lists; the rest is a "+N more" count. */
11
+ export const PARKED_IDEAS_LIMIT = 3;
@@ -48,6 +48,13 @@
48
48
  * two forces INCOMPLETE. P0 is never dropped. All project-controlled
49
49
  * strings, provenance pointers included, pass through
50
50
  * `sanitizeSingleLine` (N-1).
51
+ *
52
+ * Advisory section (IDEA-002B): Parked Ideas is the one data-holding section whose
53
+ * budget degradation does NOT force INCOMPLETE. It is user-saved side context, not
54
+ * project state; its degradation stays visible (fewer items, count, or a marker
55
+ * whenever they fit) but `Completeness` and `--strict` keep describing only the
56
+ * project context that existed before ideas did. Unreadable idea files are
57
+ * reported by the `IDEAS_UNREADABLE` warning, which is not an error.
51
58
  */
52
59
  import type { BriefModel } from './types.js';
53
60
  export declare const DEFAULT_MAX_CHARS = 6000;
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/brief/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAsE,MAAM,YAAY,CAAC;AAYjH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAGtC,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,YAAY,CAAC;AAErD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,YAAY,CAAC;CAC5B;AAiVD,wBAAgB,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,GAAE,MAA0B,GAAG,YAAY,CAsE5F"}
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/brief/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AAEH,OAAO,KAAK,EAAE,UAAU,EAA0F,MAAM,YAAY,CAAC;AAYrI,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAGtC,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,YAAY,CAAC;AAErD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,YAAY,CAAC;CAC5B;AAwXD,wBAAgB,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,GAAE,MAA0B,GAAG,YAAY,CAgF5F"}
@@ -48,8 +48,15 @@
48
48
  * two forces INCOMPLETE. P0 is never dropped. All project-controlled
49
49
  * strings, provenance pointers included, pass through
50
50
  * `sanitizeSingleLine` (N-1).
51
+ *
52
+ * Advisory section (IDEA-002B): Parked Ideas is the one data-holding section whose
53
+ * budget degradation does NOT force INCOMPLETE. It is user-saved side context, not
54
+ * project state; its degradation stays visible (fewer items, count, or a marker
55
+ * whenever they fit) but `Completeness` and `--strict` keep describing only the
56
+ * project context that existed before ideas did. Unreadable idea files are
57
+ * reported by the `IDEAS_UNREADABLE` warning, which is not an error.
51
58
  */
52
- import { ACTIVE_MD_REL } from './constants.js';
59
+ import { ACTIVE_MD_REL, PARKED_IDEAS_LIMIT } from './constants.js';
53
60
  import { sanitizeSingleLine, sanitizeMultiLine } from './sanitize.js';
54
61
  // Shorthand for the existing single-line sanitizer — applied to every string
55
62
  // that originates in project files or configuration (N-1), including
@@ -352,6 +359,41 @@ function fitItemList(header, items, footer, remaining, omittedMarkerFn, minimalF
352
359
  }
353
360
  return { text: '', consumed: 0, lossFlag: true };
354
361
  }
362
+ const PARKED_IDEA_TITLE_MAX = 80;
363
+ function formatParkedIdea(i) {
364
+ const title = san(i.title);
365
+ const shown = title.length > PARKED_IDEA_TITLE_MAX ? `${title.slice(0, PARKED_IDEA_TITLE_MAX - 1).replace(/[\ud800-\udbff]$/, '')}…` : title;
366
+ return ` ${san(i.id)} ${shown}\n`;
367
+ }
368
+ /**
369
+ * IDEA-002A: Parked Ideas — the lowest-priority section. Nothing at all when there
370
+ * are none (so a project without ideas renders exactly as before). Under budget
371
+ * pressure it first lists fewer ideas, then only the count, then a one-line
372
+ * marker, then nothing. Each step is flagged in `lossFlag`, but `render` does not
373
+ * count it towards Completeness (advisory section, see the Completeness contract).
374
+ * Listing at most `PARKED_IDEAS_LIMIT` ideas is the design, not a loss.
375
+ */
376
+ function buildParkedIdeasSection(ideas, remaining) {
377
+ if (!ideas || ideas.total === 0)
378
+ return { text: '', consumed: 0, lossFlag: false };
379
+ const header = `\n## Parked Ideas (${ideas.total})\n`;
380
+ const explore = ' Explore: `monolith idea list`\n';
381
+ const wanted = Math.min(PARKED_IDEAS_LIMIT, ideas.items.length);
382
+ const noun = (n) => (n === 1 ? 'idea' : 'ideas');
383
+ const candidates = [];
384
+ for (let k = wanted; k >= 1; k--) {
385
+ const rest = ideas.total - k;
386
+ const body = ideas.items.slice(0, k).map(formatParkedIdea).join('');
387
+ const more = rest > 0 ? `\n +${rest} more ${noun(rest)}\n` : '';
388
+ const text = header + body + more + explore;
389
+ candidates.push({ text, consumed: text.length, lossFlag: k < wanted });
390
+ }
391
+ const countOnly = `${header} ${ideas.total} ${noun(ideas.total)}, not listed (budget)\n${explore}`;
392
+ const marker = `\n[Parked Ideas (${ideas.total}) omitted — budget; \`monolith idea list\`]\n`;
393
+ for (const text of [countOnly, marker, BARE_OMIT_MARKER])
394
+ candidates.push({ text, consumed: text.length, lossFlag: true });
395
+ return candidates.find((c) => c.consumed <= remaining) ?? { text: '', consumed: 0, lossFlag: true };
396
+ }
355
397
  const P3_TEXT = '\n## More\n' +
356
398
  ' Full checkpoint history: `monolith mission checkpoints <id>`\n' +
357
399
  ' Mission detail: `monolith mission show <id>`\n' +
@@ -394,6 +436,15 @@ export function render(model, maxChars = DEFAULT_MAX_CHARS) {
394
436
  p2 += finishedSection.text;
395
437
  remaining -= finishedSection.consumed;
396
438
  budgetLoss = budgetLoss || finishedSection.lossFlag;
439
+ // Parked ideas are optional extra context: they get what is left after everything
440
+ // else, and never the room the static P3 pointer block would have had. Their
441
+ // budget loss is shown locally (fewer ideas / count / marker) but deliberately does
442
+ // not feed `budgetLoss`: saving an idea must not flip an unchanged project's brief
443
+ // to INCOMPLETE and break `--strict` checks of the main project context.
444
+ const p3Fits = P3_TEXT.length <= remaining;
445
+ const ideasSection = buildParkedIdeasSection(model.parkedIdeas, p3Fits ? remaining - P3_TEXT.length : remaining);
446
+ p2 += ideasSection.text;
447
+ remaining -= ideasSection.consumed;
397
448
  if (P3_TEXT.length <= remaining) {
398
449
  p3 = P3_TEXT;
399
450
  remaining -= p3.length;
@@ -17,7 +17,7 @@ export type DiagnosticSeverity = 'info' | 'warn' | 'error';
17
17
  * budget decision is made, which is what lets render() reserve space for
18
18
  * them deterministically (see render.ts's two-phase budget accounting).
19
19
  */
20
- export type BriefDiagnosticCode = 'MONOLITH_NOT_INITIALIZED' | 'STATE_NOT_INITIALIZED' | 'STATE_EMPTY' | 'STATE_UNREADABLE' | 'STATE_LEGACY_SCHEMA_MIGRATED' | 'MULTIPLE_ACTIVE_MISSIONS' | 'CHECKPOINT_ORDER_MISMATCH' | 'ACTIVE_MD_MISSING' | 'ACTIVE_MD_REJECTED' | 'ACTIVE_MD_UNREADABLE' | 'ACTIVE_MD_NO_CURRENT_STORY' | 'CONFIG_UNREADABLE' | 'CONFIG_ADR_DIRS_INVALID' | 'DOC_DIR_UNREADABLE' | 'DOC_FILE_UNREADABLE' | 'DOC_DIR_OUTSIDE_PROJECT' | 'PATH_OUTSIDE_PROJECT' | 'WRITE_ARTIFACTS_PRESENT';
20
+ export type BriefDiagnosticCode = 'MONOLITH_NOT_INITIALIZED' | 'STATE_NOT_INITIALIZED' | 'STATE_EMPTY' | 'STATE_UNREADABLE' | 'STATE_LEGACY_SCHEMA_MIGRATED' | 'MULTIPLE_ACTIVE_MISSIONS' | 'CHECKPOINT_ORDER_MISMATCH' | 'ACTIVE_MD_MISSING' | 'ACTIVE_MD_REJECTED' | 'ACTIVE_MD_UNREADABLE' | 'ACTIVE_MD_NO_CURRENT_STORY' | 'CONFIG_UNREADABLE' | 'CONFIG_ADR_DIRS_INVALID' | 'DOC_DIR_UNREADABLE' | 'DOC_FILE_UNREADABLE' | 'DOC_DIR_OUTSIDE_PROJECT' | 'PATH_OUTSIDE_PROJECT' | 'WRITE_ARTIFACTS_PRESENT' | 'IDEAS_UNREADABLE';
21
21
  export interface BriefDiagnostic {
22
22
  code: BriefDiagnosticCode;
23
23
  severity: DiagnosticSeverity;
@@ -84,6 +84,20 @@ export interface ProjectIdentity {
84
84
  monolithRoot: string;
85
85
  provenance: Provenance;
86
86
  }
87
+ /** IDEA-002A: one parked (status `inbox`) idea, as shown by the brief. */
88
+ export interface ParkedIdeaRef {
89
+ id: string;
90
+ title: string;
91
+ }
92
+ /**
93
+ * IDEA-002A: the `inbox` ideas, projected from the Idea Capture store (never
94
+ * re-parsed here). `items` holds at most `PARKED_IDEAS_LIMIT` entries, newest
95
+ * numeric id first; `total` counts every readable `inbox` idea.
96
+ */
97
+ export interface ParkedIdeasSummary {
98
+ total: number;
99
+ items: ParkedIdeaRef[];
100
+ }
87
101
  export interface BriefModel {
88
102
  identity: ProjectIdentity;
89
103
  monolithInitialized: boolean;
@@ -93,6 +107,8 @@ export interface BriefModel {
93
107
  story: StorySummary;
94
108
  mandatoryProtocols: ProtocolIndex;
95
109
  adrs: AdrIndex;
110
+ /** IDEA-002A: optional so a hand-built model without it renders as before. */
111
+ parkedIdeas?: ParkedIdeasSummary;
96
112
  /** Collect-time diagnostics, in deterministic (collection-order) sequence. */
97
113
  diagnostics: BriefDiagnostic[];
98
114
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/brief/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/brief/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEzE,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3D;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAC3B,0BAA0B,GAC1B,uBAAuB,GACvB,aAAa,GACb,kBAAkB,GAClB,8BAA8B,GAC9B,0BAA0B,GAC1B,2BAA2B,GAC3B,mBAAmB,GACnB,oBAAoB,GACpB,sBAAsB,GACtB,4BAA4B,GAC5B,mBAAmB,GACnB,yBAAyB,GACzB,oBAAoB,GACpB,qBAAqB,GACrB,yBAAyB,GACzB,sBAAsB,GACtB,yBAAyB,GACzB,kBAAkB,CAAC;AAEvB,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,QAAQ,CAAC,EAAE,oBAAoB,CAAC;CACjC;AAED,2EAA2E;AAC3E,MAAM,WAAW,UAAU;IACzB,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,OAAO,GAAG,YAAY,GAAG,IAAI,CAAC;AAEzE,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,gFAAgF;IAChF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,2DAA2D;IAC3D,MAAM,EAAE,OAAO,EAAE,CAAC;IAClB,mFAAmF;IACnF,cAAc,EAAE,OAAO,EAAE,CAAC;IAC1B,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,+FAA+F;IAC/F,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,uCAAuC;IACvC,UAAU,EAAE,OAAO,CAAC;IACpB,8EAA8E;IAC9E,sBAAsB,EAAE,OAAO,CAAC;IAChC,gFAAgF;IAChF,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,oFAAoF;IACpF,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAE5B,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,eAAe,CAAC;IAC1B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,EAAE,kBAAkB,CAAC;IAChC,QAAQ,EAAE,eAAe,CAAC;IAC1B,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,KAAK,EAAE,YAAY,CAAC;IACpB,kBAAkB,EAAE,aAAa,CAAC;IAClC,IAAI,EAAE,QAAQ,CAAC;IACf,8EAA8E;IAC9E,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,8EAA8E;IAC9E,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B;;;OAGG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC"}
package/dist/cli/index.js CHANGED
@@ -11,6 +11,9 @@
11
11
  * monolith mission — manage Tactical Coordinatorium mission lifecycle
12
12
  * monolith brief — deterministic, bounded project context summary
13
13
  * monolith durable — inspect/verify/maintain Durable State task logs
14
+ * monolith idea — capture and recall deferred ideas (add/list/show)
15
+ * monolith finalize — plan/apply a controlled story finalization (documentation sync)
16
+ * monolith update — add missing Idea Capture infrastructure to an existing instance
14
17
  * monolith ui — launch Mission Control (read-only dashboard)
15
18
  */
16
19
  import { MONOLITH_VERSION } from '../version.js';
@@ -38,6 +41,15 @@ Commands:
38
41
  accepted ADRs) — read-only, no LLM/network/ERG involved.
39
42
  durable Inspect and maintain Durable State (long-running task logs):
40
43
  list | show | assess | packet | verify | retention.
44
+ idea Capture a deferred thought without leaving the current task, and
45
+ recall it later: add | list | show. Plain Markdown files, no LLM.
46
+ finalize Close a story with checked preconditions and controlled documentation
47
+ updates: plan (read-only) | apply --approve <digest>.
48
+ update Bring an existing instance up to Idea Capture & Recall. Preview by
49
+ default (changes nothing). --apply creates MONOLITH-managed files
50
+ and may add or refresh managed sections inside your existing
51
+ files; your text outside those sections is kept, and conflicting
52
+ edits are never overwritten (see 'monolith update --help').
41
53
  ui Launch Mission Control, the read-only web dashboard, on
42
54
  127.0.0.1 (default port 4173). 'ui dev' adds Vite hot reload
43
55
  (source checkout only). See 'monolith ui --help'.
@@ -60,6 +72,18 @@ Durable usage:
60
72
  monolith durable verify [taskId] (exit 2 if a log fails verification)
61
73
  monolith durable retention --retain-days N [--compact-after N] [--apply]
62
74
 
75
+ Idea usage:
76
+ monolith idea add --title "..." (--description "..." | --description-stdin) [--context "..."]
77
+ monolith idea list
78
+ monolith idea show <id>
79
+
80
+ Finalize usage:
81
+ monolith finalize plan --proposal <file|-> [--json]
82
+ monolith finalize apply --proposal <file|-> --approve <digest> [--json]
83
+
84
+ Update usage:
85
+ monolith update [--apply]
86
+
63
87
  UI usage:
64
88
  monolith ui [--port N]
65
89
  monolith ui dev [--port N]
@@ -72,6 +96,12 @@ async function main() {
72
96
  const args = process.argv.slice(2);
73
97
  // `ui` owns its own --help / --version-like flags (`monolith ui dev --help`).
74
98
  const ownsHelp = args[0] === 'ui';
99
+ if (args[0] === 'update' && (args.includes('--help') || args.includes('-h'))) {
100
+ const { UPDATE_USAGE } = await import('../update/cli.js');
101
+ console.log(UPDATE_USAGE);
102
+ process.exit(0);
103
+ return;
104
+ }
75
105
  if (args.length === 0 || (!ownsHelp && (args.includes('--help') || args.includes('-h')))) {
76
106
  console.log(USAGE);
77
107
  process.exit(0);
@@ -141,6 +171,21 @@ async function main() {
141
171
  await runDurableCommand(args.slice(1));
142
172
  break;
143
173
  }
174
+ case 'idea': {
175
+ const { runIdeaCommand } = await import('../ideas/cli.js');
176
+ await runIdeaCommand(args.slice(1));
177
+ break;
178
+ }
179
+ case 'finalize': {
180
+ const { runFinalizeCommand } = await import('../finalize/cli.js');
181
+ process.exitCode = await runFinalizeCommand(args.slice(1));
182
+ break;
183
+ }
184
+ case 'update': {
185
+ const { runUpdate } = await import('../update/cli.js');
186
+ process.exitCode = await runUpdate(args.slice(1));
187
+ break;
188
+ }
144
189
  case 'ui': {
145
190
  const { runUi } = await import('./ui.js');
146
191
  process.exit(await runUi(args.slice(1)));
@@ -0,0 +1,28 @@
1
+ /**
2
+ * DISCOVERY-001C — unified Project Map composer (ADR-021). Internal.
3
+ *
4
+ * A pure transformation of TWO finished results into one Markdown text: a `DiscoveryResult`
5
+ * (structural facts, evidence OBSERVED_FILE-class) and a `DocumentationResult` (what documents
6
+ * claim, evidence DOCUMENT_TEXT). It reads no file, starts no analyzer, calls no model, opens no
7
+ * connection, keeps no clock and modifies neither input.
8
+ *
9
+ * Identity. Neither contract carries a project identity (no id, no root, no digest); both only say
10
+ * that they were derived from "a traversal". So the composer cannot confirm that the two results
11
+ * describe the same project and says so in the output. It does not guess from paths or names.
12
+ *
13
+ * Trust. The two sources are never merged: structure comes from the existing renderer, unchanged;
14
+ * documentation gets its own section, and every statement made by a document is shown as an
15
+ * unverified claim. The statuses of the two analyzers are shown side by side, never combined.
16
+ *
17
+ * Markdown safety. Every untrusted string goes through the renderer's `markdownCodeSpan` (control and
18
+ * bidi characters are shown as [U+XXXX], an inline code span cannot be closed by its content) and sits
19
+ * in a list item; headings and structure are fixed text. Document text is never interpreted.
20
+ */
21
+ import { type DiscoveryResult } from './contracts.js';
22
+ import { type DocumentationResult } from './docs.js';
23
+ /**
24
+ * Composes the unified Project Map. Throws `DiscoveryError('RESULT_INVALID')` if either input fails
25
+ * its own validator (the message names which input and the first violations, never a value).
26
+ */
27
+ export declare function composeProjectMap(discovery: DiscoveryResult, documentation: DocumentationResult): string;
28
+ //# sourceMappingURL=compose.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/discovery/compose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,EAAqD,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACzG,OAAO,EAKL,KAAK,mBAAmB,EAEzB,MAAM,WAAW,CAAC;AAgCnB;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,mBAAmB,GAAG,MAAM,CAoGxG"}