gosalyn: PRD 1.17, Case 2 story files are DOCX (row 308, sage-3516, Q235 to Q237, Q239). Applies the approved d9 text at 4607e15b8 word for word to the 1.16 text. Status, the header sentence and a 1.17 source line, the Creative library lead, REQ-LIB-1, -2, -4, -5 and -6 changed as d9 says, new REQ-LIB-8 for the writing store and REQ-LIB-9 for the Console's DOCX editor, the 1.17 notes and four risks. requirements.json goes to 1.17 with 87 ids and the d9 titles, and the tasks and bus test pins follow

This commit is contained in:
jason.woltje committed 2026-10-23 12:20:30 -05:00
1 parent 7defb58e97
commit 30e6bb6803
4 files changed
+382 -54

No files matched your search

+372 -46
View File
@@ -1,6 +1,6 @@
# PRD: Mosaic Stack
- Status: approved, version 1.16. Jason approved draft 0.4 unchanged as
- Status: approved, version 1.17. Jason approved draft 0.4 unchanged as
1.0 on 2026-10-05 (lead decision 61). They approved version 1.1, the
Organization requirements, in decision 03130d08-ddce-480d-a601-e59f64744fc3
on 2026-10-14. They approved version 1.2, the chief of staff, the
@@ -47,7 +47,34 @@
and Jason gets a report. Version 1.16 routes the new action
`library.write` under REQ-LIB-6 (REQ-WAIT-3). A change to the hard waits
needs Jason's approval under REQ-WAIT-2, so Mos puts the text to him as
written, and it lands only after his yes (mos-1328, mos-1329).
written, and it lands only after his yes (mos-1328, mos-1329). Version
1.17 records Jason's rulings Q235 to Q237 of 2026-10-23: Case 2 story
files are DOCX, Markdown stays for agent files and documentation, and a
human-started import converts a Markdown story file one way. It also
adds REQ-LIB-9, the Console's DOCX editor, from Jason's rulings Q195,
Q226 and Q234. It changes what Case 2 requirements allow, so Mos puts
the text to Jason as written, and it lands only after his yes (mos-1366,
Vikunja 570).
- Version 1.17 source: Jason's Q235, answering Q36: 'How about we see a
markdown file, we convert the markdown file to docx, then archive or
mark the markdown file as converted. The new standard for files in the
creating writing use case is to use docx to handle versioning and
WYSIWYG. We eliminate the potential for confusion based on the files.
Agents must understand which files are what format and where they live.
The system must allow for import and conversion. We will not run the
systems in parallel. There will be an irreversible conversion of the
files.' His Q236 says: 'For creative writing chapters, we need to
utilize docx as the standard. Markdown is acceptable for agent files,
instructions, PRDs, documentation, etc. The creative writing files
should be docx for familiarity for the user.' His Q237 says 'Q38: It is
correct for now (subject to future change)', which confirms Mos's
reading P1 to P6. REQ-LIB-9 rests on his Q195 request for 'a full
WYSIWYG editor within Mosaic Stack', his Q226 answer 'F41: We want to
move editing into the WYSIWYG in the WebUI. All changes are instantly
committed and available to the agents.' and his Q234 answer 'Q37: yes'
to the exact security header for the editor's frame. The storage follows
the O2 design D10 to D12 as rewritten under Vikunja 571, at b99ca86b9 on
`refactor`.
- Version 1.16 source: Webby's review webby-0164 B2, from Scrooge's row
285. Version 1.15 lets creative agents write in supporting folders, but
the write action stayed a hard wait under REQ-WAIT-3, and REQ-WAIT-2
@@ -1196,7 +1223,8 @@ design `docs/plans/2026-10-21_t1-sessions.md`, 2c843d190 on `huey/t1-sessions-de
Added in version 1.12 (Q176 Case 2, Q211). Drafted from the Case 2
design r11, fb20a61b4 on `gosalyn/case2-design`, approved by Webby in
82f50d127, with the rulings recorded after r11 up to 624212842. The
library is the user's own writing repository.
library is the user's own writing repository plus the stack's writing
store, which holds the DOCX story files (REQ-LIB-8, version 1.17).
- **REQ-LIB-1.** A library project maps the user's writing repository
onto universes, books, entity types such as character and place, the
@@ -1205,9 +1233,12 @@ library is the user's own writing repository.
human changes it, and an agent's organization write that changes it
is refused. So
`universe.book.{character,place,...}` reads as universe, book folder,
type folder. (Design 1.1 and M9. Q176 Case 2 "Data is stored in
little-endian organizational scheme". Version 1.15: supporting
folders.)
type folder. The mapping also names one archive folder, set by the
human, where converted Markdown story files go. A book's DOCX story
files are in the stack's writing store, under the same universe and book
(REQ-LIB-8). (Design 1.1 and M9. Q176 Case 2 "Data is stored in
little-endian organizational scheme". Version 1.15: supporting folders.
Version 1.17: the archive folder and the writing store.)
- **REQ-LIB-2.** Playgrounds are never confused with canon. A playground
has one of three levels, set by where its prefix sits. A book-level
prefix lies inside one of its universe's book folders, and its files
@@ -1222,18 +1253,34 @@ library is the user's own writing repository.
its own universe, when two prefixes overlap, when a draft has books or
no prefix, and when a hybrid names a draft as a source. Supporting
prefixes, the folders agents may write in (REQ-LIB-6), follow the same
placement rules. A file's scope comes from its path alone, prefixes
first: a Markdown file under a supporting prefix is supporting, one
under a playground prefix at any level is playground, any other
Markdown file in a book folder is canon, and everything else is
unmapped and never returned. A folder in both lists is supporting.
Lookups return canon unless the caller asks for playground or
supporting. A citation marked as canon must name a canon file, so an
agent can't cite a playground or supporting file as canon. The Console
shows each cite's scope. (Design 1.2, 5.2 and 7.4, the playground
ruling, 51fdfb7e2, and the ruling after r11. Q176 Case 2, the
playground items, TARGET.md:92-94. Version 1.14: the levels and the
draft. Version 1.15: supporting.)
placement rules. A Markdown file's scope comes from its path and from
past imports, prefixes first: a Markdown file under the archive folder
is archived, one under a supporting prefix is supporting, a Markdown
file at a converted file's old path is unmapped under REQ-LIB-8 but
flagged in the format map, one under a playground prefix at any level is
playground, any other Markdown file in a book folder is canon, and
everything else is unmapped and never returned. A folder in both lists
is supporting. The archive folder follows the same placement rules and
may not overlap another prefix or a book folder. An archived file keeps
the path it had under the archive folder, and its universe and book are
those of that old path. A DOCX document in the writing store keeps its
source's scope: the universe, the book if there is one, and canon or
playground. Its source is the Markdown file it was converted from or,
for one the human starts in the editor, the universe and book or the
playground the human picks (REQ-LIB-8). A playground DOCX follows the
playground rules and is never returned as canon. It stays playground
after its draft universe is made real. In version 1.17 no promotion or
mapping change makes a playground DOCX canon. A later version of this
PRD says how one becomes canon. Lookups return canon unless the caller
asks for playground, supporting or archived. Every answer marks an
archived file as archived and names the DOCX that replaced it. A
citation marked as canon must name a canon file, so an agent can't cite
a playground, supporting or archived file as canon. The Console shows
each cite's scope and format, and whether a cited Markdown file was
converted. (Design 1.2, 5.2 and 7.4, the playground ruling, 51fdfb7e2,
and the ruling after r11. Q176 Case 2, the playground items,
TARGET.md:92-94. Version 1.14: the levels and the draft. Version 1.15:
supporting. Version 1.17: archived scope and DOCX scope.)
- **REQ-LIB-3.** Universes stay separate. Every lookup names one universe,
and its results never leave it. A draft universe (REQ-LIB-2) counts as
a universe here. It has no canon, so a lookup in a draft asks for
@@ -1249,23 +1296,62 @@ library is the user's own writing repository.
A pin doesn't stop the change. The continuity agent reads the human's other
constraints and cites them. (Design 1.4 and 3. Q176 Case 2, the
crossover items.)
- **REQ-LIB-4.** Git holds every change. The user commits and pushes with
their own tools, today Obsidian with obsidian-git. The bus keeps a
- **REQ-LIB-4.** Git holds every change. The user commits and pushes
Markdown with their own tools, today Obsidian with obsidian-git. A
converted story file's current text is no longer in that repository,
which keeps only its archived Markdown (REQ-LIB-8). The bus keeps a
mirror of the remote, fetched with a read-only token every 60 seconds
and before any lookup when the last fetch is older than that. It only
fast-forwards. A force-push is held as `library-diverged` until a human
accepts it. Agents read only the mirror's served commit and never hold
a copy of their own, so they see the user's push within about a minute.
Bus writes and pushes come in later rows (C2-02, C2-03b). (Design D5,
D6, 7.1, 7.2 and 7.5. Q176 Case 2 "Git is used for all changes -- local
and remote" and the sync items.)
accepts it. Agents read the user's repository only at the mirror's
served commit, except a story file during its import under REQ-LIB-8.
They read a DOCX story file only at a committed version in the writing
store, under REQ-LIB-5. They never hold a copy of their own, so they see
the user's Markdown push within about a minute and a DOCX save at their
next lookup after the editor reports it as committed. Bus writes and
pushes come in later rows (C2-02, C2-03b). A DOCX story file is saved in
the Console's editor, and each accepted save is one commit by the human
in the stack's writing store (REQ-LIB-9). Each writing-store commit is
also pushed to a remote off the stack's host, never by force-push. The
remote is a setting only a human changes, and it starts unset. A
repository on the stack's host never counts as that remote. A missing
remote or a failed push never undoes a save, and the user sees each push
that is pending or failed. Only the stack's host pushes to that remote,
and no agent can reach it with any credential. Agents read the local
commit. (Design D5, D6, 7.1, 7.2 and 7.5. Q176 Case 2 "Git is used for
all changes -- local and remote" and the sync items. Version 1.17, with
Q222 for the remote setting.)
- **REQ-LIB-5.** Agents check the library through typed lookup tools:
find, get, search, manuscript and universe. Each answer names the
commit it read. Get returns a file's links out and links in, so the
connections are visible to agents. The user sees them in Obsidian's
graph and backlinks. (Design 3 and 7.1. Q176 Case 2 "The agents have
tools to check character, place, and other data", the visualization
item and "Connections are always visible".)
find, get, search, manuscript and universe. Each answer names the commit
it read. Each answer also names the file's format and where it lives:
its path, or its document id in the writing store. A DOCX story file is
read from its latest committed save, never from unsaved text. A lookup
that starts after the editor reports a save as committed returns that
save or a later one, even while its push to the remote is pending or has
failed, and the answer names the version. Get, search and manuscript
read a DOCX story file as its extracted text with DOCX locators, never
as lines. That text is the file with its tracked changes accepted. An
agent reads a story file's comments, or its text with tracked deletions
shown, only after a human turns on the matching setting. Both settings
are off by default, and only a human changes them. The reader in this
version can't read some things a DOCX story file can hold, such as a web
link, a text box, a field or hidden text. The editor warns the human
when an edit adds one, and the human can still save it. Until a later
save takes it out, lookups give agents none of the text of the part that
holds it, whether that is the chapter's body, a note or a comment. The
manuscript lookup follows the book's chapter order across both formats
(O2 design D10), and the next chapter it names is never an archived
file. Links out and in resolve across both formats. The universe lookup
returns the format map (REQ-LIB-8). Get returns a file's links out and
links in, so the connections are visible to agents. The user sees a
Markdown file's links in Obsidian's graph and backlinks. A DOCX story
file's wikilinks stay clickable in the Console's editor (O2 design D11),
and no graph shows them yet. The Console's Connections view lists the
current links and backlinks of each story file the user may see, in both
formats, with each one's scope and format. (Design 3 and 7.1. Q176 Case
2 "The agents have tools to check character, place, and other data", the
visualization item and "Connections are always visible". Version 1.17,
with Q222 for the two settings and Q239 for the Connections view.)
- **REQ-LIB-6.** The creative roles are ideas, research, proofreader,
fact-checker and continuity, plus a companion role that the user's own
named agents run as. Agents never write the story. A creative agent may
@@ -1273,24 +1359,37 @@ library is the user's own writing repository.
folders a human marks (REQ-LIB-1), such as character sheets, summaries,
cross-link notes and research notes. Every other path in the user's
repository is read-only to it, chapters and unmarked folders included,
and the broker refuses such a write before any git call. Each agent
write is one commit by that agent's own Gitea account, with a trailer
naming the agent. The user sees a notice for it and can revert it. Its
tools are the lookups, a message to the human and the two write tools,
and research and companion also fetch web pages through the broker. The
write tools need the action `library.write`, which routes under this
requirement within the bounds REQ-WAIT-3 names (version 1.16). Agents
talk with the user in free text. A reply may cite lines of the
repository at a commit or pages the agent fetched, and the broker
checks every citation before it stores the message. A setting,
`requireCitation`, makes every reply carry a citation, except the
runner's fixed notices for no answer, a failed turn, no answer passing
the citation check and an answer too long to send. Only the human
changes it, and it is off by default. The user sees only stored
and the broker refuses such a write before any git call. The writing
store and the archive folder are read-only to a creative agent as well,
and the broker's path check treats the archive folder as story. No agent
creates, edits, deletes, converts, archives or restores a story file in
any format, and no agent writes a DOCX. No creative agent starts or
undoes a conversion, and none asks for one through a tool or a decision
it raises, as REQ-LIB-8 says. An agent may still suggest a conversion to
the human in chat. Each creative role's contract states which files are
DOCX and which are Markdown, and cites a DOCX story file by its locator,
never by line. Each agent write is one commit by that agent's own Gitea
account, with a trailer naming the agent. The user sees a notice for it
and can revert it. Its tools are the lookups, a message to the human and
the two write tools, and research and companion also fetch web pages
through the broker. The write tools need the action `library.write`,
which routes under this requirement within the bounds REQ-WAIT-3 names
(version 1.16). Agents talk with the user in free text. A reply may cite
lines of a Markdown file at a commit, a place in a committed DOCX story
file, or pages the agent fetched, and the broker checks every citation
before it stores the message. A DOCX citation never calls a paragraph a
line. It names the document id, the committed version and a DOCX
locator. A citation that names an archived file as current is refused.
The `requireCitation` setting below applies to Markdown and DOCX
citations alike, and so does the rule for a citation marked as canon. A
setting, `requireCitation`, makes every reply carry a citation, except
the runner's fixed notices for no answer, a failed turn, no answer
passing the citation check and an answer too long to send. Only the
human changes it, and it is off by default. The user sees only stored
messages, on every channel. (Design 4, 5.2 and the ruling after r11.
Q223 and Q226. Q180 for Bean and Chet. Q176 Case 2, the agent list,
"User sets strict guardrails for agent capabilities" and TARGET.md:101
"Agents NEVER write prose for the user". Version 1.15.)
"Agents NEVER write prose for the user". Version 1.15. Version 1.17.)
- **REQ-LIB-7.** The user talks to several creative agents in one chat. A
room holds one thread per creative agent in a project. A message goes
to every agent in the room, or only to the agents named by @tags at its
@@ -1298,6 +1397,110 @@ library is the user's own writing repository.
the threads as one timeline, and each agent sees only its own thread.
(Design D4 and 6, row C2-09b. Q176 Case 2 "converse with N agents in
one chat session with @tagged messages".)
- **REQ-LIB-8.** Story files become DOCX. DOCX is the standard for chapters and
the other story text in a Case 2 writing project, canon and playground alike. A
story file becomes DOCX through a human's import (below), or when the human
starts it in the editor. From then on DOCX is its only working format, edited in
the Console's editor (REQ-LIB-9). A Markdown story file stays Markdown until its
import. Files in a type folder (REQ-LIB-1), such as character and place notes,
stay Markdown. So do supporting files, agent files, instructions, PRDs and
documentation, including the character sheets, summaries and cross-links agents
keep under REQ-LIB-6.
- A converted story file's current text leaves the user's Gitea-mirrored
repository. Its DOCX lives in the stack's writing store, on the stack's host,
and not in the repository the user pushes or opens in Obsidian. Only its
archived Markdown stays there.
- An import converts one Markdown story file, canon or playground, outside every
type folder (REQ-LIB-1), to a DOCX document in the writing store. It refuses
an unmapped, supporting, archived or type-folder file, and a file that is
already converted. Each import has its own fidelity report, the human's
confirmation of that report, a manifest naming the source file and its commit,
and one commit in the store. The DOCX keeps every wiki link of the source as
written, and a lost link to another library file fails the fidelity report. A
web link becomes plain text that keeps its label and address, and the fidelity
report lists it for the human to confirm. A web link that can't be kept safely
as plain text refuses the import.
- The human can also start a new story file in the editor, in a universe and
book or a playground the human picks. It is a DOCX document in the writing
store from its first commit, with no Markdown copy, and it opens under the
same gate as the import.
- The same import marks the Markdown file converted, naming the document, and
moves it to the archive folder under its old path (REQ-LIB-1, REQ-LIB-2).
The mark and the move are one commit authored by the human in the user's
repository. A new human-only bus step (Vikunja 571) on the C2-02 write
plumbing writes it, and C2-03b pushes it. The move keeps the bytes and the
git history, so it isn't `data.delete`.
- The store commit comes first, and the writing store's remote must confirm it
holds that commit. Then come the archive commit and its push, then publication
to the lookups. Until publication the Markdown at its old path keeps its canon
or playground scope. Agents read that file at the commit the import started
from, even after the mirror's served commit reaches the archive commit or a
later one. No lookup returns the file's archived copy before publication, even
one that asks for archived files. A refusal or failure before the archive push
leaves the Markdown unmoved and no DOCX that a lookup returns. A failure after
the archive push leaves a pending import that the human sees and can resume,
never a claim that nothing moved. An archive push whose result is unknown
counts as a failure after the archive push until the stack reads the result
back from the user's remote.
- Each stage of an import writes a logged event. The import's record on the
stack's host names the source file's path, commit and blob and the new
document id, and each event points to that record.
- After a conversion, a Markdown file at the converted file's old path is
neither canon nor playground. Lookups leave it out, the format map flags it,
and the human is told.
- A new Markdown story file in a book folder that holds converted files stays
canon until its import, unless it sits at a converted file's old path or under
a playground prefix. The Console flags it and offers the import. Nothing
converts it on its own.
- A hybrid's exclusion that covers a converted file's old path also covers its
DOCX document (REQ-LIB-3). An exclusion of a whole book folder also covers
every DOCX document in that book, including one started in the editor. An
exclusion can also name a DOCX document by its id.
- Only a human starts an import or a new story file, from the CLI or a Console
session signed in as that human. Both are human verbs outside the agent action
vocabulary. Neither is added to `ACTIONS` in the business vocabulary or to the
broker's always-gated list, including the import's action, `library.convert`.
No role holds them, no agent can request them, and the hard-wait list in
REQ-WAIT-1 doesn't change. In an organization with several humans, who may
start them is a setting only a human changes, and the default is the owner
only.
- Conversion is one way, with no parallel run. Neither the Console nor any agent
edits a converted story file as Markdown, and no DOCX edit syncs back to
Markdown. The Console's Markdown save refuses every file under the archive
folder. The user's own tools can still change the archived Markdown, and no
such change reaches the DOCX. The old Markdown stays in git history, and
nothing rewrites history. A promotion into a book folder (C2-19) runs the
import for a Markdown story file or is refused. A promotion of a playground
DOCX is refused in version 1.17.
- Agents get a format map: for each mapped folder and story file, its format,
scope and where it lives, archived files, flagged files and pending imports
included.
- The import and new story files ship closed. They open only after four things.
The editor ships. The human has set the writing store's remote, and the stack
has checked that it can push there. Agents can read committed DOCX story files
through the lookups and cite them (REQ-LIB-5, REQ-LIB-6). Any earlier agent
system that writes the user's files has stopped, which for Case 2 is the
Hermes retirement (#423 step 5). So the import itself never cuts agents off
from a chapter, the chapter's current text never lives only on the stack's
host, and no second system writes the story. The first import of a real user's
books waits for Jason's go.
(Q235, Q236, Q237: P1 to P6. Q222 for the setting. O2 design D10 to D12.
Version 1.17.)
- **REQ-LIB-9.** The Console's DOCX editor. The human edits a DOCX story file in
the Console's editor, in a split pane with the agent chat alongside it. The
human can pin an agent chat to a document. The human can select a word,
right-click it, and choose a synonym from a thesaurus. Only a human saves. Saves
happen on their own while the human types (Q226), at intervals only a human
changes, and each accepted save is one commit with the human as author, pushed
as REQ-LIB-4 says. A save made against an older version than the current one is
refused. Agents never write a DOCX. Versioning is the editor's tracked changes
plus one git commit per save. The editor's code is vendored and pinned, with a
hash per file and the licenses that its independent security review accepted. At
runtime the editor loads only files that the stack itself serves, and it
requests nothing from any other host. The editor's frame sends exactly the
content security policy Jason approved in Q234, and the WebUI shell's own header
is unchanged. REQ-PROJ-3's project docs editor is unchanged. (Q195, Q226, Q234,
Q236. O2 design D3, D4, D6, D8, D10, D13, D14, D16 and D22. Version 1.17.)
### Installer
@@ -1779,6 +1982,109 @@ latest-by date and a hard target (Q176).
- The commit that adds `library.write` to `ROUTED` in the business
vocabulary and the broker is C2-08b, row 285. It lands only after this
version.
- Version 1.17:
- Jason confirmed the reading 'for now (subject to future change)' (Q237). The
rulings stand until he revises them.
- The 10-27 Case 2 release ships on Markdown as built (P6). The 1.11 line 'The
Case 2 MVP for 10-27 is the Markdown library (#416). The WYSIWYG editor (Q195,
Q196) is an add-on that doesn't gate it.' still holds. Conversion opens after
10-27, and only once REQ-LIB-8's four conditions are met. The editor ships,
the writing store's remote is set and the stack has checked that it can push
there, agents can read and cite committed DOCX story files through the
lookups, and Hermes is retired, which is #423 step 5.
- The 1.12 note says five bus write and Console editor rows, C2-02, C2-03b,
C2-11a, C2-11b and C2-19, don't gate 10-27. Jason's Q226 F42 later moved
C2-02, C2-03b and C2-11b into the 10-27 slice. The Case 2 design brings C2-11a
in with them, because C2-11b needs it. C2-19 stays outside the slice. Mos's
reading of F42 is that C2-02 and C2-03b now gate 10-27, because design 9.2
puts them in 'the smallest slice that lets her start'. C2-11a and C2-11b are
slice rows that still don't gate 10-27, because the editor is the Q195 add-on.
The DOCX change in 1.17 leaves this slice as it is, and C2-11b's Markdown
editor never edits a converted story file.
- Q236 narrows Q176's editor choice to DOCX for story files (REQ-LIB-9). The
1.12 note that the Case 2 design keeps Obsidian now holds only for Markdown
files, including story files not yet imported. A DOCX story file is edited
only in the Console's editor under REQ-LIB-9.
- This replaces two parts of the O2 design at 25c09f19f. The superseded-notice
proposal from Fenton's F1 in D12 is withdrawn, and the
keep-Markdown-at-its-path model of D11 is replaced. Gyro's rewrite of the O2
design for Vikunja 571, landed on `refactor` at b99ca86b9, carries the
details, and where it differs from this text, this text holds:
- the import and archive steps, the mark, and the new bus step;
- links from supporting files to a moved chapter;
- the DOCX reader;
- the user's unpushed or later changes to an archived file or at its old path,
and pushing and closing the file in Obsidian before each import;
- the writing store's remote in W4 section 7.3, which replaces the no-remote
and no-backup rule that W4 section 7.4 held before the rewrite, at
062646487;
- import events counted by a bus restore, and recovery when a bus restore or a
restore of the whole host predates an import;
- manifest order for the manuscript lookup and its next chapter;
- `library.convert` kept out of `ACTIONS`, out of the hard-wait note and out
of the pinned `GATED_ONLY` list in packages/business/src/vocabulary.mjs.
- Agents read a converted story file through the Case 2 lookups under the same
project and universe access as Markdown canon, in any thread or room. W4's
earlier O2-only conversations, per-document grants and per-send sharing don't
gate these lookups. The 571 rewrite replaced them in W4 sections 7.1 and 7.2.
The creative tool list in REQ-LIB-6 doesn't change.
- The six creative role contracts row 213 landed say 'Every item cites the
lines of the user's material it is about'. A build row under 571 changes that
line for DOCX story files (REQ-LIB-6).
- A new Markdown file in a book folder is still canon in 1.17. The 1.17
exception is a file at a converted file's old path, which REQ-LIB-2 makes
unmapped.
- Story files convert whether canon or playground. Type-folder and supporting
files stay Markdown.
- Measured 2026-10-23 at about 01:21Z: the Case 2 user's library repository
tracks 213 files, 203 of them Markdown, and none is a .docx or .doc. It has no
untracked files. The user's .doc files (Q196) are outside it. So the landed
code has no DOCX there to report as unreadable at 10-27.
- Text replaced in 1.17, kept here as in earlier notes:
- Creative library lead, the 1.16 sentence: "The library is the user's own
writing repository."
- REQ-LIB-2, the 1.16 sentences: "A file's scope comes from its path alone,
prefixes first: a Markdown file under a supporting prefix is supporting,
one under a playground prefix at any level is playground, any other
Markdown file in a book folder is canon, and everything else is unmapped
and never returned. A folder in both lists is supporting." "Lookups return
canon unless the caller asks for playground or supporting." "so an agent
can't cite a playground or supporting file as canon" "The Console shows
each cite's scope."
- REQ-LIB-4, the 1.16 sentences: "The user commits and pushes with their own
tools, today Obsidian with obsidian-git." "Agents read only the mirror's
served commit and never hold a copy of their own, so they see the user's
push within about a minute."
- REQ-LIB-5, the 1.16 sentence: "The user sees them in Obsidian's graph and
backlinks." A converted chapter's connections show in Obsidian only as they
stood at conversion, and the Console's Connections view shows their
current links.
- REQ-LIB-6, the 1.16 sentence: "A reply may cite lines of the repository at
a commit or pages the agent fetched, and the broker checks every citation
before it stores the message."
- REQ-LIB-1 only gains sentences.
- REQ-LIB-3's text and REQ-LIB-7 are unchanged. REQ-LIB-8 adds one form of
exclusion REQ-LIB-3 doesn't have: naming a DOCX document by its id. A path
exclusion also covers DOCX documents, through a converted file's old path or a
whole book folder. An archived file and a DOCX document keep a universe, and a
book where their source has one, so every lookup still names one universe.
REQ-PROJ-3, the Console editor for a project's spec and docs, is unchanged.
C2-11b opens the library's Markdown files in that same editor.
- In `packages/tasks/requirements.json` the titles of REQ-LIB-1, REQ-LIB-2 and
REQ-LIB-4 change, and those of REQ-LIB-5 and REQ-LIB-6 stay. REQ-LIB-1 becomes
'A human-set library maps the user's repository onto universes, books, types,
playgrounds, supporting and archive folders'. REQ-LIB-2 becomes 'Scope comes
from the path or a DOCX's source, lookups default to canon, and only canon
files are ever cited as canon'. REQ-LIB-4 becomes 'Git holds every change. The
bus fast-forwards a read-only mirror every 60 seconds, the one place agents
read Markdown'. REQ-LIB-8 and REQ-LIB-9 add two ids, so the count goes from 85
to 87. REQ-LIB-8 is titled 'Case 2 story files become DOCX by a human-only
one-way import or in the editor; Markdown stays for notes and docs', and
REQ-LIB-9 'The Console's DOCX editor: only a human saves, each save is one
commit, and the editor code is vendored and pinned'.
- Open points O1 to O4 of draft 1 were ruled by Mos in mos-1367 B1 to B4.
- Sage files the build rows under Vikunja 570 and 571 after the rewrite is
approved. This amendment adds the requirements only.
## Risks and open questions
@@ -1817,6 +2123,26 @@ latest-by date and a hard target (Q176).
seat sandbox with its own network namespace closes it. Until then the
host's own audit log is the check after the fact (row 210 design section
6).
- A DOCX file is a zip archive, so git can't show a line diff of a chapter.
Review of a story change goes through the editor and the committed reader,
not `git diff`. (Version 1.17.)
- A converted chapter's DOCX is not in Obsidian's graph. Obsidian shows the
chapter only through its archived Markdown, and no DOCX edit reaches that file's
links. The DOCX's current links show in the Console's editor and its
Connections view, and no graph shows them yet. (Version 1.17.)
- Conversion can't be undone in place. Front matter, wiki link forms and
unsupported blocks may not survive it, and the mirror can't refuse the user's
push to an archived file. The controls are the fidelity report, the human's
confirmation, an untouched original on refusal, and the kept archive.
(Version 1.17.)
- A restore of the stack's bus alone from a backup taken before an import drops
the import's logged events, while the archive commit and the DOCX stay. A
restore of the stack's whole host from such a backup also takes the writing
store and the host's import records back to before the import. The archive
commit stays in the user's Gitea repository and the DOCX stays on the writing
store's remote, but the host keeps no record of the import. A bus restore counts
import events, and the import's recovery covers both cases (Vikunja 571).
(Version 1.17.)
## Milestones
+1 -1
View File
@@ -45,7 +45,7 @@ test('requirements returns the committed list to a holding role session, and no
const pm = agent('pm');
const list = call(b, pm, 'requirements');
assert.deepEqual(list, loadRequirements());
assert.equal(list.requirements.length, 85);
assert.equal(list.requirements.length, 87);
assert.deepEqual(call(b, agent('coder'), 'requirements'), list);
assert.throws(() => call(b, human, 'requirements'), /agent-required/);
assert.throws(() => call(b, reader, 'requirements'), /read-only/);
+6 -4
View File
@@ -1,6 +1,6 @@
{
"prd": "docs/prd/mosaic-stack.md",
"version": "1.16",
"version": "1.17",
"requirements": [
{ "id": "REQ-ROLE-1", "title": "Each role is a reviewed roles/<name>.json: contract, authority map, credentials" },
{ "id": "REQ-ROLE-2", "title": "One holder per role instance, one per assistant session; the chief of staff may end a run, others need a decision" },
@@ -77,13 +77,15 @@
{ "id": "REQ-SESS-1", "title": "Each session shows its lifetime count of completed compactions on pi and Claude Code; an unproven count shows unknown" },
{ "id": "REQ-SESS-2", "title": "Clear context retires a session after a safe stop and starts a fresh successor with none of the old context" },
{ "id": "REQ-SESS-3", "title": "Every session start passes the launch checks: authority, route, revocation, kill switch, limits and admission" },
{ "id": "REQ-LIB-1", "title": "A library maps the user's repository onto universes, books, types, playgrounds and supporting folders, set by a human" },
{ "id": "REQ-LIB-2", "title": "Scope comes from the path, lookups default to canon, and a playground or supporting file is never cited as canon" },
{ "id": "REQ-LIB-1", "title": "A human-set library maps the user's repository onto universes, books, types, playgrounds, supporting and archive folders" },
{ "id": "REQ-LIB-2", "title": "Scope comes from the path or a DOCX's source, lookups default to canon, and only canon files are ever cited as canon" },
{ "id": "REQ-LIB-3", "title": "Universes stay separate; a crossover is a hybrid universe only a human creates, reading its sources' canon" },
{ "id": "REQ-LIB-4", "title": "Git holds every change; the bus fast-forwards a read-only mirror every 60 seconds and agents read only that" },
{ "id": "REQ-LIB-4", "title": "Git holds every change. The bus fast-forwards a read-only mirror every 60 seconds, the one place agents read Markdown" },
{ "id": "REQ-LIB-5", "title": "Agents check the library through typed lookup tools that name the commit and show links out and in" },
{ "id": "REQ-LIB-6", "title": "Agents never write story, only docs in supporting folders a human marks. Chat is free text, and any citation is checked" },
{ "id": "REQ-LIB-7", "title": "One chat room with several creative agents, addressed by leading @tags; an unknown tag sends nothing" },
{ "id": "REQ-LIB-8", "title": "Case 2 story files become DOCX by a human-only one-way import or in the editor; Markdown stays for notes and docs" },
{ "id": "REQ-LIB-9", "title": "The Console's DOCX editor: only a human saves, each save is one commit, and the editor code is vendored and pinned" },
{ "id": "REQ-INST-1", "title": "The installer offers optional components: pinned, health-checked, removable, switched on in config; first is SearXNG" },
{ "id": "REQ-INST-2", "title": "With no OIDC provider to configure, the installer deploys a bundled Pocket ID, Q203 (post-v1)" },
{ "id": "REQ-INST-3", "title": "One-command install of a named instance from a profile, and one-command upgrade with backup and rollback" }
+3 -3
View File
@@ -18,10 +18,10 @@ test("the list holds the PRD's requirement ids, in its order, at its version", (
const ids = [...prd.matchAll(/^- \*\*(REQ-[A-Z]+-[0-9]+)\.\*\*/gm)].map((m) => m[1]);
// Any other mention of a bold id would be a bullet this pattern missed.
assert.equal(ids.length, [...prd.matchAll(/\*\*REQ-/g)].length);
assert.equal(ids.length, 85);
assert.equal(ids.length, 87);
assert.deepEqual(list.requirements.map((r) => r.id), ids);
assert.match(prd, new RegExp(`^- Status: approved, version ${list.version.replace('.', '\\.')}\\.`, 'm'));
assert.deepEqual([list.prd, list.version], ['docs/prd/mosaic-stack.md', '1.16']);
assert.deepEqual([list.prd, list.version], ['docs/prd/mosaic-stack.md', '1.17']);
});
test('the committed list loads frozen', () => {
@@ -74,7 +74,7 @@ test('the schema refuses any other shape', () => {
const twice = raw();
twice.requirements.push(structuredClone(twice.requirements[0]));
writeFileSync(join(dir, 'twice.json'), JSON.stringify(twice));
assert.throws(() => loadRequirements(join(dir, 'twice.json')), listError('requirements[85].id: REQ-ROLE-1 twice'));
assert.throws(() => loadRequirements(join(dir, 'twice.json')), listError('requirements[87].id: REQ-ROLE-1 twice'));
} finally {
rmSync(dir, { recursive: true, force: true });
}