Company State and context
Company State is not everything a company remembers. It is the bounded, versioned truth that determines what the company can do next. Context is a projection of that state, not its authority.
Superself currently applies this model at the project level. Goals, decisions, conventions, objectives, milestones, work, reports, and evidence survive individual context windows and agent tools. The complete Company State Runtime extends that foundation across projects, policies, capabilities, and resource allocation; that company-wide loop is a target, not a claim about the current alpha. The boundary between what is shipped and what is target lives in the roadmap.
This is a state problem, not a memory problem
Model memory and conversation history help an agent recall earlier interactions. A knowledge base helps retrieve information. Neither one, by itself, answers operational questions such as:
- Which goal governs the work now?
- Was this direction confirmed, merely proposed, or superseded?
- Which outcome is active, blocked, or complete?
- Which criterion remains uncovered?
- Which evidence permits the next transition?
A transcript contains many statements with no lasting authority. A knowledge base may contain several mutually inconsistent answers. Company State is narrower: typed, current truth whose status and lineage can be reconstructed.
This does not mean that every useful fact belongs in state. Agent scratch work, private reasoning, raw provider output, and session-only instructions can be valuable without becoming governing records. Promoting all available information into current state would recreate the unbounded memory problem under a different name.
Event → State → Projection
Superself is built on one frame:
Event → State → Projection
what happened fold of events purpose-specific views
(append-only) ("now true") (context, status, view)
| Layer | Role | Authority |
|---|---|---|
| Event log | Append-only record of state-meaningful assertions and transitions | The only original: log.jsonl is the source from which everything else is rebuilt |
| Folded state | Deterministic interpretation of the complete event history | Current meaning: which records are live, proposed, superseded, retracted, blocked, or done |
| Projections | self context, self status, generated Markdown, HTML views |
Inspectable output; regenerated from the fold and never an independent write path |
State is never stored as truth; it is computed by the fold. Editing a generated file cannot create authority. The next fold detects or overwrites drift because state changes must enter through typed events.
One record kind: the entity
Every asserted record folds into one shape — the entity. A goal, a decision, a convention, an objective, a milestone, and a work unit are not parallel type systems; they are entities with different labels and default placement.
An entity carries:
- text — the assertion itself, immutable after confirmation; supersede to change it;
- labels — free strings; the presets use
goal,objective,convention,decision,milestone,work; - links — typed references:
member-ofgroups,supersedescarries lineage, a bare id relates; - reserved metadata — a minimal vocabulary the fold interprets:
target(an ISO date that makes a deadline live in derived state) andcriteria(exit criteria that gate done claims on evidence). The vocabulary grows only by explicit design decision; - why — optional rationale.
self state is the raw verb: state add records an entity under any label,
state list and state show read every asserted record back — the preset
records included — and state place moves one in context.
Presets are an alias table, not a type system
The preset verbs are sugar over the entity: each resolves its label and default placement through one user-editable alias table.
| Verb | Label | Default placement |
|---|---|---|
self goal |
goal | full · priority 0 |
self objective |
objective | full · priority 10 |
self milestone |
milestone | index · priority 20 |
self convention |
convention | full · priority 30 |
self decide |
decision | index · priority 40 |
self idea |
idea | search |
self roadmap |
roadmap | index |
self work |
work | search (live state shows the active ones) |
Built-in rows are defaults, never constraints: self alias set overrides one,
self alias add <verb> adds a verb of your own, and every alias verb accepts
explicit placement flags that beat the row's defaults. self alias prints the
merged table.
How a state change becomes current truth
The write path has one event gate:
human or agent assertion
↓
typed command + origin + references
↓
sanitize
↓
append event or atomic event set to log.jsonl
↓
fold the complete project history
↓
derive current state, refusals, waiting items, and health
↓
render Markdown and terminal/viewer projections; refresh managed blocks
↓
commit the event history and versioned store projections to workspace Git
Every entity shares one event grammar, whoever asserts it: entity.proposed
and entity.confirmed assert, entity.superseded replaces with a linked
successor, entity.retracted withdraws with a reason, entity.placed moves
placement, entity.linked and entity.unlinked edit edges, and
entity.covered records a coverage claim against a declared criterion. The
execution events — entity.started, entity.blocked, entity.unblocked,
entity.done, entity.retired — are facts about doing rather than
assertions. Every mutation records its actor; agents and people share the
grammar.
The appended event bytes are the durable change. If rendering fails afterward,
the event remains and a later self fold can regenerate its projections.
HTML views are local generated output, and managed blocks live in the project
repository; neither becomes authoritative merely because the fold rendered it.
Placement: scope × priority × exposure
Every entity carries three placement values, each changeable by
entity.placed:
| Axis | Values | Meaning |
|---|---|---|
| scope | project | workspace |
which contexts it enters; a workspace-scoped entity renders in every project's context |
| priority | sparse integer (0, 10, 20, …) | render order; 0 is the top of context, ties break by recency |
| exposure | full | index | search |
render form: full text / one line / absent with a pointer |
Priority replaces a hardcoded section order with one rule: render in priority order until the budget is spent, then pointers. Exposure is per entity, not per label — one convention may be full while another has decayed to index.
A demotion — exposure moving toward less-rendered — always records --why.
Demotion out of full is human-owned by convention: an agent records the move
with --proposed, and it waits until a person runs self state confirm.
Retention caps
The always-rendered set is bounded by policy: user-set caps, enforced by the
engine on state add, state place, and the alias verbs, per scope. Both
tiers are measured in context tokens — the unit the budget is actually spent
in — and the defaults are 1,000 tokens of full-exposure text and 12,000 for
the index (fullTokens and indexTokens in the store's config.json).
The CLI counts characters and converts with one number, which self tokens
prints and a measurement replaces. It ships as an estimate and says so in
every refusal it produced, because two models tokenize the same sentence
differently and no single exact count exists to hard-code.
Adding or placing past a cap is refused until the caller names what demotes:
--demote <id> frees the room by moving a named entity one tier down. An
agent that passes --proposed lands the add and the demotion as a pair that
waits on a person; without it both halves apply at once. The gate binds
state add, state place, and the alias verbs — the preset verbs do not
route through it yet (see the roadmap). Rendering itself
never refuses.
Context is a projection, not a dump
self context projects the folded state in four steps:
1 collect: workspace-scoped entities + this project's entities
2 order: by priority, ties by recency
3 render: full → full text · index → one line · search → absent with a pointer
4 anchor: derived live state after the full block, before the index lines
The derived live state is engine-owned — computed, never asserted:
- work in progress and items waiting on a person render as full rows;
- all other open work is a count with a recovery pointer;
- deadlines derive from
targetmetadata; health signals and unshipped branches derive from the checkout.
Different consumers still need different amounts of the same state:
| Surface | What it provides |
|---|---|
Managed AGENTS.md and CLAUDE.md block |
Stable operating protocol plus current conventions |
self context inside a registered project |
That project's placed entities plus live state |
self context outside a registered project |
A workspace overview: each registered project's goal, work-status counts, and health-signal count |
self work show <id> |
The full recovery line for one unit: outcome, current status, reports, evidence |
self search <query> |
Live records context does not render, across registered projects, with the current project ranked first |
self state show <id> --history |
One record's own events, oldest first — the only path to history |
self log [-n N] |
Recent event inspection for operational or forensic reading |
The agent-facing render — a pipe, a redirect, --plain, TERM=dumb, or a
narrow terminal — enforces a 3,000-token budget and keeps omitted detail
reachable through recovery pointers that name the project they are about. The
human-oriented TTY presentation deliberately bypasses that budget.
This push/pull split addresses two opposite failures: injecting all history eventually overwhelms the context window, and injecting too little forces every new session to reconstruct the project.
Append history; replace the current view
Superself changes current truth by adding events, not by rewriting earlier ones. Consider a decision-labeled entity:
entity.proposed A
↓
entity.confirmed B → confirms A
↓
entity.confirmed C → supersedes B
The current view shows C as the governing decision. A and B remain in history, with their relationships intact. The same principle applies to placement, criteria coverage, and completion.
A withdrawal is terminal: once a record is retracted, a later event naming it does not move it back. Revision also invalidates conclusions that depended on the previous subject — a superseding revision of a milestone starts with its criteria uncovered, because coverage claims bind to the entity id they covered.
Done is gated on evidence
The execution events record facts about doing, and completion is the guarded
one. entity.done must carry evidence: a report with a commit or an artifact,
or a done-time report that states what verifiably happened. A bare claim is
refused. If the entity declares criteria, done is additionally gated on a
coverage claim (entity.covered) for every criterion.
This separates distinctions that survive the context window:
- proposed versus confirmed records;
- a report versus the judgment that the outcome was reached;
- an exited process versus completed work;
- evidence existing versus a gate accepting that evidence.
These distinctions let execution move between models and sessions without moving authority into the model's private memory. Context tells an agent what the current state says; typed transitions and shared gates decide whether the state may advance.
Machine-local runtime state
Some facts must not enter the synced semantic record:
- absolute checkout paths and the machine's selected workspace pointer;
- process ids and live ownership — the pid ledger (
work started/work exited), judged only on the machine that recorded it; - raw provider output.
Sanitized semantic results and artifact declarations fold into project state
through reports (report.added); the process transitions that do sync
(work.run-started, work.run-exited) carry the work id and exit code, never
the pid. This keeps a syncable company record from becoming a copy of every
provider transcript or host detail.
Legacy records read as entities
The log is append-only, so the cutover to the entity grammar rewrote nothing. The fold reads the pre-cutover record kinds as entities:
| Legacy event | Reads as |
|---|---|
goal.set |
entity(goal, full, priority 0), superseding the previous goal |
decision.proposed / decision.confirmed |
entity(decision, index) with the same lifecycle |
convention.added / convention.dropped |
entity(convention, full) / retracted |
objective.created |
entity(objective, full) with its target |
milestone.created |
entity(milestone, index) with its criteria |
work.created / work.started / … |
entity(work) plus execution facts |
report.added |
unchanged |
These legacy names are read forever and written by no verb. A workspace whose log holds them keeps folding; the CLI emits only the entity grammar.
What the alpha proves — and what it does not
The current OSS keeps per-project event history in a Git-backed workspace store, folds every asserted record into placed entities, regenerates readable views, gives a fresh session bounded context with explicit recovery paths, and synchronizes the store through a configured Git remote, which should normally be private.
It does not yet provide governing company direction above individual project goals, one cross-project graph for readiness and resource allocation, a general scope contract for every agent action, or automatic evidence-backed completion. Project State is the shipped wedge; the roadmap owns the exact boundary.
Continue reading
- Use Getting started with Superself to create the workspace, register a project, record initial state, and configure Git synchronization.
- Use Running a long-term project to operate goals, milestones, work, reports, and evidence across sessions.
- Use the CLI and record reference for the current command families and record contracts.
- Read the roadmap for the path from the current project-state foundation to the complete Company State Runtime loop.