Skip to content

feat(memory): keep every view in step with the cards it is compiled from - #277

Merged
arthware-dev merged 4 commits into
feature/0.5.0-beta.1from
feat/memory-views
Oct 20, 2026
Merged

arthware-dev merged 4 commits into
feature/0.5.0-beta.1from
feat/memory-views

Conversation

@arthware-dev

Copy link
Copy Markdown
Contributor

Summary

  • Everything the curator compiles is a view (ADR-016 §3, ADR-017 §7): it carries view, about, derived_from and compiled_from instead of a type or generated: true, and stack memory card and the card browser say when a view is behind its card.
  • Forgejo notifies the curator of every push. The views that name a changed card are compiled again within seconds without the model, also while a model compile runs; the model's text follows after the quiet window, once per burst. Polling stays as the fallback.

Upgrade: ./stack restart code, then ./stack restart memory. Until then the curator finds pushes by polling, as before.

The pages the curator compiles into the brain are views (ADR-016 §3,
ADR-017 §7): a person's, a correspondent's and a topic's page, the
diary's front, year and month pages, the home page and the folder
listings. They carried a `type` and `generated: true`, a card found its
views by their path, and a change was compiled again on a guess at which
persons it touched.

- Every view's frontmatter is `view`, `title`, `about` (a person's,
  correspondent's or topic's card), `derived_from` (the card ids it was
  compiled from) and `compiled_from` (each with the version it was read
  at, its git blob id). No view carries `type`, `card_id` or
  `generated`; `stack.cards.is_view` is the one rule every reader uses.
- When a card is pushed, the curator compiles again exactly the views
  whose `derived_from` names it, before or after the change, and the
  ones a new card would now be in, in two speeds. At once, without the
  model (`--fast`): which cards belong, list items, dates and links,
  with the model's last wording, which a view keeps below its compiled
  region. After the quiet window, with the model, once per burst. A
  diary month is compiled from the records on file (`diary pages`),
  without reading the room again.
- `stack memory card`, the cards API and the card browser show the
  views whose `about` or `derived_from` names a card, and say when a
  view is behind a card that changed since it was compiled.

Until the nightly sweep or `stack memory wiki update --all` compiles
them again, the brain keeps its pages in the old shape: the card
browser shows no views for them, and the quick compile leaves them for
the model's turn.
The curator learned of a push only at its next poll, so the views a
card is named in could follow it no sooner than the poll interval.
Forgejo now tells it of every push to `family/memory`, whoever pushed:
the archivist, the CLI, a person's own clone.

- `stack up memory` adds a webhook on `family/memory`, once, that posts
  each push to the curator (`POST /push` on the cards API, on the stack
  network). A failure to add it is reported and never blocks the start.
- The notice wakes the curator's loop within a second. It compiles the
  views the push touched at once without the model; the model's turn
  still waits for the quiet window.
- The code stacklet lets Forgejo deliver webhooks to the stack's own
  containers (`stack-*`); Forgejo's default allows public addresses
  only.
- The poll stays: a push whose notice never arrives is found there.

Upgrade: `./stack restart code`, then `./stack restart memory`. Until
then the curator finds pushes by polling, as before.
The curator did one thing at a time. A compile with the model, which
takes minutes on a real model, held the loop, so a push during it got
its views compiled without the model only once the model had answered:
on the test rig, five and a half minutes later instead of seconds. The
model compile also wrote what the cards said when it started, over any
newer facts.

- The compile with the model runs in the background, one at a time.
  The loop goes on: a push meanwhile is compiled at once and joins the
  next compile with the model, after the next quiet window. An ended
  compile wakes the loop, which commits it.
- The model is asked from the cards as they were read, and its answer
  is rendered over each view as it is when written: the cards are read
  again then, under the brain's writer lock. The diary's months work
  the same way.
- Every writer of the brain takes that lock (`brain_lock`, a `flock`
  in the brain's `.git`): each view written, a whole compile without
  the model, and the curator's commit.

Fixes: fab28a38 ("feat(memory): keep every view in step with the cards it is compiled from")
A view records the version of each card it was compiled from, so the
card graph can say when a view is behind a card. ADR-017 §7 listed the
other four fields only.
@arthware-dev
arthware-dev merged commit 0030ec5 into feature/0.5.0-beta.1 Oct 20, 2026
1 check passed
arthware-dev added a commit that referenced this pull request Oct 20, 2026
…rom (#277)

Everything the curator compiles is a view (ADR-016 §3, ADR-017 §7): it
carries `view`, `about`, `derived_from` and `compiled_from`, and
`stack memory card` and the card browser say when a view is behind its
card. Forgejo notifies the curator of every push; the views that name a
changed card are compiled again within seconds without the model, also
while a model compile runs, and the model's text follows after the
quiet window, once per burst.

Upgrade: `./stack restart code`, then `./stack restart memory`. Until
then the curator finds pushes by polling, as before.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant