Commit Graph
16 Commits
Author SHA1 Message Date
Bendik Aagaard LynghaugandClaude Fable 5.1 a2a9f4edcf Tones and storylines: every word once per tone, kept through a lift, and a report of what each brought in
tones in the plan lists tones of voice, one storyline each. The words
pass writes each page once per tone and folds the tones into lists
where they differ; the render emits the lists portal reads as
storylines; the lift carries them back. needs.yaml names the tones.
portal-trainer report --site reads the site's counts per storyline
and scores each on what arrived and what ended well.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GT37Z1Xtfd9pUuQtMTg6Yt
2026-09-30 15:16:29 +02:00
Bendik Aagaard LynghaugandClaude Fable 5.1 b0787f7c5a build: people: memberships - invite by phone number, list who is in
With portal keeping the groups itself (portal v0.5.7), a desk's invite
form asks for a phone number first, the list of invites is the list
of memberships, and a grant may know the person by number.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GT37Z1Xtfd9pUuQtMTg6Yt
2026-09-30 13:37:02 +02:00
Bendik Aagaard LynghaugandClaude Fable 5.1 1025dd7718 build: escalate - a case left too long goes up to another desk with the same buttons
escalate: { <stage>: { days, to: <group> } } on a need adds a stage
<stage>_escalated the clock enters, with the same moves out of it; the
group's desk lists exactly those cases with those buttons, and the
desk that had it keeps it and may send it up itself. Not a mail: a
desk job. The vel's help requests go up to styret after a week.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GT37Z1Xtfd9pUuQtMTg6Yt
2026-09-30 11:58:02 +02:00
Bendik Aagaard LynghaugandClaude Fable 5.1 9776dc1808 plan: the guidance names records that answer records, members-only needs and a group contact
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GT37Z1Xtfd9pUuQtMTg6Yt
2026-09-30 08:38:44 +02:00
Bendik Aagaard LynghaugandClaude Opus 5.5 d4d4c7cba3 Portal 0.5 in the plan, mails scored as read, and a front door that shows
Portal 0.5's content, from the plan: `grants` (an approval that is
membership; refused without a mail sender, since the sign-in link goes
by mail), `deadlines` (portal's `after:`, only along a move the
machine has), and `public_states` with an `empty` line on public lists,
whose words now say which stages they show.

Onboarding is a mail too: a plan that invites or grants gets
`mail.invite` in site.yaml in its own language, and a reword that loses
{link} gets it back. `rate --repo` rates every mail, the invite
included, read as it arrives: LIX, and what happened / what now / who
wrote, each against a gutted twin. The mail words are guided by what
that found on uhhm (name the case by a short required field, sign with
the business, invite a reply rather than promise a reason).

The front door shows public lists instead of pointing at them: each
public bucket is a feature with its newest three records inline and a
link to the whole list. Its card is named for what it shows. The plan
reference gains 'What a portal site can do': the schema's options and
when each pays off, as guidance rather than rules.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 20:34:53 +02:00
Bendik Aagaard LynghaugandClaude Opus 5 d2aae383b2 A case can be sent back, and can end well partway along
A municipal building authority is the first sector that the line a
case walks could not describe. An application is returned for the
drawing it was missing and walks the same stretch again; an appeal
ends the moment the authority changes its own decision, without ever
reaching the board; an applicant may withdraw from anywhere, while a
refusal may only come once the papers are in.

`reached_from: { <stage>: [<stage>, ...] }` says where a stage is
entered from when the line does not. A stage named there is entered
from exactly those stages and nowhere else, so saying where a refusal
may come from also says where it may not - which `turned_down_from`
could not, being one list for every bad ending at once.

Found by replaying fifteen real building cases through portal's own
engine against a throwaway JetStream: it refused three legal paths and
accepted two illegal ones. Portal needed no change - hand-writing the
correct graph into aggregates.yaml, cycle and all, was accepted and
enforced exactly. The rebuilt site now produces that same graph from
the plan, and the access policy follows it.

Also: a public view is of a bucket, not of a need. A permit register
holds the owner's small application and the approved firm's large one
and is one page either way; the rule refused to publish a bucket the
moment any role filed into it. A bucket only a role ever writes to is
still refused.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-25 20:17:06 +02:00
Bendik Aagaard LynghaugandClaude Opus 5 443ddcca68 A plan may ask for a place
`type: location` on a field is portal 0.4.0's map pin, stored as
lat/lon/zoom. The reference tells the model it needs `optional: true`,
since a map needs a browser that can draw one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-24 21:35:45 +02:00
Bendik Aagaard LynghaugandClaude Opus 5 1ed33b6160 build: a card states what the reader must already have
`requires:` on a need is one sentence naming what the person must
have or be for the alternative to work - a membership, a reference
number, the link from a mail. It renders as the card's first feature,
above the road, who-reads-it and the form, because a condition a
reader meets only after filling the form in has already cost them the
filling in. Whether the section exists is read from the plan, never
from its wording: under a lift every slot holds a token and a token is
never empty, which would conjure a section the live page lacks and
shift every feature after it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-24 20:42:41 +02:00
Bendik Aagaard LynghaugandClaude Fable 5.1 4d22f4cb44 plan: a spectator role goes back to the model once; bare-word movers and unlabelled groups parse
Re-planning the contractor showed three wasted rounds: `moves_by: {
checking: submitter }` written as a bare word, a group without a
label, and the two featured owner roles left with nothing to play,
which the builder only warned about after the fact. The bare word and
the missing label now parse (a label defaults to the id), and a plan
that parses with spectator roles is sent back once with the finding;
on the contractor, round three fixed both.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 06:42:05 +02:00
Bendik Aagaard LynghaugandClaude Fable 5.1 6e49694211 build: turned_down_from, and uhhm's stages in words
A need may say which unfinished stages a case can still be turned
down from; the machine no longer offers the bad end from every stage.
uhhm's collaborators are declined before they start and depart after,
as the live site has it. The uhhm plan gets stages_text and three
desk buttons reworded: every uhhm desk scores full marks.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 06:01:56 +02:00
Bendik Aagaard LynghaugandClaude Fable 5.1 be14e33603 build: stages in the plan's own words
`stages_text` on a need gives each stage plain words in the plan's
language. The fallback mails, the road line and the desk buttons use
them, and needs.yaml carries them as `stage_words` so the desk score
describes an outcome the way the site would. The vel's plan has them;
its desks score 26 of 26 where the id-based outcome scored 24.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 05:17:18 +02:00
Bendik Aagaard LynghaugandClaude Fable 5.1 2622fdac88 plan: a budget that equals the form is reported as counted, not decided
Four of the planned contractor's five needs had max_fields equal to
their required fields: the model counted the form and called it the
person's tolerance. `plan` now says so when most needs do, and the
reference tells the model to decide the number before writing the
form.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 03:04:22 +02:00
Bendik Aagaard LynghaugandClaude Fable 5.1 209e9d1258 plan: held-out personas are mapped to the plan's needs by a model, ids only
The one manual step left after `plan` was mapping the attached
personas' `need:` to whatever ids the model chose. A second call now
does it: the model sees the plan's needs and the persona texts and
returns ids only, after the plan is final, so no persona wording can
reach a page. An id the plan lacks is ignored and the reader is told.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 02:27:38 +02:00
Bendik Aagaard LynghaugandClaude Fable 5.1 20e5e16641 plan: the model that writes a plan learns this week's keys
`does`, `shows`, `mail`, `mails`, `invites_by`, `events`,
`attended_by`, and the measured guidance on doors: the plan reference
the model reads lagged the builder by a week, so a planned site had no
opener, no mails and no onboarding.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 01:54:02 +02:00
Bendik Aagaard LynghaugandClaude Fable 5.1 e3dae063d4 English in the code: fixtures, identifiers, and one phrase table
The fallback mail phrases move into a `Phrases` table, the one place a
language other than English appears in this code; the `navn` special
case goes (a form names the person's field `name`). Test fixtures
speak English: traffic, board, hazards, report, fixed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-23 22:09:04 +02:00
Bendik Aagaard LynghaugandClaude Fable 5.1 255aeb4f4b plan: intake to plan by a model; doors, labelled groups, the whole card
Work from another session, committed as found (tests green):

- `plan` reads an intake into a plan.yaml (a model decides needs,
  stages, forms and budgets; a person reads the result before build).
- Plans gain `doors` (a first question before the forms, when a front
  door would carry more than five needs), `groups` with labels that a
  select may draw its options from (`options_from: groups`), `private`
  fields kept off public pages, `multiple` selects, and `max_fields`
  as what the intake said the person will tolerate.
- `card.rs`: an alternative as the visitor meets it, in text, so the
  answering visitor and `rate` read the served card, not the heading.
- `rate` reads followup pages from the repo and reports "what happens
  next" as not measured rather than zero when it cannot.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L4jrCgLiKKHAEFuZUJjckH
2026-09-23 12:31:51 +02:00