Commit graph Brokkr/brokkr-command
Author SHA1 Message Date
Meta Vens
e2f1cc7942 Pin CultLib 2.0.0 for builds
Directory.Build.props names CultLibRoot (CULTLIB_ROOT, else the sibling checkout) and pins CultLibRevision to cultlib-unity-v2.0.0 (42dce361). Directory.Build.targets fails the build unless that checkout is at the pin and clean, as Aetheria's guard does. Project references use CultLibRoot.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 19:46:07 +02:00
Meta Vens
121fa329e2 Soul pass 3: conditional enable in Runtime, receipt floor, one write path
- The enable commit is conditional (ExpectUnchanged) and lives in the new
  Runtime BrokkrCommandStore, with the pull-recompute-retry loop in
  BrokkrCommandDrain.EnableAsync, so the tests exercise the shipped code. An
  intent landing between the pull and the commit is expired, not run; eight
  refusals in a row fail the enable loudly with the sink off. The probe is now
  a thin fault-injecting wrapper over the real store, not a copy of it.
- Every editor write to the command lane is one cache commit; durable shard
  logs are off (no server, no reader).
- No receipt is pruned before ten minutes, whatever the count, and the CLI
  refuses a wait over five minutes. Fixed the comments that claimed otherwise.
- Pending and Prunable count a document only under the key its own id names.
- README and snapshot comment: the token stops stale EditorPrefs, it does not
  authenticate writers; a restored or sync-conflict copy of the editor's own
  store can rerun answered intents.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 17:52:34 +02:00
Meta Vens
9f5e8fbf3c Decide "before the enable" by the store, batch the expiry, bound receipts
Soul pass 2 findings S1, S2, S3, S4.

- Enabling the sink is the drain's EnableAsync: every intent already in the
  store gets an "expired" receipt and the enable marker is written, all in one
  flush. No decision compares StoredAt with a clock any more, so a fast
  writer clock and the Rust daemon's secs.nanosZ stamps stop mattering.
- The operator's EditorPrefs hold a token, and the sink runs only while the
  store carries the marker with that token. A re-clone or a copied .brokkr has
  no such marker, so a stale "enabled" authorizes nothing and the editor drops
  it. The epoch and agentCommandsEnabledAt (host snapshot key 19) are gone.
- Selection is one pass over the store per tick (Pending), not a copy and sort
  per intent.
- Receipts are capped at the newest 1000, pruned 128 pairs per tick with the
  intent deleted before its receipt.
- A marker that could not be written is withdrawn, so the intent reads as
  never started and is retried, not "interrupted".
- The drain writes through IBrokkrCommandStore; puts stage and one flush makes
  them durable.
- The CLI timeout text no longer says the intent "stays written" without the
  expiry caveat; the check-then-write window on --command-id is documented.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 16:56:33 +02:00
Meta Vens
350c5626c3 brokkr-command: say "cannot be opened", and pin the catch-all with a mid-flight failure
A store that fails to open is not always unreadable (a held lock does it too),
so the message says what happened. The catch-all's test now corrupts the store
after the CLI opened it, which the open's own handling cannot see.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 16:25:15 +02:00
Meta Vens
b451cddf1d brokkr-command: map every failure to exit 0/1/2, refuse a reused command id
- Any exception now exits 2 with a message. An empty or legacy store fails with
  a message that names the path instead of aborting with 134.
- A --command-id that already has a receipt is refused with exit 2, so a stale
  receipt is never reported as the answer to a new intent.
- The wait treats the editor's "attempted" marker as not yet a verdict.
- The action theory passes --output so captureEditorView clears admission now
  that the harness runs the real policy.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 16:16:50 +02:00
Meta Vens
12f2d426b1 A4: admission policy and the editor lifecycle actions
BrokkrCommandPolicy (Runtime, pure, tested outside Unity) is consulted by
BrokkrEditorService before every BrokkrUnityCommandExecutor.Execute; it is the
only call path into the executor. The per-project allowed-action list defaults
to scene mutation plus lifecycle; createScriptableObject, createPrefabVariant
and saveScene are shipped denied (parked Q4 = A), and an action the list does
not name is denied. A denial gets a receipt with status denied and a reason.
The window's buttons write intents like any other caller, so operator and
agent share the gate.

Re-landed from the donor as fresh code: refreshAssets, setEditorPlayState,
setEditorPaused, captureEditorView, and the play-state fields on the host
snapshot (keys 14-17). The donor's captureEditorView wrote to any rooted
outputPath; it now resolves the path through one function that accepts only a
plain relative .png path under <project>/.brokkr/captures and refuses drive
letters, rooted or UNC paths, stream suffixes and any .. segment on every host
OS, and dimensions are bounded to 8192. requestedBy joins the intent (key 17)
and is echoed on the receipt (key 6). saveScene is new.

The window gains an Allowed Actions field bound to a per-project preference.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 14:44:31 +02:00
Meta Vens
1e46483fe5 A3: brokkr-command, the caller CLI, with every intent field and a real CultLib root
Re-landed from the donor as a fresh file (read with git show, not merged).
Changes from the donor: the CultLibRoot default is ..\..\CultLib instead of a
directory that does not exist; every field of brokkr.unity.command_intent.v0
has a --kebab option (the donor mapped six of seventeen), and unknown options
are refused before anything is written; keys come from BrokkrCommandLedger;
exit is 0 accepted, 1 other receipt, 2 usage error or timeout; readHost opens
the store read-only and prints the agent-commands flag; a timeout says when
the editor reports the sink off. The intent gains the capture fields at keys
13-16, which the CLI needs and A4's executor will read.

Tests run the built CLI as a process against the editor probe: field mapping,
fresh id per invocation, exit code from the receipt, timeout leaves only the
intent, unknown option writes nothing, and every action name reaches the
editor once with one receipt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 14:26:23 +02:00