gosalyn: Case 2 design r3 for #416 (T2): playground inside a book folder, persona in a 0600 file with a digest var, creative instances human-only, fenced persona block, host 10.1.1.54 as mosaic (webby-0009, mos-1031, mos-1033, Q181)
This commit is contained in:
1 parent
c1913fb07a
commit
2958acb81e
1 file changed
+196
-51
@@ -1,4 +1,4 @@
|
||||
# Case 2 design: the creative writing hub (r2)
|
||||
# Case 2 design: the creative writing hub (r3)
|
||||
|
||||
Gosalyn, 2026-10-20 (from `date -u`). Track T2 in jason-master-restart `projects/mosaic-mvp/PLAN.md`,
|
||||
Vikunja #416, DECISIONS Q176-Q178. The requirement is Jason's text in TARGET.md (addendum 2026-10-20).
|
||||
@@ -8,6 +8,57 @@ Base: `refactor` at 9ae8c73ac. r1 cited 5d019d876. `git diff --stat 5d019d876 9a
|
||||
adapters roles scripts` is empty (Mos in mos-0980, Webby in webby-0001), so every `file:line` holds at
|
||||
9ae8c73ac. Paths are relative to the repository root.
|
||||
|
||||
## Changes from r2
|
||||
|
||||
Mos, mos-1031 (Jason's answer to Q2, DECISIONS Q181). The host is now fixed (9, 10):
|
||||
|
||||
- `<host>` is 10.1.1.54, W-Melanie-OC, VM 1012. `<user>` is `mosaic`, a system user with no sudo, no
|
||||
groups and no keys. Its home is `/srv/mosaic`, mode 0700. It runs as the system unit
|
||||
`mosaic-stack.service` with `ProtectHome`, so the config directory and the token slot live under
|
||||
`/srv/mosaic`. ops-01's plan, section 3, Vikunja #421.
|
||||
- ops-01 sets VM 1012 to 16 GiB fixed with 6 cores, which covers my 4 GB estimate. The precheck still
|
||||
prints free memory.
|
||||
- The B7 residual from `melanie`'s sudo is no longer Jason's to accept. Step 2b of the plan removes her
|
||||
sudo and lxd. Section 10 step 1 becomes "Jason approves the tightening plan (#421)".
|
||||
|
||||
Webby's review (webby-0009, CHANGES, notes at agents/webby/work/case2-r2/REVIEW.md, 162ce46db). I re-read
|
||||
each cited line at 9ae8c73ac, and each one holds.
|
||||
|
||||
- B1. A playground prefix now sits inside a universe entry and must lie inside one of that universe's
|
||||
book folders, so a playground file has a universe and a book. A prefix outside one refuses the
|
||||
business file. Playground, like canon, is `.md` only, so a `.canvas` under a playground prefix is
|
||||
unmapped (1.1, 1.2).
|
||||
- B2. The persona text no longer goes in the business file. It lives in a 0600 file per instance under
|
||||
`<configDir>/personas/`, and the business file holds only `persona.name` and `persona.sha256`. So the
|
||||
tester's `instances` read, the Console's and `changes.jsonl` carry the digest, never the text. The
|
||||
modes of the business file, `.history` and `changes.jsonl` are stated from code and tested in C2-08,
|
||||
and the C2-13 precheck checks them and refuses `bus.tester` on her business (4).
|
||||
- B3. `launch-settings.mjs:140`, `:186` and `:191` stay `THREAD_DEFINITION`, so the chief of staff's
|
||||
`assistants` key never reaches Bean or Chet, with a C2-08 refusal test. `organization.set`'s
|
||||
`instances` key refuses a creative instance for any actor. `instances.set` gets one branch, so the
|
||||
human can add or change a creative instance without a hand edit, and the tester can't. That is how a
|
||||
model change, a persona change or a later specialist happens (4, 10 step 7). This also moves C2-08 from
|
||||
Haiku to Opus, because it now changes who may write the business file (M10 in 5.1).
|
||||
- B4. The persona block goes between the contract and "## This session", fenced like skills, and the
|
||||
bundle refuses text that holds the end marker or a level 1 or 2 heading (4).
|
||||
- N1. `library_get`'s `links_out` and `links_in` drop other-universe and unmapped targets (3).
|
||||
- N2. The setup sheet says moving a note into a book folder makes it canon (7.1).
|
||||
- N3. M9 sits in `organizationWriter.write` (`organization.mjs:177`), compares all of `projects`, hybrid
|
||||
entries included, and its test calls `write` directly (1.1, 5.1).
|
||||
- N4. Obsidian resolves a shortest-path link across her whole vault, `~/src`, and the reader sees one
|
||||
repo, so the two can resolve one link to different files. Stated in 1.3 and the setup sheet.
|
||||
- Webby's answers to my three questions: reporting is enough for 1.3, M9 holds today, and the persona
|
||||
order is B4. I take all three as written.
|
||||
|
||||
Mos, mos-1033. B2 and B3 are required, and the chief of staff gets no path to rewrite Bean's or Chet's
|
||||
persona, because the personas are Melanie's. With B3 above, only the human changes a persona or a
|
||||
creative instance, and no organization read or history line holds persona text. C2-20 reads the same
|
||||
things as in r2. Only its output changes, to the persona file and its digest (9.1).
|
||||
|
||||
A correction to r2. r2 said that with `END_PROTECTED` set to `THREAD_DEFINITIONS`, only the human could
|
||||
end Melanie's agents. That's wrong. An `END_PROTECTED` instance is ended by the chief of staff or by a
|
||||
decision the human resolved (`broker.mjs:148-150`, Q169). Ending a run changes no persona (4).
|
||||
|
||||
## Changes from r1
|
||||
|
||||
Jason's rulings (DECISIONS Q180, relayed in mos-1014) come first, because they set the slice:
|
||||
@@ -152,13 +203,13 @@ The mapping is a new form of business file project entry. Business files live in
|
||||
"branch": "main",
|
||||
"vaultPrefix": "<repo folder name under ~/src>",
|
||||
"universes": {
|
||||
"<u>": {"name": "<display name>", "books": ["<book folder>", "<book folder>"]}
|
||||
"<u>": {"name": "<display name>", "books": ["<book folder>", "<book folder>"],
|
||||
"playground": ["<book folder>/<playground folder>/"]}
|
||||
},
|
||||
"types": {"<characters folder>": "character", "<locations folder>": "place",
|
||||
"<research folder>": "research", "<tracker folder>": "tracker",
|
||||
"<chapter summaries folder>": "summary"},
|
||||
"manuscript": ["<chapters folder>"],
|
||||
"playground": ["<prefix>/"]
|
||||
"manuscript": ["<chapters folder>"]
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -166,16 +217,24 @@ The mapping is a new form of business file project entry. Business files live in
|
||||
- Every value in `<>` comes from the survey and Melanie's say, through Jason (10 step 7).
|
||||
- `universes` groups her book folders. If she has one world, it is one universe holding every book
|
||||
folder. Jason's `universe.book.{character,place,...}` then reads as universe, book folder, type folder.
|
||||
- `playground` is a list of path prefixes. Her repo has no playground today as far as I know. The setup
|
||||
sheet suggests one folder per book, for example `<book>/playground/`, or one at the top. Until she makes
|
||||
one, everything mapped is canon.
|
||||
- `playground` is a list of path prefixes inside each universe entry (B1). Each prefix must start with
|
||||
one of that universe's book folders, and no prefix may hold another. A prefix outside its universe's
|
||||
book folders refuses the business file with `library-playground-outside-book`, so every playground
|
||||
file has a universe and a book, and the one-universe cite check (5.2) has something to compare. Her
|
||||
repo has no playground today as far as I know. The setup sheet suggests one folder per book, for
|
||||
example `<book>/playground/`. Until she makes one, everything mapped is canon.
|
||||
- `types` maps a type folder name to a type. A file's front matter `type`, if present, is shown next to
|
||||
it but doesn't change scope.
|
||||
|
||||
Agents can't change this mapping. No organization verb writes `projects` today: `organization.mjs` has no
|
||||
write of it, and `instance-settings.mjs:141` only reads `proposed.projects`. An organization write sends
|
||||
a whole proposed document, though, so C2-04 adds a refusal, `organization-projects-protected`, for any
|
||||
organization write whose `projects` differ from the file's, with a test (M9).
|
||||
organization write whose `projects` differ from the file's (M9). Every setter builds its document from
|
||||
the file and changes only its own keys (`broker.mjs:1261-1271`), so the rule holds today. It goes in
|
||||
`organizationWriter.write` (`organization.mjs:177`), the one place every setter's write passes
|
||||
(`instance-settings.mjs:154`, `launch-settings.mjs:207`, `:277`, `plugin-settings.mjs:60`). It compares all
|
||||
of `projects` in canonical JSON, hybrid entries included, and its test calls `write` directly (N3). The
|
||||
mapping changes only by a hand edit of the file.
|
||||
|
||||
### 1.2 Scope
|
||||
|
||||
@@ -183,12 +242,13 @@ Each path in her repo, relative to the repo root, gets one scope:
|
||||
|
||||
| Scope | Rule |
|
||||
|---|---|
|
||||
| `playground` | Starts with a configured playground prefix |
|
||||
| `canon` | Otherwise, inside a configured book folder, and a `.md` file |
|
||||
| `unmapped` | Everything else: top-level notes, `.base`, `.canvas`, attachments, anything outside a book folder |
|
||||
| `playground` | A `.md` file that starts with a playground prefix of its book's universe |
|
||||
| `canon` | Otherwise, a `.md` file inside a configured book folder |
|
||||
| `unmapped` | Everything else: top-level notes, `.base`, `.canvas` (under a playground prefix too), attachments, anything outside a book folder |
|
||||
|
||||
Lookups default to canon and return playground only on request. Unmapped files are never returned or
|
||||
citable. The universe of a file is the universe whose `books` list holds its book folder.
|
||||
citable. The universe of a file is the universe whose `books` list holds its book folder. Because every
|
||||
playground prefix lies inside a book folder (1.1), that holds for playground files too.
|
||||
|
||||
### 1.3 Reading and reporting
|
||||
|
||||
@@ -215,6 +275,12 @@ and Obsidian's shortest-path form, a base name that matches exactly one indexed
|
||||
is in another of her repos under `~/src` resolves to nothing (R4). `appears_in` and `relationships`
|
||||
values are read as links when they are wikilinks, and as names otherwise.
|
||||
|
||||
One known difference (N4). Obsidian resolves a shortest-path link across her whole vault, `~/src`, and
|
||||
the reader sees only the books repo. A base name that is unique in the repo but also exists in another
|
||||
of her repos can resolve to different files in Obsidian and in the hub. The reader can't detect that,
|
||||
because it never sees the other repos. A link written as a full path resolves the same in both, and the
|
||||
setup sheet says so (C2-12).
|
||||
|
||||
Why reporting is enough for separation. The guarantee Jason asked for is that agents keep playground and
|
||||
canon apart. The code that does that is the scope rule, the lookups' default and the cite check in 5.2,
|
||||
which refuses a playground cite on a `fact`, `finding` or `correction`. None of those needs her files to
|
||||
@@ -351,6 +417,8 @@ reads the mirror at its current served commit (7.2) and returns that commit.
|
||||
- Universe isolation is in code. `universe` is required, and results never leave it, except for a
|
||||
hybrid's declared sources minus exclusions.
|
||||
- Every result carries `scope` from the path (D2). Playground is opt-in. Unmapped files never appear.
|
||||
- `library_get`'s `links_out` and `links_in` drop targets in another universe and unmapped targets, as
|
||||
the other tools do (N1). A hybrid keeps links into its declared sources.
|
||||
- Replies stay under `REPLY_CAP` (`tools.mjs:271-280`) by paging. They are never cut.
|
||||
- The index (types, names, links and backlinks) is built per commit and cached in memory by commit id.
|
||||
Her repo has 203 Markdown files today. I estimate a rebuild well under a second, and C2-05a's gate
|
||||
@@ -374,17 +442,79 @@ All six have `authority: {withinRole: ["message.send"], crossRole: []}`, `creden
|
||||
`network` is `none`, except `api-only` for `companion` and `research`.
|
||||
|
||||
Bean and Chet. Jason's ruling (Q180): "She will want to keep those agent names and personalities." They
|
||||
are two business role instances, `bean` and `chet`, both with definition `companion`. Instance entries
|
||||
already take agent-layer `vars` (`packages/business/src/business.mjs:89`), and every var key is declared
|
||||
once in `REGISTRY` (`packages/business/src/vars.mjs:102`). C2-08 declares two keys, agent layer only:
|
||||
are two business role instances, `bean` and `chet`, both with definition `companion`. The personas are
|
||||
Melanie's (mos-1033), so only the human changes one, and no organization read or log holds the text.
|
||||
|
||||
Where the persona lives (B2). Instance entries take inline `vars` only
|
||||
(`packages/business/src/business.mjs:89`). Inline vars go wherever the business file goes. The
|
||||
`instances` read returns every instance's vars whole (`packages/business/src/instance-settings.mjs:58-63`),
|
||||
and the tester may call it (`TESTER_ORGANIZATION_VERBS`, `broker.mjs:103`). Every organization write logs
|
||||
old and new values to `businesses/.history/<id>/changes.jsonl` (`organization.mjs:70-80`, `:204`). So the
|
||||
text stays out of the business file. C2-08 declares two agent-layer keys in `REGISTRY`
|
||||
(`packages/business/src/vars.mjs:102`):
|
||||
|
||||
- `persona.name`, a string of at most 40 characters, the name she sees ("Bean", "Chet").
|
||||
- `persona.text`, a string of at most 8,000 characters, the personality prompt from Hermes.
|
||||
- `persona.sha256`, 64 lowercase hex characters, the digest of the instance's persona file.
|
||||
|
||||
The bundle's `prompt()` (`packages/harness/src/bundle.mjs:175-177`) puts the role contract first. The
|
||||
persona text goes after the contract, under a heading that says the contract wins on any conflict. That
|
||||
order is a hint to the model. The enforcement is the broker guard in 5.2, which doesn't read the persona
|
||||
at all, so no persona text can lift a guard. A persona var is refused on a non-creative definition.
|
||||
The persona file is `<configDir>/personas/<business>/<instance>.md`, outside `businesses/`. It is UTF-8,
|
||||
at most 8,000 characters, mode 0600, in 0700 directories owned by `<user>`. The bundle reads it at launch
|
||||
with `O_NOFOLLOW`. It refuses a file that isn't regular, isn't owned by the bus's uid or has any group or
|
||||
other bit, the same check `organization.mjs:141` makes on `changes.jsonl`. It refuses `persona-mismatch`
|
||||
when the file's sha256 isn't the var's. So the `instances` read, the Console's view of it and
|
||||
`changes.jsonl` show `persona.sha256` and never the text. The persona's own session sees the text in its
|
||||
prompt, which is the point. No verb returns the file, and agent file tools stay inside the workspace
|
||||
(`packages/harness/src/gate.mjs:146-156`), so no other session can read it. A persona var or file is
|
||||
refused on a non-creative definition.
|
||||
|
||||
Modes, from code. The writer creates the business file's candidate and `changes.jsonl` with mode 0600
|
||||
(`organization.mjs:61`, `:139`) and its `.history` directories with 0700 (`:39`). It refuses a log with any
|
||||
group or other bit (`:141`). C2-08 tests those modes after an `instances.set` write, and the C2-13
|
||||
precheck checks the business file, `.history` and the persona files on `<host>`.
|
||||
|
||||
Who can change a persona or a creative instance (B3). Today's paths, and what C2-08 does to each:
|
||||
|
||||
- `organization.set`'s `assistants` key, which the chief of staff holds (`broker.mjs:145`, `:1266-1271`),
|
||||
targets only definition `assistant` (`packages/business/src/launch-settings.mjs:140`, `:186`, `:191`).
|
||||
Those three lines stay `THREAD_DEFINITION`, not `THREAD_DEFINITIONS`. Test: `assistants: {bean: ...}`
|
||||
from the chief of staff refuses `organization-not-assistant`, and the file is unchanged.
|
||||
- `organization.set`'s `instances` key sets the `model` var of any instance (`launch-settings.mjs:170-177`).
|
||||
It now refuses a creative instance with `organization-creative-instance`, for every actor. Test: the
|
||||
chief of staff's and the human's `instances: {bean: ...}` both refuse.
|
||||
- `instances.set` is human only, and the tester may call it too (`broker.mjs:103`, `:1263-1265`). Today it
|
||||
refuses any `END_PROTECTED` definition (`instance-settings.mjs:23`, `:109`), which would make every
|
||||
creative add or change a hand edit. C2-08 adds one branch. An add or change of a
|
||||
`CREATIVE_DEFINITIONS` instance is accepted from the human and refused from the tester with
|
||||
`organization-creative-human-only`. That is how her agents' models change, how a new persona digest is
|
||||
set after the file is replaced, and how a specialist is added later (10 step 7). Tests: the human adds
|
||||
`ideas` and changes `bean`'s model, the tester's add and change refuse, and `instances.set` still
|
||||
refuses an `assistant` instance.
|
||||
- The tester is off on her business. `bindTester` refuses unless `bus.tester` is exactly true
|
||||
(`broker.mjs:542-545`), and the C2-13 precheck refuses a library business with it on. If it were on,
|
||||
the tester would see digests only and could change no creative instance.
|
||||
|
||||
The persona block (B4). `prompt()` puts the contract first (`packages/harness/src/bundle.mjs:177`), then
|
||||
"## This session" (`:179`) and the session lines. The persona block goes between the two:
|
||||
|
||||
```
|
||||
<contract>
|
||||
|
||||
## Persona
|
||||
|
||||
Your name here is <persona.name>. The persona below sets your voice and manner. The role contract above
|
||||
wins on any conflict, and the broker checks every reply whatever the persona says.
|
||||
|
||||
<persona-file instance="bean" sha256="<64 hex>">
|
||||
<persona text>
|
||||
</persona-file>
|
||||
|
||||
## This session
|
||||
```
|
||||
|
||||
It is fenced the way skills are (`SKILL_END`, `bundle.mjs:107`, `:170`). The bundle refuses
|
||||
`persona-invalid` for text that holds `</persona-file>` or has a line starting `# ` or `## `, so the text
|
||||
can't close its fence or open a section of its own. C2-08's snapshot pins contract, persona, session, in
|
||||
that order. The order is a hint to the model. The enforcement is the broker guard in 5.2, which doesn't
|
||||
read the persona, so no persona text can lift a guard.
|
||||
|
||||
What changes for her. In Hermes, Bean and Chet answer in free text and may write story text when she
|
||||
asks. In Mosaic they answer in short cited items, and a request for prose gets a `question` or an `idea`
|
||||
@@ -403,9 +533,12 @@ New constants in `vocabulary.mjs`, each changed only by a reviewed commit:
|
||||
|
||||
- `THREAD_DEFINITIONS = ["assistant", "companion", "ideas", "research", "proofreader", "fact-checker", "continuity"]`.
|
||||
This replaces the single `THREAD_DEFINITION` wherever it means "may hold a thread". The definition the
|
||||
chief of staff may set stays `assistant` (`tools.mjs:186`).
|
||||
- `END_PROTECTED` (`vocabulary.mjs:135`) becomes `THREAD_DEFINITIONS`. These agents hold Melanie's
|
||||
threads, so only the human may end them (N2).
|
||||
chief of staff may set stays `assistant` (`tools.mjs:186`), and so do the three `assistants` lines in
|
||||
`launch-settings.mjs` (B3 above).
|
||||
- `END_PROTECTED` (`vocabulary.mjs:135`) becomes `THREAD_DEFINITIONS` (N2). An instance of one is then
|
||||
ended only by the chief of staff or a decision the human resolved (`broker.mjs:148-150`, Q169), not by
|
||||
another agent. r2 said only the human, which was wrong. Ending a run changes no persona, and a thread's
|
||||
session stops after 900 idle seconds anyway.
|
||||
- `CREATIVE_DEFINITIONS`, the six above.
|
||||
- `CREATIVE_KINDS`, mapping each definition to the item kinds in the table.
|
||||
- `CREATIVE_TOOLS = ["read", "grep", "find", "ls", "web"]`. `validateRoleDocument` refuses a creative
|
||||
@@ -426,7 +559,8 @@ New constants in `vocabulary.mjs`, each changed only by a reviewed commit:
|
||||
| M6 no free-text decision channel | `decision.raise` from a creative definition refuses `decision-not-allowed` in the broker. The typed tool is also absent (M3) | C2-08: a creative session's raise refuses and no decision row appears. An assistant's raise still works |
|
||||
| M7 no raw session view | On a business with a library project, the conversation reader leaves creative sessions out of `catalogue()`, and `open()` refuses them with `conversation-not-listed` | C2-10a: a creative session file under the root isn't listed and won't open by id. An assistant session still lists |
|
||||
| M8 no raw Discord engine | On a business with a library project, `discord check` and `discord run` refuse a binding whose engine isn't `mosaic-bus` (`discord-engine-not-allowed`), and a `mosaic-bus` binding with `tools` | C2-10a: both refuse on a library business. A pi binding on a business without a library still checks clean |
|
||||
| M9 no agent write to the mapping | An organization write whose `projects` differ from the file's refuses `organization-projects-protected` | C2-04: a write that changes a playground prefix refuses and the file is unchanged |
|
||||
| M9 no agent write to the mapping | An organization write whose `projects` differ from the file's refuses `organization-projects-protected`, in `organizationWriter.write` | C2-04: `write` called directly with a changed playground prefix, and again with a changed hybrid entry, refuses, and the file and `changes.jsonl` are unchanged |
|
||||
| M10 personas and creative instances are the human's | The chief of staff's `assistants` and `instances` keys on a creative instance, and the tester's `instances.set` on one. A persona file that fails its digest, mode or fence check | C2-08: each path refuses with its code (4), and the file is unchanged. No `instances` read or `changes.jsonl` line holds a marker string from a fixture persona |
|
||||
|
||||
Residual, in numbers. One reply can carry up to 5 `idea` items of 200 characters, which is 1,000
|
||||
characters of free suggestion text inside a total of 1,200 characters of item text. Each item must quote
|
||||
@@ -545,7 +679,10 @@ She has it working already. `~/src` is her vault, the books repo is a folder in
|
||||
pushes it to git.mosaicstack.dev (mos-1000). The hub changes nothing on her machine and commits nothing
|
||||
to her repo. The setup sheet (C2-12) tells her which folders the agents read, that a folder named in
|
||||
`playground` is her playground, and how to add a graph colour group for that path in her own vault
|
||||
settings if she wants one. The graph view and backlinks stay Obsidian's own.
|
||||
settings if she wants one. The graph view and backlinks stay Obsidian's own. The sheet also says two
|
||||
things she might not expect. Moving a note into a book folder makes it canon, so agents may cite it as
|
||||
fact (N2). And a short link to a name that also exists in another of her repos can point somewhere else
|
||||
for the agents than in Obsidian. A full-path link avoids that (N4, 1.3).
|
||||
|
||||
### 7.2 Sync (bus side)
|
||||
|
||||
@@ -657,13 +794,13 @@ Chains follow Q177 merge-chaining. S marks a slice row.
|
||||
| C2-05b | S | Broker lookup verbs and typed tools. Sync before a read older than 60 s | C2-05a, C2-03a | Sol (Rocko) | broker verb tests. Typed tool name snapshot per creative role (M3) |
|
||||
| C2-06 | S | Cited-reply guard (5.2) in `packages/library`, the broker's pre-check on agent-to-human `message.send`, the page store, the three notices | C2-05a | Opus | one pass and one refusal per check in M5 and 5.2, through the RESULT path and `send_message`, and with a non-creative sender. `messages` count unchanged on each refusal |
|
||||
| C2-07 | S | Runner retry on a guard refusal (at most 2), then `no-cited-answer`. `no-answer` and `turn-failed` in a library business | C2-06 | Haiku high | fake harness: free text then a valid reply stores one message. An empty and a failed turn store the fixed notices |
|
||||
| C2-08 | S | Six role files and contracts, the new constants, M1, M6, the `webPlan` refusal, gate tests (M2), messaging test. `persona.name` and `persona.text` in `REGISTRY`, and the persona block after the contract in `prompt()` | none | Haiku high | role tests, gate tests, a creative raise refused, `harness-builtin` refused for `research` and `companion`, `scripts/test-config.sh`. Persona vars refused at other layers, over their caps and on a non-creative definition. A prompt snapshot with the contract before the persona |
|
||||
| C2-08 | S | Six role files and contracts, the new constants, M1, M6, the `webPlan` refusal, gate tests (M2), messaging test. `persona.name` and `persona.sha256` in `REGISTRY`, the persona file read and checks, and the fenced persona block between the contract and "## This session" in `prompt()`. M10: the `organization.set` refusals and the `instances.set` creative branch (4) | none | Opus | role tests, gate tests, a creative raise refused, `harness-builtin` refused for `research` and `companion`, `scripts/test-config.sh`. Persona vars refused at other layers, malformed and on a non-creative definition. The persona file refused when missing, a symlink, another uid's, group or other readable, over 8,000 characters, off its digest, holding `</persona-file>` or a `# `/`## ` line. A prompt snapshot pinning contract, persona, session. The M10 tests. Business file, `.history` and `changes.jsonl` modes after a write |
|
||||
| C2-09a | S | `#threaded` and launcher read `THREAD_DEFINITIONS`. `thread.create` takes `instance`. The Console new-thread control picks it | C2-08 | Sol (Rocko) | the C2-09a tests in section 6 |
|
||||
| C2-10a | S | M7 in the conversation reader. M8 in `discord check` and `discord run` | C2-08 | Haiku high | the M7 reader test, the M8 tests |
|
||||
| C2-10b | S | Console chat: cited-item renderer through `renderItems`, the status line | C2-06, C2-09a, C2-03a | Haiku high | webui tests for items, scope badges, notices, "changed since" and the status line |
|
||||
| C2-12 | S | The setup sheet for Melanie (7.1, and what changes for Bean and Chet in 4) and the survey run sheet for `<host>` | C2-01 | Luna | doc only, reviewed against the survey's real flags |
|
||||
| C2-20 | S | Persona import (9.1): a script that reads only the persona definitions of the two Hermes profiles, confirms profile to name, and writes `persona.name` and `persona.text` into a 0600 file for the business file. Prints names, byte counts and sha256 only | C2-08 | Opus (Gosalyn), run under Jason's go | fixture Hermes profile trees: the right fields are taken, memory and session files are never opened (a read trace on the fixture), a profile with no persona field refuses, output holds no persona text |
|
||||
| C2-13 | S | Install script and precheck for `<host>` as `<user>`: bootstrap, release activate, business file with the mapping, `bean` and `chet` with their persona vars, any specialists she picks, her human id, token slot path. Jason or his delegate runs it (10) | C2-04, C2-03a, C2-20 | Opus (Gosalyn), Jason's go | precheck: config validates, `<user>` has no sudo, `library.sync` fetches her repo read-only, `library.status` lists R-problems, no Discord binding exists. Tested against a scratch data root and a local bare repo |
|
||||
| C2-12 | S | The setup sheet for Melanie (7.1, including N2 and N4, and what changes for Bean and Chet in 4) and the survey run sheet for `<host>` | C2-01 | Luna | doc only, reviewed against the survey's real flags |
|
||||
| C2-20 | S | Persona import (9.1): a script that reads only the persona definitions of the two Hermes profiles, confirms profile to name, and writes each persona file (4) with its `persona.name` and `persona.sha256` for the business file. Prints names, byte counts and sha256 only | C2-08 | Opus (Gosalyn), run under Jason's go | fixture Hermes profile trees: the right fields are taken, memory and session files are never opened (a read trace on the fixture), a profile with no persona field refuses, a persona that would fail C2-08's fence check refuses, output holds no persona text, each written file is 0600 and its digest matches |
|
||||
| C2-13 | S | Install script and precheck for `<host>` as `<user>`: bootstrap, release activate, business file with the mapping, `bean` and `chet` with their persona vars and files, any specialists she picks, her human id, token slot path, the `mosaic-stack.service` unit. Jason or his delegate runs it (10) | C2-04, C2-03a, C2-20 | Opus (Gosalyn), Jason's go | precheck: config validates, `<user>` has no sudo and no groups, `bus.tester` is not on, the business file, `.history`, `changes.jsonl` and persona files have the modes in 4 and each persona digest matches, free memory printed, `library.sync` fetches her repo read-only, `library.status` lists R-problems, no Discord binding exists. Tested against a scratch data root and a local bare repo |
|
||||
| C2-14 | S | End-to-end acceptance on a scratch data root and a bare repo in her layout: sync, ask a creative agent in its thread, a reply whose cites verify, a playground cite as canon refused, a force-push held as diverged, the Console shows the reply as items | slice rows | Opus | one script, which the reviewer also runs |
|
||||
| C2-02 | | Bus writes: `writeLibraryFile`, `commitFile` refactor, r1's S0 rule on the working tree | C2-04 | Sol (Rocko) | writer tests, `packages/project/tests` unchanged and green |
|
||||
| C2-03b | | Push path, race retry, `unpushed`, `library-remote-invalid` on writes | C2-02, C2-03a | Opus | push tests against a bare repo |
|
||||
@@ -692,22 +829,25 @@ compaction count and clear context (GAP-MAP C2.12, C2.13). Until then, a new thr
|
||||
|
||||
## 9. Where it runs, Bean and Chet's move, and what can't be ready by 2026-10-27
|
||||
|
||||
Where it runs. The host is a variable, `<host>`, and the instance runs as its own user `<user>`, which
|
||||
has no sudo. Mos's reading, which he is confirming with Jason, is her VM 10.1.1.54 with RAM added. The
|
||||
design doesn't depend on the host. The bus, data root, mirror and runners live under `<user>`. It needs
|
||||
outbound HTTPS to git.mosaicstack.dev and the model providers. It needs nothing from her user, because
|
||||
her writing reaches it through the Gitea remote she already uses.
|
||||
Where it runs (Jason, Q181, relayed in mos-1031). `<host>` is her VM 10.1.1.54, W-Melanie-OC, VM 1012
|
||||
on pve. `<user>` is `mosaic`, a system user with no sudo, no groups and no keys, home `/srv/mosaic` at
|
||||
mode 0700. It runs as the system unit `mosaic-stack.service` with `ProtectHome`, so nothing it needs may
|
||||
live under `/home`. Its config directory, `<configDir>`, is `/srv/mosaic/.config/mosaic-dev`, and the token
|
||||
slot and persona files live under it (ops-01's plan, section 3, Vikunja #421). The rest of the design
|
||||
still names `<host>` and `<user>`, so a later move changes only the install inputs. The bus, data root,
|
||||
mirror and runners live under `<user>`. It needs outbound HTTPS to git.mosaicstack.dev and the model
|
||||
providers. It needs nothing from her user, because her writing reaches it through the Gitea remote she
|
||||
already uses.
|
||||
|
||||
Memory, from mos-1000. Her two Hermes services use about 1.8 GB together, and 1.2 GiB was free on a 3.8
|
||||
GiB VM. Each Mosaic agent session measured 300 to 390 MB on dragon-lin. With Hermes still running,
|
||||
Bean and Chet in use at once, and the bus and Console, I estimate at least 2 GB more is needed, and 4 GB
|
||||
more if she also talks to specialists at the same time. That is an estimate from those numbers, not a
|
||||
measurement on her VM. C2-13's precheck prints free memory before the start.
|
||||
Memory. From mos-1000, her two Hermes services use about 1.8 GB together, and each Mosaic agent session
|
||||
measured 300 to 390 MB on dragon-lin. I estimated at least 2 GB more than the 3.8 GiB her guest saw, and
|
||||
4 GB more with specialists running at the same time. ops-01 is setting VM 1012 to 16 GiB fixed with 6
|
||||
cores (mos-1031), which covers both. C2-13's precheck still prints free memory before the start.
|
||||
|
||||
Isolation on that host. `<user>` without sudo keeps the hub from touching her files. The reverse doesn't
|
||||
hold: `melanie` has passwordless sudo (mos-1000), so anything that runs as her, and anyone who can ssh in
|
||||
as her, can read the hub's data root and its token slot. That is the B7 residual for this host. It is
|
||||
Jason's to accept (10 step 1).
|
||||
Isolation on that host. `<user>` without sudo keeps the hub from touching her files. The reverse was the
|
||||
B7 residual in r2, because `melanie` had passwordless sudo (mos-1000). Step 2b of ops-01's plan removes
|
||||
her sudo and lxd, so it is no longer a residual to accept. It depends on Jason approving that plan
|
||||
(10 step 1).
|
||||
|
||||
### 9.1 Moving Bean and Chet (C2-20)
|
||||
|
||||
@@ -719,9 +859,11 @@ Jason's to accept (10 step 1).
|
||||
profile's own configured name, and prints the pairing for Jason before anything is written. If a profile
|
||||
names neither, it stops and asks.
|
||||
- How it reads. A script, run on `<host>` by whoever Jason names, because the persona files sit in her
|
||||
home directory and `<user>` can't read them. It writes `persona.name` and `persona.text` to a 0600 file
|
||||
that the business file entry for `bean` and `chet` takes, and prints names, byte counts and sha256 only.
|
||||
No agent sees the persona text, and it never enters the repository.
|
||||
home directory and `<user>` can't read them. It writes each persona text to a 0600 staging file, and a
|
||||
second step run as `<user>` installs it as `<configDir>/personas/<business>/<instance>.md` (4). It
|
||||
prints `persona.name` and `persona.sha256` for the business file entries of `bean` and `chet`, and
|
||||
otherwise names, byte counts and sha256 only. The text never enters the repository, the business file
|
||||
or `changes.jsonl`, and only Bean's or Chet's own session sees it.
|
||||
- Hermes keeps running. The row changes nothing in the Hermes checkout, its profiles, its services or its
|
||||
Discord bots. Bean and Chet in Mosaic are new agents with the same persona, not a move of the Hermes
|
||||
ones. She uses both until she is happy, and stopping Hermes is her choice through Jason, after Bean and
|
||||
@@ -749,16 +891,18 @@ resolves to 10.1.1.222, and STATE.md lists its certificate among the edge certif
|
||||
reachable from the internet. Her writing is already there by her own choice. The hub adds no new remote.
|
||||
What it adds is one bot account with read access to that one repo.
|
||||
|
||||
1. The host: `<host>` and `<user>`. If it is her VM 10.1.1.54, the RAM to add (9) and acceptance of the
|
||||
B7 residual from `melanie`'s sudo (9).
|
||||
1. Jason approves the tightening plan (#421). The host is set (Q181): 10.1.1.54 as `mosaic` under
|
||||
`/srv/mosaic`, 16 GiB and 6 cores. Plan step 2b, which removes `melanie`'s sudo and lxd, closes r2's
|
||||
B7 residual (9).
|
||||
2. Running the install on `<host>` as `<user>`, by him or his delegate: `scripts/bootstrap.sh`, release
|
||||
package and activate, the pinned harness, and which model accounts its agents use. Model use is spend,
|
||||
so the accounts are his call.
|
||||
3. A new Gitea bot account for the hub, with read access to the books repo only. Not bean-brain, and not
|
||||
her other three repos. Her repo's access list is hers, so adding the bot means asking her or acting as
|
||||
admin, which is his call.
|
||||
4. The bot's token in slot `library-gitea` under `~/.config/mosaic-dev/secrets/<business>/` of `<user>`,
|
||||
mode 0600. He puts it there, or says who may, per the Q173 secrets rule. Agents never print it.
|
||||
4. The bot's token in slot `library-gitea` under `<configDir>/secrets/<business>/`, which is
|
||||
`/srv/mosaic/.config/mosaic-dev/secrets/<business>/` for `mosaic`, mode 0600. He puts it there, or
|
||||
says who may, per the Q173 secrets rule. Agents never print it.
|
||||
5. Her Console sign-in from her machine: her Authentik user and `sub` once SSO lands (#412 step 3 is the
|
||||
model), or his ruling on an interim.
|
||||
6. The C2-20 persona import: who runs it on `<host>`, his check of the printed profile-to-name pairing,
|
||||
@@ -766,7 +910,8 @@ What it adds is one bot account with read access to that one repo.
|
||||
7. Running `library survey` on `<host>` after step 4, which prints names and counts, never text. Then
|
||||
contacting Melanie: who tells her what changes for Bean and Chet (4), sends the setup sheet (C2-12),
|
||||
and asks her to confirm the mapping, the universes, the playground folders and which specialists to
|
||||
start with, and when.
|
||||
start with, and when. A specialist she wants later is added by the human through `instances.set`
|
||||
(4), with no hand edit and no new row.
|
||||
8. The residual in 5.1: up to 5 idea items of 200 characters per reply, 1,000 characters of free text
|
||||
within 1,200 total. He or Melanie accepts it or orders lower caps. Mos takes it to him.
|
||||
9. The instance start. Stopping Hermes comes later, and only when she chooses it.
|
||||
Reference in new issue
Block a user