Documentation Index
Fetch the complete documentation index at: https://docs.oktolabs.ai/llms.txt
Use this file to discover all available pages before exploring further.
Archive & retention
Pulse never hard-deletes graph data. Two layers cooperate:- Entity archive —
archive_tree/restore_treemark a Pulse entity (ideation, refinement, spec, sprint, card) and its children as archived. Their KG nodes stay queryable. - KG retention —
Decision,Constraint, and other graph nodes are retired throughsupersedesedges, not by deletion. A daily decay tick reduces stale-node relevance scores. Dead-letter entries linger until an operator inspects them.
Entity archive — the 2 tools
Source:okto-pulse-core/src/okto_pulse/core/mcp/server.py. Citations: 80-pulse-feature-inventory.md:392–393, :566–567, :814–848.
okto_pulse_archive_tree
Archive an entity and all of its children (cascading soft-delete). The entity is hidden from default views but every row remains in the database.
server.py:6733. Permission: the entity-scoped <entity>.entity.archive flag in the granular registry — e.g. spec.entity.archive for archiving a spec, card.entity.archive for archiving a card.
| Root | Children archived along with it |
|---|---|
| Ideation | Linked refinements (only if not also linked elsewhere) |
| Refinement | Specs derived from this refinement (only if not multi-parent) |
| Spec | Sprints scoped to this spec, plus their cards |
| Sprint | Cards in this sprint |
| Card | (leaf — no cascade) |
kg_impact.nodes_kept reports how many graph nodes reference the archived tree by belongs_to. Those nodes are not removed. Their decisions, constraints, and learnings remain queryable by every read tool — including across boards via kg_query_global.
okto_pulse_restore_tree
Reverse of archive_tree. Restores the entity and every cascade entry that was archived in the same operation.
server.py:6777. Permission: the entity-scoped <entity>.entity.restore flag — e.g. spec.entity.restore.
Permissions per entity type
80-pulse-feature-inventory.md:814–848. Every entity type that supports archival exposes archive and restore flags under its <entity>.entity.* namespace in core/infra/permissions.py:PERMISSION_REGISTRY:
| Entity | Archive flag | Restore flag |
|---|---|---|
| Ideation | ideation.entity.archive | ideation.entity.restore |
| Refinement | refinement.entity.archive | refinement.entity.restore |
| Spec | spec.entity.archive | spec.entity.restore |
| Sprint | sprint.entity.archive | sprint.entity.restore |
| Card | card.entity.archive | card.entity.restore |
Underlying REST endpoints
| Method | Path |
|---|---|
POST | /boards/{board_id}/archive/{entity_type}/{entity_id} |
POST | /boards/{board_id}/restore/{entity_type}/{entity_id} |
80-pulse-feature-inventory.md:566–567. The MCP tools wrap these directly — most callers should prefer the MCP tools.
How archive interacts with the Knowledge Graph
When a Pulse entity is archived, three things happen on the KG side:- Graph nodes are not deleted. Every
Decision,Constraint,Requirement, etc. that was consolidated from the archived entity stays ingraph.lbug. Queries continue to return them. belongs_toedges remain. The structural link from the graph node to its source artifact is preserved. Queries can still walk back to the (now-archived) entity row.- Audit rows are immutable. The consolidation audit table is append-only. An archive operation never edits or deletes audit rows.
kg_impact.nodes_kept — a count, not a delete. This is by design: a decision that turned out to be wrong is a decision worth keeping in the graph, marked as superseded, so future agents can see why the team moved away from it.
If the goal is to retire a decision (not the entity that produced it), the right move is a new consolidation session that adds a supersedes edge from the new node to the old one. See consolidation — add_edge_candidate.
KG retention model
The graph is durable, but it is not append-only forever. Three mechanisms keep it useful at scale:Supersedence — the structural soft-archive
When aDecision is replaced, the new node is added with a supersedes edge to the old one. The old node is preserved. Queries that walk the chain (kg_get_supersedence_chain) return both, in order.
This is the canonical way to “retire” a decision in the KG. There is no delete_decision MCP tool — and there will not be one. The supersedence chain is the audit trail.
Decay tick — relevance, not deletion
The decay tick worker (kg/workers/kg_decay_tick.py) runs daily by default (kg_decay_tick_interval_minutes = 1440). For each node whose last_recomputed_at is older than kg_decay_tick_staleness_days (default 7), it recomputes relevance_score based on age, citation count, and edge centrality.
Stale nodes don’t disappear — they sink in default rankings. kg_find_similar_decisions and kg_query_natural return higher-relevance nodes first. Direct queries (kg_get_decision_history, kg_query_cypher) still return everything.
To force a recompute without waiting for the schedule, use kg_tick_run_now.
Dead-letter retention
Failed consolidation entries land in a dead-letter table afterkg_queue_max_attempts retries. They are kept indefinitely until an operator either:
- Calls
kg_dead_letter_reprocessto retry them, or - Decides the underlying source no longer exists and removes the row directly from the database.
Audit-row immutability
The consolidation audit table is append-only. Everykg_commit_consolidation call writes one row containing the session id, content hash, every candidate, every reconciliation hint, every override, and the agent identity. Archiving a Pulse entity does not edit or delete audit rows. Migrating the schema does not edit audit rows. The graph state can be reconstructed from the audit table at any point in history.
Retention vs. archive — pick the right tool
| You want to… | Tool |
|---|---|
| Hide a spec from the default board view, but keep its decisions queryable | okto_pulse_archive_tree |
| Bring back a spec that was archived | okto_pulse_restore_tree |
| Retire a decision while preserving the rationale chain | New consolidation session with a supersedes edge — see consolidation |
| Reduce ranking weight of stale decisions | okto_pulse_kg_tick_run_now (or wait for the daily schedule) |
| Remove a dead-letter entry that will never succeed | DB-level delete (no MCP tool — by design) |
Common scenarios
”We retired a feature — archive its specs but keep the decisions”
archive_treeon each retired spec. Cascade carries sprints and cards.- KG nodes for those specs (
Decision,Constraint,Requirement) stay. They are returned by every read tool. - To make the supersedence explicit, open a consolidation session and add
supersedesedges from the replacement specs’ decisions to the retired ones.
”We archived the wrong spec”
restore_treeon the same(entity_type, entity_id). The full cascade restores.- Any KG nodes consolidated since the archive remain — restore is a
belongs_toflip, not a graph rewrite.
”Old decisions are dominating new search results”
- Force a decay tick:
kg_tick_run_now. - If still ranking high, the issue is recency weighting in
find_similar_decisions(0.2 × recency in the formula atkg_service.py:244). Usekg_get_decision_historywithsincefilter for time-bounded results.
Next steps
Overview
Schema, storage layout, and the full 26-tool index.
Health & migration
Operate the consolidation pipeline, dead-letter, and decay tick.