Ctrl K
ComunidadGuías…

CHANGELOG.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Changelog

All notable changes to Lyriks Community are documented in this file. The
format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
versions follow the platform's semantic version.

## [Unreleased]

## [0.9.40] - 2026-10-12

Cursor can connect to a Lyriks install that requires sign-in.

### Fixed

- Clicking Allow access on the MCP consent page did nothing in Cursor: the
  browser reported that sending the form violated the page's Content Security
  Policy. The page allowed the form to reach only Lyriks and the client's
  callback origin, browsers apply that rule to every redirect after the click,
  and Cursor's callback on www.cursor.com redirects to cursor.com. The rule is
  gone from the consent page; scripts stay off, every value is escaped and the
  page cannot be framed.

### Security

- Dependencies move past fixable high-severity advisories:
  @modelcontextprotocol/sdk 1.31.0, fast-uri 3.1.7, proxy-addr 2.0.8 and
  devalue 5.9.3.

## [0.9.39] - 2026-09-25

Evolution becomes optional, and what agents reported from the field is fixed.

### Changed

- Evolution is optional. The binding block, the per-prompt hook and the skills
  sent every change to an existing product through an Evolution dossier, with no
  threshold, and a dossier for a two-line fix cost more than the fix. A change is
  now made directly: the spec first through the section tools, then the code,
  then the index sync. A dossier is opened when the person asks for one or wants
  a change qualified before it is decided. The module itself is unchanged.
- An implementation report judges the change, not the feature it lands in. The
  first freeze of a request records what the touched features already hold; a
  line on one of those elements is `inherited`, shown apart and marked on the
  page, and only the request's own lines hold the report open.
- The board answers the requests first; leaves and sources are counted there and
  read one list at a time (`part=leaves`, `part=sources`).

### Added

- An amendment can be a delta: criteria retired or reworded by id, and the
  description patched by an exact passage or appended to, each checked against
  the feature when the draft is made and applied at the freeze.
- `register_source` registers a documents register row inside the batch that
  cites it.
- A request is named by any unique prefix of four characters or more.
- Searching the knowledge graph for features also matches their criteria,
  actions and rules, and `matchedVia` names what matched.
- Helper scripts: `index-file.mjs upsert` and `remove` edit `.unspa.json`
  without reformatting it; the sync refuses to run when the index names another
  project than the binding block; `ingest-results.mjs` records a criterion's
  `verification.lastResult`; the hook says when the Lyriks MCP stopped answering;
  `sync_skills` sends a helper script only when it changed.

### Fixed

- The summary lines an AI client reads for an impact walk agree with the rows:
  a feature the change only reaches is to be read again, not edited, and an
  empty report says why.
- A proposal missing what was read or what was inferred is refused when it is
  proposed, not when someone tries to accept it; the summary groups the blocked
  proposals by their reason.
- An amendment and the feature it amends are one feature for the maturity: a
  value typed on the amendment counts as filled, and the gate into Verify no
  longer refuses a request whose every field is filled.
- Settings > Versions names the release the install runs (for example
  2026.09-62) beside the channel it follows, and Lyriks-back reports its real
  version instead of 0.4.1.
- Engine 0.25.2: a surface marked `partial` in the index resolves its states and
  invariants instead of reporting them all missing, and a behavior batch names
  every id it minted and every state it renamed.

## [0.9.38] - 2026-09-24

The dossier of an evolution request reads as one answer, and says where to act.

### Changed

- The impact report is one reading, not three hypotheses. It used to print three
  columns, "if we add it / change it / remove it", and leave the reader to pick,
  although the request already says what it does. On a request that both adds and
  amends, none of the three columns described it. Each row now carries the verb of
  the draft behind it, and a node the walk only reached carries what the request
  does overall.
- A row says what it rests on. The "knock-on" chip is gone; a row two links out
  now names the thing it depends on, for example rests on "Model the behavior".
- A row says the work to do instead of "re-check": walk it again, replay it, set
  who may, read it again, check the shape holds, write it, edit it, delete it. A
  removal still reads "may break", the one case that is a risk and not a task.
- A row of the impact report says what is true of it. A feature the change only
  reaches is never told to be written or deleted, the line under a row says in
  plain words what joined it to the change, a node reached from an amended
  feature reads as a change even when the request also adds something, and the
  sentence on top counts exactly the rows shown.
- A dossier reads once per feature. An amendment and the feature it stands for
  are one row, a draft is shown by its name, and a proposal on an existing value
  shows what it adds, what it removes and how many lines it keeps.
- Every place a person acts on is a link. The request, a field, a proposal, the
  next gate, a report line and a refused result carry the address of the page
  opening on that exact place, and an AI client hands it over as a link.

- A glossary flag warns and never blocks. It names the agreed term the word
  stands in for, a word between quotation marks is never flagged, and a person
  can keep the wording by saying which sense they meant, which is recorded
  beside the value. An AI client can take back a proposal nobody has decided.
- The dossier opens on what is owed: the questions to answer and the values to
  sign come first, answers already given are folded, and the maturity says how
  many of its answers were given in the request and how many the features
  already held.
- The impact report runs the walks the request asks for, and what it would cost
  to take the change back out is a separate reading, asked when wanted. A
  report that reached nothing says why.

### Fixed

- Ticking a feature on a dossier could take a draft out of its own request.

## [0.9.37] - 2026-09-24

### Fixed

- The engine moves with the platform. The platform runs the engine's own
  mcp-server, not only the behaviour dashboard does, so a fix shipped in the
  engine reached the dashboard and not the answers the platform itself gives. The
  dependency now moves with the release, which is how the corrected hint on an
  orphan index key actually arrives. Caught on the release candidate, where the
  new answer and the old hint came back in the same response.

## [0.9.36] - 2026-09-24

Eight things that made the tool argue with the person using it.

### Fixed

- A value signed by a person is the value the feature carries. It used to lose to
  the text typed on the draft, so two of four signed values reached nothing, with
  nothing on screen saying which of the two had been kept. A signed list of
  acceptance criteria now replaces the typed one instead of joining it, which is
  what put two wordings of the same criterion side by side.
- A value carried by a draft counts as filled. The maturity read only the owning
  section, so it reported four critical fields empty on a draft that held them,
  and asked a person to sign values that already existed.
- A reasoning is judged in any language. The separation of what was read from what
  was inferred was guessed by searching the text for the English words "read" and
  "infer", so a reasoning written in French said exactly that and was told it did
  not, which no rewording could fix. It is now two named fields, judged on being
  filled.
- An addition never crosses its own gates. A feature the product does not have yet
  has no neighbours, so the impact walk finds nothing, and that silence was read as
  "nothing follows": a drafted capability crossed both gates alone, froze a version
  and wrote itself into the tree with nobody deciding anything.
- A refused field path names the path it received and the paths it accepts, instead
  of pointing at another tool for a list the caller already holds.
- The dossier page shows every value whole. A criterion longer than 160 characters
  was displayed cut in mid-word, ending in three dots, because the page was served
  the excerpt a tool answer needs to stay one size.
- The freeze says, per written feature, how many of the draft's acceptance criteria
  that feature already carried word for word, and which therefore keep the
  identifier the feature gave them.
- Registering a source says which of the two registers is meant: the project's
  evidence register that proposals cite, or the engine's attachments an analysis
  read.

## [0.9.35] - 2026-09-23

A signature that survives, and two screens that say what they mean.

### Changed

- The Versions panel opens on the versions and folds the machine away. What
  runs is one sentence anyone can read, and a single gesture copies the whole
  panel, hardware included, for a bug report. The machine's figures used to be
  the first thing the page showed, to a reader who had come for a version
  number.

### Fixed

- A value signed on a draft feature now reaches the specification. It was
  written on a line whose key names a draft rather than an existing feature, so
  the next write of the features section pruned it, and the freeze read the
  draft object instead of the signed line. Signed values were lost with no
  alarm while the dossier went on counting the field as decided. The freeze also
  merges acceptance criteria now instead of replacing them, which had erased
  seven criteria of an existing feature.
- A lone option is a tick box, not a radio dot. A single choice drawn as a radio
  button cannot be unticked, so a reader who had turned it on had no way back.

## [0.9.34] - 2026-09-22

Who decides what leaves a score, and readings that disagreed with the screen.

### Added

- A coherence finding can be settled **by design**: the finding is correct and
  the choice was deliberate, so nothing is at risk. The only exits until now all
  asserted that something was wrong, and an author with a deliberate choice to
  record left the finding open instead, which is how a register fills with
  things already decided.
- A client can PREPARE a decision on a finding: it names the disposition and
  writes the reason, changes no score and takes nothing off the list. The person
  reads it on the finding itself and takes it in one click, or turns it down.
  Refusing a client the decision without offering it anything meant the same
  findings came back, unargued, the next session.
- The coherence section read carries the headline the panel prints: the score,
  the word beside it, how many findings block, how many are severe, and the five
  that weigh most on the number. A client that could not read it summarised the
  list on its own, against thresholds it had guessed, and contradicted the
  screen the person was looking at.
- A change request carries what it PROPOSES: a draft feature to add, an existing
  one in its amended form, or one marked for removal. The impact report, the
  coherence check and the readings all run with those drafts laid over the
  specification, so the impact walk starts from the change itself. Nothing
  reaches a section before the crossing into Verify.
- A journey reports how many actions it was authored with and whether it
  exercised any. One verified without executing a single interaction is named in
  the advisories instead of passing for a proof.

### Changed

- The coherence score weights a finding by WHO says so: one the author declared
  costs 40 percent of one the engine detected. Charged the same, the reading
  rewarded an empty register and taught every author to say nothing.
- The COHERENCE verdict follows what the list holds, not how long it is.
  "Critical" is kept for something blocking or of high severity; a register of
  low and medium findings with nothing severe is a queue of decisions.
- Deciding on a coherence finding is now refused to anything but a person at
  every way in, and reopening is refused the same way, because it supersedes a
  decision somebody took.
- The authoring skills say to read every headline the product shows before
  writing a number, to read their own work back before reporting on it, and to
  say so plainly when they cannot see a screen instead of letting it pass.

### Fixed

- A finding could be settled by an AI client and recorded, and signed, as a
  person's decision: the endpoint built its author without asking who was
  calling, and the whole section could be written with decisions inside it,
  author kind included. Both doors now read the caller from the request.
- A step lost the actions it had been authored with when the journeys were read
  back, and every later save wrote the loss down. The check that should have
  caught it reported a successful run on a journey that executed nothing.
- A permission row naming a capability that no longer exists no longer wedges
  the access matrix shut. A stored dead grant is dropped on the next save and
  named in the answer; one being introduced is still refused, with the canonical
  id suggested.
- A source citation resolves to the source on every surface, the Evolution
  dossier included, instead of printing a bare title or a raw id with nothing to
  click.

## [0.9.33] - 2026-09-21

The corrective lot, from a build made end to end through the tools.

### Added

- `patch_section` gains `append`: one new row at the end of a collection, with
  no selector at all. Adding a row used to mean knowing an id the section had
  not minted yet, or counting the existing rows to set an index.
- `get_evolution` serves the six origins a change request can carry, and the
  refusal that asks for one names them, so opening a request never means
  guessing an enumeration.
- `simulate_experience` answers who the run acted as, and says in words when a
  run as a role met no access gate at all, since such a run proves nothing
  about permissions.

### Changed

- An approval still `in_review` is a decision FILED: the completion gate counts
  it and reports the missing signature as debt instead of blocking, so nobody
  has to write `accepted_risk` on a human's behalf.
- Evolution is a derived section: its dossiers are written through their typed
  operations, so the completion gate no longer asks for a verdict on it, and
  `describe_section` answers for it like any other section.
- The rule inventory is a read-only mirror, so an empty one no longer zeroes a
  section whose contradictions and edge cases were authored; the message names
  the sections that fill it.
- Specify does not close while a proposal still awaits a signature: the
  maturity beside a dossier is inherited from the features it touches and never
  proves the change itself was specified. A named waiver still crosses.
- `import_data_collections` gives an existing collection the model fields it
  was missing, instead of skipping it in silence.
- Both batches accept `op` and `kind` as the same discriminator, a proposal
  takes a list of lines on a list field, and the answer fields lifted out of
  `raw` stop travelling twice.

- Evolution is read where it belongs: the board and every change request move
  into the Evolution tab of the Features capability, beside the feature tree a
  request changes, instead of a page of their own. The old address still
  resolves, carrying the request and the reading it named.

### Fixed

- A kernel write no longer shares one temporary file with whoever else writes
  the same feature: each write renames its own. A section save could answer
  that a row applied and lose it to another writer's rename.
- A declared `emittedEvents` really emits (engine 0.25.0): the cascade a model
  promises runs, and the batch says which declarations it wired.

## [0.9.32] - 2026-09-20

### Added

- Evolution: qualify a change to the product before anyone builds it. A change
  request opens as a dossier read in three steps (the idea, the proposals a
  person signs, the impact report), and the whole lifecycle is drivable from an
  AI client through `get_evolution` and `apply_evolution_batch`, under the same
  guards as the page: name the features the change touches, read the impact on
  two planes (what the specification holds and what the code anchors) under the
  three hypotheses of adding, changing and removing, read the coherence the
  engine computes, propose values a person accepts (an accepted value is written
  into the section that owns it, and the dossier keeps no copy), hand a proposal
  to named reviewers, cross a stage gate or waive it with a stated reason, freeze
  the specification as a numbered version, judge the implementation report the
  index derives under five verdicts, and close the request. A request plans
  without building: while it is being specified, no feature, entity, term, rule,
  screen or grant is created in the sections.
- The knowledge graph is the shared read model of a project: it holds what a
  feature promises, its edges no longer collide, a deep link opens the behaviour
  node it names, and deleting anything shows what rests on it first.
- A feature has one list of acceptance criteria, the model's. The rows written
  on the Features page and the criteria an AI client writes through the MCP were
  two lists that did not know each other; they are now one, which carries a
  title, Given/When/Then, an outcome, a status, relations and an index key, and
  the generated requirements document prints them.
- Evidence and traceability say apart what verifies a criterion and what is
  proven against the code, and actions the search did not reach are no longer
  counted as dead.
- The authoring skills ship with their helper scripts: an index sync and a batch
  apply, so a repository can send test results back into the implementation
  index and an agent can write a batch against the version it read.
- A conversation stays bound to its Lyriks project: `sync_skills` installs the
  binding, so every later request about that product goes through the model
  without anyone naming Lyriks again.
- AI clients stay signed in while they are used at least once every 30 days:
  each grant re-signs the session for thirty days, so a restart costs a silent
  refresh instead of a browser window, while a logout, a removed account or a
  withdrawn role still cuts the session on the next call.
- The MCP exposes what authoring actually needs: section writes that guard on
  the revision they read, a patch preview that validates without saving, the
  canonical permission capability registry, selective skill synchronisation,
  project elaboration, and modelled scenarios exported as fixtures a repository
  test can run against the code, whose results come back into the index.
- Typography takes any named role beside heading, body and mono, so a product's
  own type scale survives in the generated screens.
- The behaviour engine is `unspaghettit` 0.24.0, which is what makes a criterion
  carry its standing and its relations, and keeps what verifies a criterion with
  its status.
- First steps: the user menu links to the getting-started guide on
  get.lyriks.io, one entry before Documentation, opened in a new tab. The
  link carries this installation's address as a URL fragment, which stays in
  the browser, so the guide's shortcuts and its MCP address point back at
  this installation without the host ever seeing it.

### Changed

- Experience writes are per screen: one screen or component is built or rebuilt
  at a time, and the rest is edited in place. Replacing a whole Experience could
  not be verified change by change.
- A large MCP answer stays readable instead of being cut: it degrades to a shape
  with a hint naming the argument that narrows it, and an error stays short.
- Implementation coverage reads what a sync located, never an index the engine
  found on its own, so a percentage says what was actually proven.
- Reading an evolution request through the MCP gives the counts and the
  features it touches, not the rows behind them: the fields, the proposals and
  the readings are read one list at a time, narrowed to one touched feature
  with `leaf` and paged with `offset`/`limit`, like the impact and the report
  already were. A request touching seventeen features answered 59 KB, over the
  cap an AI client reads through, so the entry point to a real dossier came
  back as a stub and the client could not even tell which fields to fill.

### Removed

- Supervision and FinOps are retired. They governed AI members, policies and
  spending inside a workspace, which this product does not manage. The retirement
  covers the navigation, the capability help, the schemas, the section reads and
  writes, the gateway endpoints, the composition and repositories, the optional
  policy and budget adapter, the MCP registration and the build skill; hiding a
  menu entry alone would have left callable functionality behind. Baselines,
  approvals, specification generation, audit records and the work queue remain,
  and no historical data is purged.

### Fixed

- A leaf id another project already holds is refused when it is claimed. Two
  projects could name the same feature id, and the behaviour engine addresses a
  feature by its id across projects, so one project's model could answer for
  another's.
- A request to `/mcp` or its sign-in routes that carries `Expect: 100-continue`
  is served. It answered `502 mcp_unavailable` while the gateway was up: the
  header was forwarded to a `fetch` that refuses it. Windows PowerShell sets it
  on every POST, so a registration tried by hand from there looked like an
  outage.
- A malformed expression operand is refused before it is stored, and a domain
  payload is no longer read as an expression.
- A criterion gap stays a criterion gap instead of being reported as something
  else, and an interaction that was never rendered cannot be planned.
- Project discovery and multi-term operation references are paged, so a large
  portfolio answers in full instead of being cut.


## [0.9.30] - 2026-09-18

### Security

- Dependencies flagged by the advisory feeds are updated: `hono` 4.13.8 in the
  MCP gateway (`parseBody()` memory exhaustion on nested keys, query parsing
  after the URL fragment), `devalue` 5.9.2, and the build and test tooling
  (`vite`, `vitest`, `postcss`), which never ships in an image.
- Every published image is scanned, including its system packages, and an
  image carrying a fixable high or critical finding is not published. The
  images themselves carry none.

## [0.9.29] - 2026-09-17

### Fixed

- An `/api/*` request answers 503, not 401, while the account service cannot
  be reached. The guard runs before the route, so 0.9.27's own 503 never
  answered on a real install: the MCP gateway read the guard's 401 as a dead
  session and sent every client back to a browser window.

## [0.9.28] - 2026-09-17

### Security

- The images apply the Debian security updates published after their base
  image was built (libpcre2 and liblzma), which the base image does not carry
  yet.

## [0.9.27] - 2026-09-17

### Fixed

- AI clients stay signed in when Lyriks cannot check an account for a
  moment (a restart, an update, a slow account service). The MCP gateway
  used to read that as a signed-out user: every client process discarded
  its tokens and opened a browser window on the login page, two per incident
  with Claude Desktop, which runs one process for chat and one for Cowork
  and Code. The session check now answers 503 when it has no verdict; a tool
  call is retried, a renewal is kept, and the sign-in page asks to reload
  instead of logging in again. A renewal presented again within 30 seconds
  by another process of the same client is honoured too.
- `wire_element` is listed again in Claude clients: one of its fields
  serialized to a JSON Schema the Anthropic API refuses, which dropped the
  whole tool.

## [0.9.26] - 2026-09-11

### Fixed

- An AI client that checks a stale MCP registration before opening the
  browser (mcp-remote) is now sent on to the sign-in like a browser when its
  callback is on the user's computer, and signs in once under the id it
  holds. 0.9.25 answered `invalid_client` there, on which mcp-remote
  registered again but kept waiting on the sign-in it had already started,
  browser unopened, until its next restart. A callback elsewhere still gets
  the OAuth error.

## [0.9.25] - 2026-09-11

### Fixed

- An AI client whose MCP registration this install no longer recognises (one
  issued before 0.9.23, or under another secret) reconnects without anyone
  deleting its cache by hand. A client that checks its registration before
  opening the browser (mcp-remote) is told `invalid_client` in the OAuth
  format and registers again by itself; a browser sent by a client waiting on
  the user's own computer goes on to the sign-in and the consent like any
  other client, on a consent page that says the client is unregistered.
  Bouncing such a client back to its callback with an error, as 0.9.23 did,
  made it retry, one browser window per try.

### Added

- The appliance smoke test proves both recoveries: a stale registration is
  told `invalid_client` when the client asks for JSON, and still reaches the
  sign-in when a browser brings it with a callback on the user's computer.

## [0.9.24] - 2026-09-10

### Fixed

- Approving an AI client in the browser no longer fails with "cross-origin
  request blocked". The consent page hid the referrer from itself, which made
  browsers send a null Origin on the consent form's own POST, and the gateway
  then refused it. The page now keeps the referrer for same-origin requests
  and the gateway also accepts the browser's own same-origin attestation.

### Added

- The appliance smoke test proves AI clients keep their MCP registration: it
  registers a client and requires a signed registration, checks the
  authorization page accepts it, and re-checks the client it registered on
  the previous run after every update or restart.

## [0.9.23] - 2026-09-10

### Fixed

- AI clients stay connected to the MCP gateway across gateway restarts and
  token expiry. A client registration is now a signed identifier the gateway
  verifies instead of a record it kept in memory, and the short-lived access
  token comes with a rotating refresh token bound to the operator's platform
  session. Before, every restart or update of the appliance forgot the
  client's registration and the client looped on the authorization page
  ("invalid client or redirect_uri") in the browser.

## [0.9.22] - 2026-09-09

### Changed

- The tools only Enterprise serves (`get_model`, `get_view`,
  `find_inconsistencies`, `apply_rule`, `generate_artifact`) are stand-ins on
  Community: same names, one argument, an answer that says what to use
  instead. Their real arguments live with the Enterprise overlay, as does the
  list of Enterprise constructs the open-source boundary test refuses.

### Removed

- The `paid` tier and the Canvas placeholder page: the editions are Community
  and Enterprise, nothing else.

## [0.9.21] - 2026-09-09

### Added

- Documents & Sources: a registered source must stay reachable by whoever
  reads the specification, through a web address anyone can open or through
  its content carried verbatim in the note. A row nobody else can open is
  reported when it is saved and by the completion gate (`source-unreachable`,
  `source-empty`), and the MCP playbooks state the rule.

### Fixed

- Behaviour dashboard: a checked state deletion started from `/behavior` on an
  appliance failed with "cross-origin request blocked". The dashboard calls the
  platform on its internal service name, and the CSRF guard refused that origin
  whenever `LYRIKS_TRUSTED_ORIGINS` named only the public one. The request's
  own origin is now always trusted beside the configured list.
- Shell: the user menu dropped from the initials opened behind the Control
  Center when the panel was open. The header now stands above side panels
  and below modal overlays.

## [0.9.20] - 2026-09-08

### Security

- Require explicit MCP client consent and issue opaque, revocable access tokens.
  Raw browser sessions are no longer accepted as MCP bearer credentials.
- Revoke local sessions after logout or a password change, including the MCP
  grants backed by those sessions and already-open collaboration sockets.
- Authorize collaboration rooms against their project and isolate the relay's
  room identifiers by project. Restrict the shared multi-user behavior editor
  to installation administrators.
- Reject unsafe login redirects and archives with inconsistent or excessive
  decompressed sizes. Update affected application dependencies.
- Scan the final platform, MCP and behavior images before publishing any of
  them. Preserve the scanned images and their build attestations for publication;
  retain complete reports, including vulnerabilities without an available fix.
- Exclude build dependencies and package managers from runtime images.

### Fixed

- Ship PostgreSQL 16 backup and restore clients to match the Compose database.
  The previous version 15 client refused to back up a version 16 server.
- Publish the scanned images: the publisher selects the tagged entry inside
  the OCI archive instead of failing on an archive that names several tags.

### Upgrade notes

- Upgrade the platform and MCP gateway together, then reconnect MCP clients
  and approve the new consent screen.
- The behavior image now uses the engine version selected by the tested
  workspace lockfile. Updating npm's latest version alone does not change a
  release rebuild.

### Changed

- The behaviour viewer's image is `lyriks-behavior-community`, renamed from
  `lyriks-dashboard-community`: "dashboard" named a shape, not the job, and the
  container is the one the platform serves at `/behavior`. An appliance rewrites
  the name on its next update; a compose install pulls the new repository as
  soon as it pulls this tree's version.

## [0.9.19] - 2026-09-05

### Security

- The operator login is enforced by the declared edition, like product
  activation: a Community install cannot be configured into open mode. Only a
  `vite dev` boot, or a build that declares no edition, keeps the flag.

## [0.9.18] - 2026-09-05

### Added

- The MCP gateway is part of this repository (`packages/mcp`) and is built
  here as `lyriks-mcp-community`, beside `lyriks-dashboard-community`
  (`docker/dashboard.Dockerfile`): a Community appliance now pulls three images
  this repository publishes, and nothing else. `pnpm dev:mcp` runs the gateway
  in development, `pnpm test:mcp` runs its suite and its own open-source
  boundary test.
- Control Center: the Coherence page reads as a diagnosis. Cards state the
  problem from the reader's side, the headline tiles filter the list, decisions
  are traced, and the score history shows where a project moved.
- Every project starts with one sentence: from scratch, or from a codebase,
  which lands on the kickoff prompt an agent follows through the MCP.
- A select with literal options projects as an enum state, typed alike
  everywhere it is written.

### Fixed

- A projected state definition is refreshed on save instead of frozen by its
  first projection; a leftover state seed is typed from its value, not declared
  a string.
- The writer gate and the realtime relay decide who may write on their own,
  without a companion service.

## [0.9.17] - 2026-09-04

### Fixed

- A viewer reads what it was granted, and nothing more; the realtime relay
  admits writers only, like the behaviour sync.

### Security

- fast-uri 3.1.6: four HIGH advisories in the pinned 3.1.5.

## [0.9.16] - 2026-09-03

First open-source tree of the Community edition.

### Added

- The specification workspace: foundation, users and permissions, features
  with full behaviour depth, journeys and screens with the Experience
  simulator, rules and edge cases, data, architecture, evidence and
  traceability, generated artifacts.
- Coherence, completion and readiness scores on the heuristic engine, with the
  Control Center listing every gap and where to fix it.
- Roadmap and delivery: releases, sprints, tickets whose acceptance criteria
  are the modelled scenarios, and the implementation index that keeps the
  specification and the code in step.
- The behaviour engine (unspaghettit) as an isolated subprocess, with the
  behaviour dashboard served behind the platform session.
- The MCP gateway proxy at `/mcp` with the five authoring skills.
- One operator account held by the platform, claimed at first run with a free
  Community key, verified offline.
- Product activation, update awareness, in-app feedback, and the shared search
  bar on every list that grew past reading.