ShadowGraph
OfficialShadowGraph is an MCP server for recording, retrieving, reviewing, and maintaining project decision memory and scoped development experience.
Record decisions with chosen options, assumptions, evidence, rejected alternatives, and reopen rules.
Record attempts/results and observed facts with provenance, confidence, and validity windows.
Store and reconcile scoped memories (preference, profile, goal, instruction, procedure, episode, note) using ADD/UPDATE/DELETE/NOOP batches.
Update decision lifecycle status, outcomes, confidence evidence, and supersession relationships.
Review and reconsider decisions by evaluating reopen conditions, persisting/acknowledging review signals, and loading a project working set.
Search records, retrieve one-hop graph neighbours, recall/rank memory, build context, and expand context-line handles.
Run maintenance to age decisions, expire facts, and evaluate due conditions; validate store integrity.
Enforce project/origin/access-grant scoping, audited reads, and completeness/provenance metadata.
Supports optional OpenAI-compatible embedding endpoints to generate semantic embeddings used for vector-based recall of scoped memory; remote endpoints are opt-in.
ShadowGraph
Carry useful development experience into the next agent session.
ShadowGraph records what worked, what failed, and why a decision was made—then supplies relevant experience when you continue working. The demonstrated automatic paths are the Windows Codex terminal wrapper and, in print mode, Claude Code CLI hooks on Windows, after one-time setup in projects you enroll.
Get started · Supported workflows · Release & downloads · Documentation
After setup, work normally. Memory processes in the background; reuse follows your project and sharing choices. Editable diagram.
From a failed check to useful experience
In a bounded Windows demonstration, an agent ran a parser check that failed because empty fields were missing. It removed a filtering step and reran the unchanged check successfully. Its explanation included the rejected alternative: reconstructing empty fields later would lose their original positions and add complexity.
The wrapper captured the actual command results and explanation. A fresh session working on a differently delimited reader received the relevant experience automatically, identified it as prior-session evidence before its first command, and preserved empty fields in its implementation. Its check passed.
This demonstrates one working path, not perfect recall. Extraction can be delayed: two ordinary tasks completed while earlier memory was still pending, then processing recovered automatically. No memory reminder or manual extraction command was needed.
Related MCP server: Memryzed
Quick start: Windows Codex
Prerequisites
Windows x64, PowerShell 7+, and Node.js 22.5+ with npm (Node 24 recommended).
Codex CLI 0.161.0, signed in through your existing ChatGPT subscription. The adapter explicitly selects
gpt-6.1-sol; other executor versions and API-key/provider overrides are not supported by this profile.A project you choose to enroll, and a private directory outside source control for memory and configuration.
The Codex executor is a separate prerequisite distributed as @openai/codex. ShadowGraph itself is not published to npm. Installing ShadowGraph alone does not enable automatic memory.
1. Install
Run in PowerShell 7+. The version is pinned; the release includes SHA256SUMS.txt for the tarball.
npm install --global https://github.com/LiLara-AI/shadowgraph/releases/download/v0.43.4/shadowgraph-unified-plugin-0.43.4.tgz
$executorDir = Join-Path $env:LOCALAPPDATA 'ShadowGraph-Codex-0.161.0'
npm install --prefix $executorDir @openai/codex@0.161.0
$codexExe = (Get-ChildItem (Join-Path $executorDir 'node_modules/@openai') -Filter codex.exe -Recurse | Select-Object -First 1).FullName
& $codexExe --version
& $codexExe login statusIf needed, use & $codexExe login and complete Codex's normal sign-in yourself. Select the native codex.exe, not an npm shim. Setup checks its version, binary identity and account route. Do not copy authentication files.
2. Enroll your project once
Run this from the project directory you want to enroll. Choose a descriptive project name; demo is an example.
$memoryHome = Join-Path $env:LOCALAPPDATA 'ShadowGraph-Codex-Memory'
$setupFile = Join-Path $env:LOCALAPPDATA 'shadowgraph-codex-setup.json'
@{
executable = $codexExe
hostMode = 'workspace'
projects = @(@{ project = 'demo'; cwd = (Get-Location).Path })
} | ConvertTo-Json -Depth 5 | Set-Content -Encoding utf8 $setupFile
shadowgraph-codex.cmd setup --config $setupFile --home $memoryHome
shadowgraph-codex.cmd status --home $memoryHomePersistent setup asks for genuine owner consent at your terminal. Review the project, executor and provider scope before confirming. Workspace permissions and managed execution rules still apply. PowerShell 7 writes this JSON as UTF-8 without a byte-order mark.
3. Work normally
From the enrolled project, launch:
$memoryHome = Join-Path $env:LOCALAPPDATA 'ShadowGraph-Codex-Memory'
shadowgraph-codex.cmd run --home $memoryHomeEnter ordinary task prompts, one line per turn. Launch the same command again for a fresh session. Relevant memory is supplied before each new turn; you do not need to say “remember” or “search memory.” Only work launched through this wrapper is observed.
Answers appear without waiting for extraction. Pending memory retries while the wrapper is open and on later launches. Closing it stops the bounded worker; there is no permanent background daemon. For configuration, pending-state troubleshooting and limits, see the Codex guide.
What survives a session
Experience | What stays attached |
Decisions | Chosen approach, alternatives, reasons and conditions for reconsideration |
Attempts and outcomes | What was tried and the observed result; inferred causes remain distinct |
Evidence | Source quotations, captured command results and provenance |
Current state | Corrections and supersession, while retaining history |
Uncertainty | Model-proposed interpretation, missing conditions and limits of the evidence |
Stored records are inspectable. A model interpretation is not independently verified truth, and a useful lesson is not automatically valid in every project.
Sharing and control
Memory starts project-only. You can explicitly share selected enrolled projects, select all currently permitted projects, exclude sources, revoke wider sharing, or pause the integration. Capture scope and read sharing are separate choices.
# From an enrolled project; use the same private home as setup.
shadowgraph-codex.cmd share --home $memoryHome --mode selected --projects demo,shared-library
shadowgraph-codex.cmd share --home $memoryHome --mode all-permitted --exclude confidential-project
shadowgraph-codex.cmd share --home $memoryHome --mode project
shadowgraph-codex.cmd pause --home $memoryHome
shadowgraph-codex.cmd resume --home $memoryHomeReplace names with your enrolled projects. Sharing is explicit and revocable, not an automatic permission detector. Corrections retain history; source dependencies prevent copied memory-informed answers from bypassing later revocation. Already displayed information cannot be erased from a transcript or a person's knowledge. Details and inspection commands.
Local-first, with a configured provider. Canonical memory stays in your private local store. Automatic extraction and host delivery send selected captured/context data through the configured model provider and require its account and network. Pattern redaction cannot guarantee every secret is removed. There is no hosted sync or telemetry. Data lifecycle, backup and deletion.
MCP interface profiles
Full remains the default (35 tools, or 36 with a configured verifier). Compact remains 16 tools. The new opt-in Workflow Profile offers 20 tools: Compact plus stored review signals, keyed confidence evidence, decision status transitions and explicit supersession, using the existing handlers and access controls.
Server environment | Inventory |
Profile unset; compact unset or | Full: 35 / 36 |
Profile unset; | Compact: 16 |
| Workflow: 20 |
Set the environment on the MCP server process, then restart/reconnect and refresh
tools/list. There is no agent-callable mode switch. Workflow does not expose
administrative repair or destructive cleanup. See the configuration and workflow
guide.
Use shadowgraph_search for literal every-term matching, shadowgraph_recall
for ranked experience, shadowgraph_retrieve for matches plus ordered graph
neighbours, shadowgraph_context for a working set without saving signals, and
shadowgraph_expand for a returned context-line handle. In Workflow or Full,
shadowgraph_review_signals reads saved review signals; shadowgraph_review,
shadowgraph_review_context and shadowgraph_reconsider evaluate reopen rules
and persist signals. Access-key reads save a bounded audit. See the read and
review guide.
Supported workflows
Workflow | What this preview establishes |
Windows | Installed command-executing workflow; automatic capture, background extraction, fresh-session delivery and recovery after delay/failure |
MCP, CLI, HTTP and JavaScript API | Explicit record/read operations; MCP exposes 16 compact or 35 full tools. Tool calls alone do not observe all work |
Claude Code CLI hooks (Windows) | After one-time setup on Claude Code CLI 2.x (verified on 2.1.302 and 2.1.312, print mode): durable capture under contention, automatic extraction by an owner-selected model, delivery to fresh sessions, corrections of decisions (a decision kept verbatim is linked and marked as corrected, not closed) and revocable sharing. On Windows, use Claude Code 2.1.312 or later: up to 2.1.302, |
Codex Desktop UI or ordinary CLI launched elsewhere | Not observed by this wrapper |
Glama MCP container | Credential-free MCP surface; cannot capture a user's Windows Codex sessions by itself |
The accepted Glama release read back on 2026-11-03 has display label 0.42.6 and runtime 0.43.2, with the 20-tool Workflow profile. See the release/runtime identity mapping. A new package release alone does not update that container.
Store locking and retry limits (0.43.1)
Store fences require a local filesystem with exclusive hard-link creation (tested on Linux and Windows CI). Network/shared filesystems, cross-host stores, mixed Windows/WSL writers and concurrent old/new runtime writers are not supported. Stop every writer and back up private state before upgrading; schema 7 is unchanged.
A live PID keeps its lock even if its timestamp is old. Stale store locks with a
dead owner are reclaimed serially. A .lock.reclaim guard is never stolen merely
because it is old: a suspended owner is indistinguishable from a crashed one.
If a crashed reclaimer leaves this guard while a stale store lock still needs
reclamation, writes time out with
storage_lock_timeout. Stop every process using that store (including hooks and
workers), preserve a private backup, positively identify the exact orphan guard,
then remove only that guard and retry. Follow the
stopped-writer recovery checklist.
Do not remove a live writer's lock or infer an orphan from age alone.
Lock-candidate .lock.*.candidate files contain ownership tokens, not store content;
a process killed before linking can leave one. Remove such orphans only with all
writers stopped.
Capture retries track an entry's stable payload key throughout one hook, including when another hook has renamed the file. A non-contention failure consumes at most one attempt per hook; after eight failed hook cycles the entry is dropped with a content-free marker. Store contention, deadline exhaustion and newer schemas leave input pending without consuming an attempt. Pending input survives hook restarts; the existing seven-day age and spool-size bounds still apply. This patch adds no new live model or automatic-memory support claims.
Preview limits
Each host turn has a 120-second process limit. Background extraction has bounded calls, retries and concurrency; a backlog can remain honestly pending. Native command events and user/assistant text are captured, but not every native tool-event type. Retrieval happens between turns, not inside a running turn.
For Claude Code CLI, delivered experience is not always applied: in one live run a fresh session received an earlier lesson and did not apply it. After extraction is deactivated and activated again, items left pending under the earlier setup are not extracted; status reports them as priorSetup. The Claude Code evidence is one Windows print-mode (claude -p) path, not every host.
This is Technical Preview, not stable/GA. There are no claims of perfect semantic classification, universal language support, cost or time savings, superiority over native memory, or a human third-party security audit. See release notes, security scope and benchmark status.
Upgrade and storage
0.43.2 tightens automatic correction evidence and transient file-error recovery, and reports capture gaps and loss-count saturation. Review acknowledgement keeps its accurate Destructive hint; a journal does not make replacement of current state additive. Patch details and recovery.
Stop active work and back up your stores and private integration home before upgrading. v0.43.2 retains schema 7; changed source/executor/account identity requires setup again. Older pending work with different setup provenance is held, not silently reassigned. Upgrade and rollback guide.
Moving between 0.41.0 and 0.42.0
The historical schema-5/schema-7 migration and downgrade instructions remain in the migration guide. Preserve a backup made before upgrading.
Documentation
Need | Guide |
Automatic Windows setup, sharing, limits and troubleshooting | |
Manual installation, MCP configuration, CLI/HTTP/JavaScript and storage | |
Other clients and existing hooks | |
API and protocol details | |
A decision that reopens when conditions change | |
Privacy, backups and recovery | |
Development and feedback |
Please redact private paths, prompts, stores and credentials before reporting an issue. Report security vulnerabilities privately.
MIT license. No npm publication, paid hosting or standing extraction is implied by installing this preview.
Available Tools
20 toolsshadowgraph_ack_reviewADestructive
Acknowledge one persisted review signal by id, closing it as open work. Pass reviewSignalId from shadowgraph_review or shadowgraph_review_context as id; shadowgraph_review_signals lists saved signals. Decision changes use shadowgraph_update_status or shadowgraph_supersede. Overwrites status and acknowledgedAt in place with no journal entry, so a rebuild cannot reconstruct it; a repeat restamps it.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Persisted signal id: reviewSignalId from shadowgraph_review or shadowgraph_review_context, or id from shadowgraph_review_signals. A fresh context evaluation can be unpersisted and have no ID. This is not the decisionId. | |
| project | No | Owning project; required unless originId is set, else the write is refused. | |
| originId | No | Capture-origin id; with no project the record belongs to it alone. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | Signal identifier, used by shadowgraph_ack_review. |
| kind | Yes | Always "review". |
| title | No | Decision title, when the stored decision has one. |
| reason | Yes | Why it was raised. Identity is this plus decisionId and coverage. |
| status | Yes | open until acknowledged. |
| coverage | No | Exact conditions covered, and part of this identity. |
| createdAt | Yes | ISO 8601 time the signal was raised. |
| decisionId | Yes | The decision this signal is about. |
| acknowledgedAt | Yes | ISO 8601 time of the most recent acknowledgement. |
| alternativesToReconsider | Yes | Alternative labels to look at again. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true and idempotentHint=false, but the description goes further: it discloses that status and acknowledgedAt are overwritten in place with no journal entry, that a rebuild cannot reconstruct the change, and that a repeat restamps it. That explains the mechanism behind the non-idempotency hint rather than repeating it. Minor gap: it does not state any permission or prerequisite requirement for the write.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four compact sentences, front-loaded with the action and its effect, then id sourcing, then alternatives, then the persistence caveat. No sentence is filler and each adds a distinct fact.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists, so return values need no explanation; the description instead covers the two things an agent must know before calling a destructive, non-journaled write: where the id comes from and that the change is unreconstructable. Nothing material is missing for a 3-parameter tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds cross-tool routing the schema cannot: it names which upstream field maps to id and warns off decisionId. It does not explain the project/originId interaction beyond what the schema already says, which keeps it from a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
"Acknowledge one persisted review signal by id, closing it as open work" gives a specific verb (acknowledge), a bounded resource (one persisted review signal), and the effect (closes open work). The scope word "persisted" alone separates it from acting on fresh, unpersisted context evaluations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It tells the agent exactly where the id comes from (reviewSignalId from shadowgraph_review or shadowgraph_review_context, or id from shadowgraph_review_signals) and explicitly routes decision changes to shadowgraph_update_status or shadowgraph_supersede. That is a named alternative with the condition that selects it, not just implied usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shadowgraph_confidence_evidenceADestructive
Apply one keyed piece of supporting or contradicting evidence to a decision's confidence. Use shadowgraph_record_outcome once the decision has played out, shadowgraph_record_fact for an observation that can reopen it. Reusing key cannot double-count, but restamps the decision and commits a revision; a new observation needs a new key.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | REQUIRED stable dedupe key. Reuse the same key for the same observation so retries cannot double-count; use a NEW key for a genuinely new observation. There is no default, because a generated one would only be stable within a millisecond. | |
| actor | No | Who performed this write, such as an agent or person name. Stored for audit; never used to grant trust. | |
| client | No | Which client software performed this write, such as the host application name. | |
| reason | Yes | Why this evidence matters. Required, non-empty, and kept in the audit history. | |
| project | No | Owning project; required unless originId is set, else the write is refused. | |
| originId | No | Capture-origin id; with no project the record belongs to it alone. | |
| supports | No | Defaults to true. false records contradicting evidence, moving confidence down instead of up. | |
| sessionId | No | Caller-owned identifier that groups related writes in the audit trail. | |
| decisionId | Yes | Identifier of an existing decision, as returned by shadowgraph_record_decision, shadowgraph_search, or shadowgraph_retrieve. | |
| observedAt | No | ISO 8601 time the evidence was observed. Defaults to now. | |
| sourceClass | No | Claimed origin, never proof: agent_claimed (the default), tool_observed, human_confirmed, or production_verified. It weights confidence only. An unrecognised label downgrades to agent_claimed, kept verbatim in sourceRaw. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | Stable entity identifier. |
| goal | No | What the decision was trying to achieve. |
| kind | Yes | Entity kind: decision, attempt, memory, fact, relation, review, or alternative. |
| actor | No | Who performed the write. |
| title | No | Short name of the decision. |
| chosen | No | The option that was chosen. |
| client | No | Which client performed the write. |
| status | No | Lifecycle state. Legacy records may carry a value this build does not recognise; shadowgraph_validate reports those. |
| outcome | No | The recorded outcome, or null until one is recorded. |
| project | No | Project namespace; null for an unattributed record or one imported from before projects. |
| evidence | No | Normalised evidence entries: source, type, sourceClass, confidence, observedAt, detail. |
| createdAt | No | ISO 8601 creation time. |
| migration | No | Present only on migrated records; records the legacy value a field was mapped from. |
| sessionId | No | Session identifier recorded with the write. |
| sourceRaw | No | The original origin label when it differed from sourceClass. Audit only; never evidence. |
| updatedAt | No | ISO 8601 time of the last change. |
| confidence | No | Auditable confidence: initial, current (0-1), policy, a history entry per move, and a basis summarising the contributions it was folded from. Legacy records may lack basis. |
| supersedes | No | Identifiers of decisions this one replaced. |
| assumptions | No | Assumptions the decision rests on. Searchable content. |
| reviewAfter | No | ISO 8601 instant after which shadowgraph_maintain marks this decision stale. |
| sourceClass | No | Claimed origin class recorded with the write. A claim, never proof. |
| alternatives | No | Rejected alternatives, each with id, label, reasonRejected, status, and the reopenWhen rules that make it reconsiderable. |
| supersededBy | No | Identifier of the decision that replaced this one. |
| schemaVersion | No | Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded. |
| failedAttempts | No | Attempt identifiers or notes attached to this decision. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=true and idempotentHint=false, so the agent knows this mutates state. The description adds real context beyond that: reusing a key cannot double-count but still restamps the decision and commits a revision, which explains the non-idempotent effect precisely. It does not cover permissions or what the restamp means for prior revisions, which keeps it below a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each doing distinct work: purpose, sibling routing, then the key/revision caveat. The core action is front-loaded and there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and all 11 parameters are documented in the schema. The description supplies the routing and idempotency semantics an agent needs, though it says nothing about authorization or how confidence is actually adjusted. Adequate and close to complete for this tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the key parameter already carries a thorough description of dedupe behavior, so the schema does the heavy lifting. The description's remarks about reusing versus creating a key largely restate that field rather than adding syntax or examples the schema lacks. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: applying one keyed piece of supporting or contradicting evidence to a decision's confidence. It also names the sibling tools it is not (record_outcome, record_fact), so an agent can separate it from those without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes: use shadowgraph_record_outcome once the decision has played out, and shadowgraph_record_fact for an observation that can reopen it. This is an explicit when-to-use-this vs when-to-use-the-alternative split, which is rare and valuable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shadowgraph_contextA
Read the project working set before planning: decisions, stale facts, failed attempts and fired conditions. shadowgraph_search matches every term; shadowgraph_retrieve adds neighbours; shadowgraph_recall ranks memory; shadowgraph_review_context persists signals. No decision or signal writes. Unmatched-query diagnostics stay in memory until a later save. No immediate revision without an access key; a key saves a revision and audit.
| Name | Required | Description | Default |
|---|---|---|---|
| asOf | No | ISO 8601 instant for relevant: facts and memories valid then, recency ordered from it, and lines derived as of it. | |
| facts | No | Temporary key/value overrides for object rules; unlisted keys use stored facts. Example: facts:{ready:true} tests {key:"ready",value:true}. This does not record a fact or fire a string rule; changedFacts supplies those changed-key signals. | |
| limit | No | Maximum items per collection, 1-1000, applied to each collection independently. Omit for the default of 50. | |
| query | No | Free text. With it or focalId, the response adds relevant: the records in scope that the lexical or graph signal ranks, ahead of the working set. No semantic signal is computed on this read. | |
| compact | No | With query or focalId, true delivers each relevant record as a shortened claim line (T1); false or omitted delivers full records. A line that would omit decisive meaning falls back to the full record. This controls record presentation, not the server tool mode. For example, query:"cache", compact:true adds relevant.items with expansion handles; compact:true alone does not add relevant. | |
| focalId | No | Entity id to rank graph neighbours from. An id outside the scope reaches nothing, like an unknown one. | |
| grantId | No | Alias for accessId; conflicting identifiers are refused. | |
| project | No | Project or confirmed workspace binding; otherwise origin-only. No identity returns an empty scoped view. | |
| accessId | No | Grant ID, rechecked at use. Widens reads only, never write authority. Presenting an access key commits a revision and bounded operational audit: at most one aggregate per grant, surface, outcome and UTC day. Conflicts with a different grantId are refused. | |
| originId | No | Capture-origin id; with no project the record belongs to it alone. | |
| changedFacts | No | Ephemeral changed-key signals for string-form reopenWhen rules; not stored facts. Example: changedFacts:["budget"] fires reopenWhen:["budget"]. Object rules instead read values from facts overrides or stored facts. |
Output Schema
| Name | Required | Description |
|---|---|---|
| notice | Yes | Declared interface metadata, not memory: context is a read, and reviewContext (shadowgraph_review_context) evaluates and persists. |
| project | Yes | The resolved project, or null when unresolved. |
| relevant | No | Present with query or focalId: records in scope ranked on the records themselves, head first. |
| completeness | Yes | Per-collection completeness. context returns several named collections, so one page object cannot describe it. |
| failedAttempts | Yes | Attempts that failed: resultClass failed or, with none and not captured, a result mentioning failure, regression, or error. |
| readProvenance | No | Original read bounds; reuse intersects these with currently valid authority. |
| activeDecisions | Yes | Decisions whose lifecycle status is current: proposed, planned, in_progress, executed, validated, or reconsidered. |
| firedConditions | Yes | Decisions whose recorded review conditions fired, with the conditions and the facts they were computed from. |
| reusableAttempts | No | Attempts whose reusableWhen conditions all hold now. The recorded failure still stands, and this is not authorisation to retry. |
| staleAssumptions | Yes | Facts that are no longer active, such as superseded or expired ones, which earlier decisions may still rest on. |
| conditionDiagnostics | No | Conditions that could not be settled, or that rest on facts which disagree. Neither a breach nor a confirmed-safe decision. |
| belowConfidenceThreshold | Yes | Decisions of any status whose recorded confidence is below the policy threshold. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false and the description explains why: it is a read, but presenting an access key 'commits a revision and bounded operational audit', and unmatched-query diagnostics persist in memory until a later save. These are non-obvious side effects that the annotations alone would not convey. It stops short of describing pagination or output shape, but the output schema covers that.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core purpose and scope are front-loaded in the first sentence, and every subsequent sentence maps to a sibling or a side effect. It is dense and somewhat telegraphic in places ('fired conditions', 'T1'), relying on jargon the agent must infer, which keeps it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 11-parameter tool, the description supplies the selection logic, the write side effect of accessId, and the statefulness of diagnostics; annotations cover the safety profile and an output schema exists. The remaining gap is that optional fields like asOf, project and focalId are left entirely to the schema, which is acceptable given full coverage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema coverage the baseline is 3, and the description still adds cross-parameter meaning: the access-key/audit tradeoff for accessId and the in-memory diagnostic retention tied to query. It does not re-explain facts, limit or changedFacts, which the schema already handles well.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and resource: 'Read the project working set', then enumerates what it returns (decisions, stale facts, failed attempts, fired conditions). It also names the four sibling tools and how each differs, so an agent can select it without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Read the project working set before planning' gives explicit timing, and the following clause routes the agent away from shadowgraph_search (exact term matching), shadowgraph_retrieve (neighbours), shadowgraph_recall (ranking) and shadowgraph_review_context (persists signals). This is exactly the when/when-not/alternatives structure the dimension rewards.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shadowgraph_expandA
Fetch the full current record behind a context line, with its expansion handle as input. shadowgraph_context supplies the handle; flatten its scope into top-level inputs. Own-scope read saves nothing; an access key commits a revision and bounded audit. Returns record, revision status and bounded counterparts. A stale digest yields revision_changed; inaccessible records yield unavailable.
| Name | Required | Description | Default |
|---|---|---|---|
| asOf | No | The line's expansion.asOf, when it has one. | |
| digest | Yes | The line's expansion.digest: the revision the line was derived from. | |
| grantId | No | Alias for accessId; conflicting identifiers are refused. | |
| project | No | Project or confirmed workspace binding; otherwise origin-only. No identity returns an empty scoped view. | |
| accessId | No | Grant ID, rechecked at use. Widens reads only, never write authority. Presenting an access key commits a revision and bounded operational audit: at most one aggregate per grant, surface, outcome and UTC day. Conflicts with a different grantId are refused. | |
| originId | No | Capture-origin id; with no project the record belongs to it alone. | |
| recordId | Yes | The line's expansion.recordId. | |
| derivedAt | No | The line's expansion.derivedAt. A logical purge of the read's own project recorded after it answers purged. | |
| maxExpansions | No | How many structural counterparts to fetch in full, 0-50. Defaults to 5; the rest are marked uninvestigated, with their lines. | |
| derivationVersion | No | The line's expansion.derivationVersion. |
Output Schema
| Name | Required | Description |
|---|---|---|
| record | Yes | The current full record, or null. Never a summary and never the old revision. |
| status | Yes | current: the line came from this revision. revision_changed: the record changed since, and this is the current record. purged: the first purge of the read's own project after the line was logical. unavailable: no record with this id is served in the scope. |
| recordId | Yes | The record the line named. |
| completeness | Yes | Request coverage and any withheld detail. |
| boundRevision | Yes | The revision the line was derived from. |
| investigation | Yes | Counterparts investigated within the budget; null when no record is served. |
| readProvenance | No | Original read bounds; reuse intersects these with currently valid authority. |
| currentRevision | Yes | The live revision; null when no record is served. |
| revisionChanged | Yes | Whether the record changed after the line was derived; null when no record is served. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false and idempotentHint=false without explaining why; the description fills that gap by disclosing that presenting an access key commits a revision and a bounded audit while an own-scope read has no side effects. It also enumerates failure modes (stale digest → revision_changed, inaccessible → unavailable), which is behavior an agent cannot infer from the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then prerequisite, side effect, return shape and error outcomes — each sentence carries distinct information with no filler. The density of domain jargon makes some clauses ('Own-scope read saves nothing') require a second read, costing a point.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values needn't be spelled out, yet the description still flags the three things an agent must anticipate: record/revision status/counterparts, revision_changed on a stale digest, and unavailable on access failure. With 10 parameters at full schema coverage, nothing material is left undocumented.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema itself is unusually descriptive, so the baseline is 3. The description still adds construction guidance ('with its expansion handle as input', 'flatten its scope into top-level inputs') that tells the agent how to derive the arguments rather than just what they are, pushing it to a 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Fetch the full current record behind a context line') and names the sibling that produces its input (shadowgraph_context), which lets an agent place it in the workflow. The jargon ('context line', 'expansion handle') is domain-specific and not self-explanatory, keeping it just short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit prerequisite chain — shadowgraph_context supplies the handle, then flatten its scope into top-level inputs — and distinguishes the own-scope read from the access-key read by consequence ('saves nothing' vs 'commits a revision and bounded audit'). It stops short of naming a concrete when-not-to-use alternative among the many record_* siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shadowgraph_maintainADestructive
Age due owned decisions to stale, expire due owned facts, then evaluate reopen rules. shadowgraph_review evaluates without aging; shadowgraph_validate diagnoses integrity. Maintenance does not repair or restore. Uses now or the clock; saves lifecycle changes and signals, even on repeats. Grants widen audited reads, not writes. Returns changed IDs, due items and stored signals, including acknowledged ones.
| Name | Required | Description | Default |
|---|---|---|---|
| now | No | ISO 8601 instant to treat as the current time. Defaults to the real clock; supplying it makes the run deterministic. | |
| facts | No | Temporary key/value overrides for object rules; unlisted keys use stored facts. Example: facts:{ready:true} tests {key:"ready",value:true}. This does not record a fact or fire a string rule; changedFacts supplies those changed-key signals. | |
| grantId | No | Alias for accessId; conflicting identifiers are refused. | |
| project | No | Project or confirmed workspace binding; otherwise origin-only. No identity returns an empty scoped view. | |
| accessId | No | Grant ID, rechecked at use. Widens reads only, never write authority. Presenting an access key commits a revision and bounded operational audit: at most one aggregate per grant, surface, outcome and UTC day. Conflicts with a different grantId are refused. | |
| originId | No | Capture-origin id; with no project the record belongs to it alone. | |
| changedFacts | No | Ephemeral changed-key signals for string-form reopenWhen rules; not stored facts. Example: changedFacts:["budget"] fires reopenWhen:["budget"]. Object rules instead read values from facts overrides or stored facts. |
Output Schema
| Name | Required | Description |
|---|---|---|
| at | Yes | The instant maintenance ran against. |
| due | Yes | Decisions due for reconsideration after the run. |
| diagnostics | No | Conditions that could not be settled, or that rest on facts which disagree. |
| reviewSignals | Yes | Every persisted review signal after the run, open and acknowledged alike. |
| readProvenance | No | Original read bounds; reuse intersects these with currently valid authority. |
| agedDecisionIds | Yes | Compatibility alias of staleDecisionIds for older callers. |
| staleDecisionIds | Yes | Decisions moved to stale because they passed reviewAfter. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructive=true, idempotent=false, readOnly=false, and the description adds real context beyond them: lifecycle changes and signals persist 'even on repeats' (explaining the non-idempotent behavior), aging/expiry is irreversible here since it does not repair or restore, and grants widen audited reads only, never write authority. It does not spell out what happens to already-stale items on a re-run, which keeps it short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core action is front-loaded in the first sentence and every sentence carries distinct information about siblings, boundaries, or return contents. The phrasing is telegraphic ('Uses now or the clock', 'Grants widen audited reads, not writes'), which is dense but occasionally requires re-parsing.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex, destructive, multi-parameter maintenance tool with an output schema and full annotations, the description covers what mutates (decisions aged, facts expired), what it will not do (repair/restore), determinism via now, and the return contents (changed IDs, due items, stored signals including acknowledged ones). An agent has enough to call it correctly and to know the side effects.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents all seven parameters in depth. The description adds marginal value only, restating that the run uses 'now or the clock' and that grants widen reads, not writes; it contributes nothing new about facts, changedFacts, or origin/project scoping beyond what the schema states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence names three concrete operations (age decisions to stale, expire facts, evaluate reopen rules) with a specific verb+resource scope. It then explicitly contrasts itself with shadowgraph_review (evaluates without aging) and shadowgraph_validate (diagnoses integrity), so an agent can separate the three without reading schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description routes the agent explicitly: use shadowgraph_review to evaluate without aging, shadowgraph_validate for integrity diagnosis, and it states the negative boundary 'Maintenance does not repair or restore.' That is a clear when-to-use/when-not/alternative set, with only the operational cadence left implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shadowgraph_recallA
Rank scoped memory and records by lexical, vector, graph and temporal signals. shadowgraph_search requires every term; shadowgraph_retrieve adds neighbours; shadowgraph_context prepares a working set. Own-scope read saves nothing; an access key commits a revision and bounded audit. Returns scores and signal availability. No provider/vector means no semantic ranking. Omitted memory scope fields select null, not any user/run.
| Name | Required | Description | Default |
|---|---|---|---|
| asOf | No | ISO 8601 instant to select by valid time, returning what was true then rather than now. Also enables temporal ranking. | |
| limit | No | Maximum items to return, 1-1000; the default is 50 and completeness.limitSource reports which applied. Out of range is rejected, never silently clamped. | |
| query | No | Free text to rank against. An empty query still returns scope-matching records ranked by the remaining signals. | |
| scope | No | Scope selector. Omitted or partial fields mean explicit nulls, not "any": identity is the exact (project, userId, agentId, runId, memoryType, key) tuple, so a run-scoped memory never leaks into a user-only read. | |
| offset | No | Items to skip before this window. Ordering is total and deterministic, so paging cannot drop or duplicate an item. | |
| focalId | No | Entity id to measure graph distance from. Without it the graph signal reports available:false. | |
| grantId | No | Alias for accessId; conflicting identifiers are refused. | |
| project | No | Project or confirmed workspace binding; otherwise origin-only. No identity returns an empty scoped view. | |
| accessId | No | Grant ID, rechecked at use. Widens reads only, never write authority. Presenting an access key commits a revision and bounded operational audit: at most one aggregate per grant, surface, outcome and UTC day. Conflicts with a different grantId are refused. | |
| originId | No | Capture-origin id; with no project the record belongs to it alone. | |
| memoryType | No | Restrict memory candidates to this type. | |
| preferRecent | No | Enable temporal ranking against now. Ignored when asOf is supplied, which already selects a point in time. | |
| queryEmbedding | No | Caller-supplied query vector. Omit to use the configured provider; with neither, the semantic signal reports available:false and a reason. | |
| readProvenance | No | Original expansion bounds; cannot widen access. |
Output Schema
| Name | Required | Description |
|---|---|---|
| page | Yes | The window actually applied to the matching items. |
| items | Yes | The items in this window, in deterministic order. |
| completeness | Yes | Declares exactly what this response left out, so a truncated result can never look complete. |
| readProvenance | No | Original read bounds; reuse intersects these with currently valid authority. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false and idempotentHint=false, and the description explains why: an access key 'commits a revision and bounded audit,' while an own-scope read persists nothing. This adds valuable context beyond the annotations, including audit bounding language. It does not detail permission requirements or reversibility, but it meaningfully clarifies the side-effect profile.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose, then alternatives, then behavioral caveats, packing substantial information into five sentences for a 14-parameter tool. Most sentences earn their place, though phrases like 'Own-scope read saves nothing' are telegraphic and slightly opaque. Overall it is efficient and well-structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a complex 14-parameter tool with a full output schema, the description covers the major gotchas: null scope semantics, side effects from access keys, degraded ranking without a provider, and sibling alternatives. The output schema handles return-value details, so the description need not explain them. A few edge behaviors, such as paging or out-of-range limits, are delegated entirely to the schema, which is acceptable but leaves minor gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents parameters thoroughly; the baseline is 3. The description reinforces a few semantics, notably that omitted scope fields select explicit nulls rather than 'any' and that missing provider/vector disables semantic ranking, but these points largely restate schema content. It does not add syntax or format details beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Rank scoped memory and records by lexical, vector, graph and temporal signals.' It also explicitly distinguishes this tool from three siblings by naming their contrasting behaviors: search requires every term, retrieve adds neighbours, and context prepares a working set. An agent can identify exactly what this tool does and how it differs from adjacent options.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description names shadowgraph_search, shadowgraph_retrieve, and shadowgraph_context with their distinguishing behaviors, giving the agent a clear basis for choosing among them. It also notes a key usage constraint: 'No provider/vector means no semantic ranking.' However, it stops short of an explicit 'use this when' statement or exclusions, leaving the selection slightly implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shadowgraph_reconsiderA
Recheck decision conditions; explain all results, including uncertainty, and save review reminders. shadowgraph_review returns only due items; shadowgraph_ack_review closes a reminder. Saves deduplicated owned signals and commits a revision. Grants widen audited reads only. No choice, confidence or lifecycle changes. review_recommended: condition fired; manual_review: unresolved evidence; unchanged: complete evaluation, no trigger.
| Name | Required | Description | Default |
|---|---|---|---|
| facts | No | Temporary key/value overrides for object rules; unlisted keys use stored facts. Example: facts:{ready:true} tests {key:"ready",value:true}. This does not record a fact or fire a string rule; changedFacts supplies those changed-key signals. | |
| grantId | No | Alias for accessId; conflicting identifiers are refused. | |
| project | No | Project or confirmed workspace binding; otherwise origin-only. No identity returns an empty scoped view. | |
| accessId | No | Grant ID, rechecked at use. Widens reads only, never write authority. Presenting an access key commits a revision and bounded operational audit: at most one aggregate per grant, surface, outcome and UTC day. Conflicts with a different grantId are refused. | |
| originId | No | Capture-origin id; with no project the record belongs to it alone. | |
| decisionId | No | Limit the resolved project/origin to this decision; the ID does not supply scope. Unknown, out-of-scope, archived, abandoned or superseded decisions are rejected. Omit to explain all eligible decisions in scope. | |
| changedFacts | No | Ephemeral changed-key signals for string-form reopenWhen rules; not stored facts. Example: changedFacts:["budget"] fires reopenWhen:["budget"]. Object rules instead read values from facts overrides or stored facts. |
Output Schema
| Name | Required | Description |
|---|---|---|
| scope | Yes | What was reconsidered. |
| verdict | Yes | Aggregate over every decision in scope: a definite trigger outranks uncertainty, which outranks unchanged. |
| decisions | Yes | One entry per decision in scope, including decisions with nothing to report. |
| readProvenance | No | Original read bounds; reuse intersects these with currently valid authority. |
| evaluationCompleteness | Yes | partial when any decision in scope was partial. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say readOnly=false, idempotent=false, destructive=false; the description adds genuine side-effect disclosure beyond that: it saves deduplicated owned signals, commits a revision, grants 'widen audited reads only' (never write authority), and explicitly bounds the blast radius with 'No choice, confidence or lifecycle changes.' That tells the agent exactly what mutates and what does not.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and appropriately short, with no filler sentences. The style is extremely telegraphic, though: fragments like 'Grants widen audited reads only.' and 'No choice, confidence or lifecycle changes.' push compression close to ambiguity and cost some readability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 7-parameter mutating tool the definition covers what an agent needs: purpose, sibling routing, bounded side effects, and the returned outcome labels. An output schema exists, so return-value structure need not be explained, and the schema itself documents all parameters.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already carries the parameter documentation, including the facts-vs-changedFacts distinction and grant/alias conflict rules. The description adds meaning for outcome states (review_recommended, manual_review, unchanged) rather than for parameters, which is valuable but belongs to results, not inputs. Baseline 3 is correct here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Recheck decision conditions'), then adds the scope of what it produces: an explanation of all results including uncertainty, plus persisted review reminders. It explicitly contrasts with two siblings ('shadowgraph_review returns only due items; shadowgraph_ack_review closes a reminder'), so an agent can route between the three without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The sibling contrasts give real routing guidance: use shadowgraph_review for due-only items, shadowgraph_ack_review to close a reminder, implying this tool for full re-evaluation of conditions. The decisionId note ('Omit to explain all eligible decisions in scope') also frames the broad-vs-narrow choice. It never states an explicit 'do not use this when...' exclusion, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shadowgraph_record_attemptA
Record one attempt with its result; returns the stored attempt. Use shadowgraph_record_decision for a choice; shadowgraph_record_outcome updates an existing decision and its confidence. An attempt is a separate record. Appends an attempt and journal entry and commits a revision; idempotencyKey prevents duplicate retries. resultClass overrides wording-based failure classification.
| Name | Required | Description | Default |
|---|---|---|---|
| actor | No | Who performed this write, such as an agent or person name. Stored for audit; never used to grant trust. | |
| client | No | Which client software performed this write, such as the host application name. | |
| reason | No | Why it turned out that way. Searchable content. | |
| result | Yes | What happened. Required, non-empty, and searchable content. With no resultClass, wording such as failed, error, or regression is what places the attempt in shadowgraph_context failedAttempts; a captured attempt's wording is never read. | |
| project | No | Owning project; required unless originId is set, else the write is refused. | |
| originId | No | Capture-origin id; with no project the record belongs to it alone. | |
| solution | Yes | What was tried. Required, non-empty, and searchable content. | |
| sessionId | No | Caller-owned identifier that groups related writes in the audit trail. | |
| environment | No | Where it was tried, such as a runtime, OS, or version. Searchable content, so a later attempt can be matched to the same environment. | |
| resultClass | No | Classify the result instead of leaving it to the wording heuristic. Set it when the result text does not say failed, error, or regression, or when it does but the attempt did not fail. | |
| sourceClass | No | Claimed origin, never proof: agent_claimed (the default), tool_observed, human_confirmed, or production_verified. It weights confidence only. An unrecognised label downgrades to agent_claimed, kept verbatim in sourceRaw. | |
| idempotencyKey | No | Retry identity within the project or origin and operation (also scope/type/key for memory). Reuse it to recover the original canonical ID; this key is never an entity ID. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | Stable entity identifier. |
| kind | Yes | Entity kind: decision, attempt, memory, fact, relation, review, or alternative. |
| actor | No | Who performed the write. |
| client | No | Which client performed the write. |
| reason | No | Why it turned out that way, verbatim as recorded. |
| result | No | What happened. |
| project | No | Project namespace; null for an unattributed record or one imported from before projects. |
| solution | No | What was tried. |
| createdAt | No | ISO 8601 creation time. |
| relatedTo | No | Identifiers of related entities. |
| sessionId | No | Session identifier recorded with the write. |
| sourceRaw | No | The original origin label when it differed from sourceClass. Audit only; never evidence. |
| updatedAt | No | ISO 8601 time of the last change. |
| causalClaim | No | The cause, attributed apart from the attempt: state recorded (the reason, agent_claimed), unknown, not_recorded, or legacy_freetext (a reason stored before causes were, never classed or evidenced). |
| environment | No | Where it was tried. |
| resultClass | No | Declared or observed: failed, succeeded, or inconclusive. If absent: not captured (no captureRef or outcomeEvidence), the wording heuristic classifies; captured, the outcome is undetermined. |
| sourceClass | No | Claimed origin class recorded with the write. A claim, never proof. |
| reusableWhen | No | Conditions recorded for reusing the attempt. All must hold, and none may be unresolved. |
| schemaVersion | No | Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations by disclosing side effects ('Appends an attempt and journal entry and commits a revision'), retry semantics via idempotencyKey, and that resultClass overrides the wording-based failure classifier that feeds shadowgraph_context failedAttempts. It does not address permissions, ordering, or what happens if the commit fails, and there is mild tension between idempotentHint=false and the claim that idempotencyKey prevents duplicate retries (the key is opt-in, so not a true contradiction).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four front-loaded sentences: purpose+return, sibling routing, side effects, then parameter notes. Every sentence carries information, though the clipped phrasing ('An attempt is a separate record.') reads more telegraphic than explanatory.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 12 parameters, an output schema, full annotation coverage and 100% schema description coverage, the description supplies what structured fields cannot: sibling routing and commit side effects. Remaining gaps are minor given the rich schema, though the interaction between a non-idempotent annotation and an optional idempotency key could have been spelled out.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100%, so the baseline is 3; the description still adds value by explaining that idempotencyKey guards duplicate retries and that resultClass bypasses the wording heuristic. It does not touch the required project/originId rule or sourceClass weighting, but those are documented in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Record one attempt with its result'), states the return ('returns the stored attempt'), and explicitly distinguishes itself from shadowgraph_record_decision and shadowgraph_record_outcome. An agent can pick this tool without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names two alternative siblings and the condition that selects each ('for a choice' → record_decision; 'updates an existing decision and its confidence' → record_outcome), plus the clarifying rule 'An attempt is a separate record.' The routing decision is fully resolved in the description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shadowgraph_record_decisionA
Record one decision: chosen option, assumptions, evidence, and rejected alternatives with reopenWhen rules. Use shadowgraph_record_attempt for something tried, shadowgraph_record_fact for an observation, shadowgraph_remember for a note. Appends a decision and a journal entry; without idempotencyKey each call adds another and commits a revision.
| Name | Required | Description | Default |
|---|---|---|---|
| goal | No | What the decision is meant to achieve. Searchable content. | |
| actor | No | Who performed this write, such as an agent or person name. Stored for audit; never used to grant trust. | |
| title | Yes | Short name of the decision. Required, non-empty, and searchable content. | |
| chosen | Yes | The option actually chosen. Required, non-empty, and searchable content. | |
| client | No | Which client software performed this write, such as the host application name. | |
| project | No | Owning project; required unless originId is set, else the write is refused. | |
| evidence | No | Supporting evidence. Counted as declared evidence in the confidence basis, but never re-checked. | |
| originId | No | Capture-origin id; with no project the record belongs to it alone. | |
| sessionId | No | Caller-owned identifier that groups related writes in the audit trail. | |
| confidence | No | Starting confidence, 0-1. Defaults to 0.5. Later outcomes and evidence move it from this baseline; it is a degree of belief, never a verification status. | |
| assumptions | No | What the decision takes for granted. Record each as a fact too if it should be able to reopen the decision. | |
| sourceClass | No | Claimed origin, never proof: agent_claimed (the default), tool_observed, human_confirmed, or production_verified. It weights confidence only. An unrecognised label downgrades to agent_claimed, kept verbatim in sourceRaw. | |
| alternatives | No | Options considered and rejected. Alternatives belong to the decision and have no separate write API; they are what shadowgraph_review reconsiders. | |
| idempotencyKey | No | Retry identity within the project or origin and operation (also scope/type/key for memory). Reuse it to recover the original canonical ID; this key is never an entity ID. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | Stable entity identifier. |
| goal | No | What the decision was trying to achieve. |
| kind | Yes | Entity kind: decision, attempt, memory, fact, relation, review, or alternative. |
| actor | No | Who performed the write. |
| title | No | Short name of the decision. |
| chosen | No | The option that was chosen. |
| client | No | Which client performed the write. |
| status | No | Lifecycle state. Legacy records may carry a value this build does not recognise; shadowgraph_validate reports those. |
| outcome | No | The recorded outcome, or null until one is recorded. |
| project | No | Project namespace; null for an unattributed record or one imported from before projects. |
| evidence | No | Normalised evidence entries: source, type, sourceClass, confidence, observedAt, detail. |
| createdAt | No | ISO 8601 creation time. |
| migration | No | Present only on migrated records; records the legacy value a field was mapped from. |
| sessionId | No | Session identifier recorded with the write. |
| sourceRaw | No | The original origin label when it differed from sourceClass. Audit only; never evidence. |
| updatedAt | No | ISO 8601 time of the last change. |
| confidence | No | Auditable confidence: initial, current (0-1), policy, a history entry per move, and a basis summarising the contributions it was folded from. Legacy records may lack basis. |
| supersedes | No | Identifiers of decisions this one replaced. |
| assumptions | No | Assumptions the decision rests on. Searchable content. |
| reviewAfter | No | ISO 8601 instant after which shadowgraph_maintain marks this decision stale. |
| sourceClass | No | Claimed origin class recorded with the write. A claim, never proof. |
| alternatives | No | Rejected alternatives, each with id, label, reasonRejected, status, and the reopenWhen rules that make it reconsiderable. |
| supersededBy | No | Identifier of the decision that replaced this one. |
| schemaVersion | No | Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded. |
| failedAttempts | No | Attempt identifiers or notes attached to this decision. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes beyond the annotations by disclosing what a call actually produces — a decision plus a journal entry and a committed revision — and by warning that without idempotencyKey each call creates another record. That is real behavioral value not derivable from idempotentHint=false alone. It does not discuss permissions, refusals on missing project/originId, or error modes, which the schema covers but the description does not surface.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences: what it records, where to go instead, and what happens on the write. Front-loaded with the core action and no filler; the routing sentence is the exact length needed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need no explanation; the description still contributes the creation/duplication semantics and sibling routing an agent needs to call this correctly. Nothing material is missing for a 14-parameter, 2-required record tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already carries parameter meaning and the baseline of 3 applies. The description's mention of chosen/assumptions/evidence/alternatives/reopenWhen mirrors fields rather than adding format or constraint detail beyond them.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — 'Record one decision' — and immediately enumerates what a decision contains (chosen option, assumptions, evidence, rejected alternatives with reopenWhen rules), which separates it from a generic write. It also names three sibling tools it is not, so an agent can disambiguate without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent: record_attempt for something tried, record_fact for an observation, remember for a note. The condition selecting this tool versus those alternatives is stated unambiguously.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shadowgraph_record_factADestructive
Record one observed fact as a project and key, with a claimed provenance class and optional validity window. Use for the fact keys reopenWhen rules name; shadowgraph_remember stores durable memory that is not an observation. Supersedes the previous active fact, keeping it as history. No input can make a fact verified. Each call commits a revision.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | Fact name, unique per project among active facts. Required and non-empty. Use the same key that a decision’s reopenWhen rules refer to. | |
| actor | No | Who performed this write, such as an agent or person name. Stored for audit; never used to grant trust. | |
| value | No | Any lossless JSON value: string, finite number, boolean, null, array, or object. | |
| client | No | Which client software performed this write, such as the host application name. | |
| source | No | Legacy alias for sourceClass. An unknown label downgrades to agent_claimed with the raw label kept in sourceRaw. | |
| project | No | Owning project; required unless originId is set, else the write is refused. | |
| originId | No | Capture-origin id; with no project the record belongs to it alone. | |
| expiresAt | No | ISO 8601 instant after which shadowgraph_maintain expires this fact. Combined with validTo, the earlier boundary wins. | |
| sessionId | No | Caller-owned identifier that groups related writes in the audit trail. | |
| confidence | No | How much the caller trusts this observation, 0-1. Defaults to 0.5. It does not verify anything. | |
| sourceClass | No | Claimed origin, never proof: agent_claimed (the default), tool_observed, human_confirmed, or production_verified. It weights confidence only. An unrecognised label downgrades to agent_claimed, kept verbatim in sourceRaw. | |
| idempotencyKey | No | Retry identity within the project or origin and operation (also scope/type/key for memory). Reuse it to recover the original canonical ID; this key is never an entity ID. | |
| verificationStatus | No | Only "contradicted" may be set by a caller, because it lowers trust. "verified" and "expired" are rejected: verification is not self-assertable and expiry is owned by shadowgraph_maintain. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | No | Stable entity identifier. |
| key | Yes | Fact name, unique per project among active facts. |
| kind | No | Entity kind: decision, attempt, memory, fact, relation, review, or alternative. |
| actor | No | Who performed the write. |
| value | No | The observed value, any lossless JSON value. |
| client | No | Which client performed the write. |
| source | No | Legacy alias of sourceClass, retained for compatibility. |
| status | No | active, superseded, or expired. |
| project | No | Project namespace; null for an unattributed record or one imported from before projects. |
| temporal | No | Bi-temporal window: validFrom, validTo, recordedAt, invalidatedAt. |
| createdAt | No | ISO 8601 creation time. |
| expiresAt | No | Caller-declared expiry instant, or null. |
| sessionId | No | Session identifier recorded with the write. |
| sourceRaw | No | The original origin label when it differed from sourceClass. Audit only; never evidence. |
| updatedAt | No | ISO 8601 time of the last change. |
| confidence | No | Caller-declared confidence in the observation, 0-1. |
| observedAt | No | ISO 8601 time the fact was observed. |
| sourceClass | No | Claimed origin class recorded with the write. A claim, never proof. |
| verification | No | Present only on a signed verification: the attestation this build checked. |
| schemaVersion | No | Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded. |
| validityPolicy | No | Declared expiry inputs and the effective expiration boundary derived from them. |
| verificationStatus | No | unverified, contradicted, expired, or verified. Only the separately configured signed-evidence verifier can produce verified. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=false; the description goes beyond them by explaining that the prior active fact is superseded but retained as history, that each call commits a revision, and that no input can make a fact verified. What it leaves implicit is how retries interact with revision churn, which is left entirely to the schema's idempotencyKey field.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Five short sentences, front-loaded with what the tool does, followed by routing, mutation semantics, and the trust invariant. Every sentence carries distinct information and none restates the title or annotations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 13-parameter mutation tool with full schema coverage, complete annotations, and an output schema, the description supplies the conceptual model an agent needs: identity, supersession with history, and the non-assertable verification rule. The remaining gap is guidance on the sibling supersede tool, which matters given the destructive annotation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all 13 parameters including the enums and the verified/expired rejection rule are already documented in structured data. The description only echoes the top-level concepts (project, key, provenance class, validity window) and adds no syntax, defaults, or interaction details beyond the schema, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Record one observed fact") plus the identity model (project + key), provenance class, and validity window. It also explicitly distinguishes itself from shadowgraph_remember, so an agent can route between the two without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete when-to-use rule ("Use for the fact keys reopenWhen rules name") and names the alternative that handles non-observational data. It does not address the overlap with the sibling shadowgraph_supersede, which also deals with replacement, so an agent gets no explicit guidance on when to prefer that tool instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shadowgraph_record_outcomeADestructive
Record how a decision turned out and move its confidence by an evidence-weighted amount. shadowgraph_confidence_evidence records evidence short of an outcome, shadowgraph_update_status changes the lifecycle state. One outcome contribution per decision: re-recording replaces it, updates the decision timestamp and commits a revision; it does not change lifecycle status.
| Name | Required | Description | Default |
|---|---|---|---|
| outcome | Yes | The outcome to record. | |
| project | No | Owning project; required unless originId is set, else the write is refused. | |
| originId | No | Capture-origin id; with no project the record belongs to it alone. | |
| decisionId | Yes | Identifier of an existing decision, as returned by shadowgraph_record_decision, shadowgraph_search, or shadowgraph_retrieve. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | Stable entity identifier. |
| goal | No | What the decision was trying to achieve. |
| kind | Yes | Entity kind: decision, attempt, memory, fact, relation, review, or alternative. |
| actor | No | Who performed the write. |
| title | No | Short name of the decision. |
| chosen | No | The option that was chosen. |
| client | No | Which client performed the write. |
| status | No | Lifecycle state. Legacy records may carry a value this build does not recognise; shadowgraph_validate reports those. |
| outcome | No | The recorded outcome, or null until one is recorded. |
| project | No | Project namespace; null for an unattributed record or one imported from before projects. |
| evidence | No | Normalised evidence entries: source, type, sourceClass, confidence, observedAt, detail. |
| createdAt | No | ISO 8601 creation time. |
| migration | No | Present only on migrated records; records the legacy value a field was mapped from. |
| sessionId | No | Session identifier recorded with the write. |
| sourceRaw | No | The original origin label when it differed from sourceClass. Audit only; never evidence. |
| updatedAt | No | ISO 8601 time of the last change. |
| confidence | No | Auditable confidence: initial, current (0-1), policy, a history entry per move, and a basis summarising the contributions it was folded from. Legacy records may lack basis. |
| supersedes | No | Identifiers of decisions this one replaced. |
| assumptions | No | Assumptions the decision rests on. Searchable content. |
| reviewAfter | No | ISO 8601 instant after which shadowgraph_maintain marks this decision stale. |
| sourceClass | No | Claimed origin class recorded with the write. A claim, never proof. |
| alternatives | No | Rejected alternatives, each with id, label, reasonRejected, status, and the reopenWhen rules that make it reconsiderable. |
| supersededBy | No | Identifier of the decision that replaced this one. |
| schemaVersion | No | Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded. |
| failedAttempts | No | Attempt identifiers or notes attached to this decision. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=false, and the description is consistent with both: re-recording replaces the prior contribution, bumps the decision timestamp, and commits a revision, while leaving lifecycle status untouched. This is useful context about what is overwritten, but the description does not address authorization or project/origin refusal behavior beyond repeating the schema's own note.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the verb and effect, then routing to alternatives, then mutation semantics. No filler and no repetition of annotation fields.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
A mutation tool with a nested parameter object and 19 siblings, yet the description covers what it writes, what it replaces, what it does not change (lifecycle), and how it differs from the two closest tools. Since an output schema exists, no return-value explanation is needed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description earns extra credit by framing the `outcome` object as a single replaceable contribution that shifts confidence by an evidence-weighted amount. It adds no independent detail for `decisionId`, `project`, or `originId` beyond what the schema already documents.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Record how a decision turned out") plus the concrete effect ("move its confidence by an evidence-weighted amount"), and explicitly separates the tool from shadowgraph_confidence_evidence and shadowgraph_update_status. An agent can identify this tool from the sibling list without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names the two nearest alternatives and the condition that selects each: confidence_evidence for evidence short of an outcome, update_status for lifecycle changes. It also states the cardinality rule ("One outcome contribution per decision: re-recording replaces it"), which tells the agent what happens on a repeat call.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shadowgraph_rememberADestructive
Add or reconcile one scoped memory, or apply an ADD/UPDATE/DELETE/NOOP plan, by identity tuple. Use shadowgraph_record_decision for a choice, shadowgraph_record_fact for an observation, shadowgraph_recall to read memory back. Identical content is a NOOP, new content supersedes and keeps history, DELETE invalidates; every call commits a revision.
| Name | Required | Description | Default |
|---|---|---|---|
| key | No | Stable caller-chosen name within this scope and type, such as hotel-style. Reusing it reconciles that memory rather than adding a second one. | |
| tags | No | Free-form labels stored with the memory. Part of the compared content, so changing them produces a new version. | |
| text | No | The memory content itself. Stored verbatim, searched as content, and compared to decide ADD, UPDATE, or NOOP. | |
| actor | No | Who performed this write, such as an agent or person name. Stored for audit; never used to grant trust. | |
| scope | No | Scope selector. Omitted or partial fields mean explicit nulls, not "any": identity is the exact (project, userId, agentId, runId, memoryType, key) tuple, so a run-scoped memory never leaks into a user-only read. | |
| client | No | Which client software performed this write, such as the host application name. | |
| project | No | Owning project; required unless originId is set, else the write is refused. | |
| validTo | No | ISO 8601 instant after which it stops being true, or null for open-ended. Must be later than validFrom. | |
| metadata | No | Caller-owned JSON object kept with the memory. Part of the compared content, so changing it produces a new version. | |
| originId | No | Capture-origin id; with no project the record belongs to it alone. | |
| embedding | No | Caller-supplied vector for this text. Omit to use the configured embedding provider; with no provider the record is still stored and recall reports semantic.available=false instead of renaming lexical overlap as semantic. | |
| sessionId | No | Caller-owned identifier that groups related writes in the audit trail. | |
| validFrom | No | ISO 8601 instant from which this memory is true in the modeled world. Defaults to the write time. Writes for one identity must arrive in non-decreasing validFrom order. | |
| memoryType | No | Which kind of memory this is, and part of its identity. preference and profile are durable user facts, goal a desired state, instruction an operating constraint, procedure reusable steps, episode a recallable event, note general knowledge. | |
| operations | No | A batch plan. Supply this instead of a single memory, typically from an extraction step. Every operation is validated before the first one is applied, so a malformed late operation cannot leave a half-applied batch. | |
| sourceClass | No | Claimed origin, never proof: agent_claimed (the default), tool_observed, human_confirmed, or production_verified. It weights confidence only. An unrecognised label downgrades to agent_claimed, kept verbatim in sourceRaw. | |
| idempotencyKey | No | Retry identity within the project or origin and operation (also scope/type/key for memory). Reuse it to recover the original canonical ID; this key is never an entity ID. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, readOnlyHint=false and idempotentHint=false; the description adds the important nuance that 'destructive' here means invalidation with history retained and that every call commits a revision. That reframes the risk profile in a way annotations alone cannot. It does not cover auth/permission requirements or failure modes, keeping it a 4.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with purpose then alternatives then semantics, with zero filler. The final sentence is a dense run-on of three behaviors that could be split for readability, but every clause carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 17-parameter, nested, mutation tool with an output schema, the description supplies the essential mental model (identity tuple, reconciliation outcomes, revision commit) and sibling routing. Batch atomicity and ID-rejection rules live in the schema, which is legitimate, but the description does not mention the single-vs-operations mutual exclusivity that an agent must satisfy.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3; the description adds the governing concept that memory is keyed by an exact scoped identity tuple and that identical content is a NOOP, which explains why no id is accepted. That conceptual framing helps the agent choose between single-memory and operations form, though individual parameter meanings still come from the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb-and-resource statement ('Add or reconcile one scoped memory') and covers the batch form ('apply an ADD/UPDATE/DELETE/NOOP plan, by identity tuple'). It explicitly differentiates itself from siblings by naming shadowgraph_record_decision, shadowgraph_record_fact and shadowgraph_recall with their respective purposes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives direct routing rules: use record_decision for a choice, record_fact for an observation, recall to read back. The reconciliation semantics (identical content = NOOP, new content supersedes, DELETE invalidates) tell the agent when an ADD collapses into a no-op or an update. The only minor gap is no explicit guidance versus shadowgraph_supersede or shadowgraph_maintain.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shadowgraph_retrieveA
Find content matches and their one-hop graph neighbours. shadowgraph_search returns matches only; shadowgraph_recall ranks relevance; shadowgraph_context prepares a working set. Own-scope read saves nothing; an access key commits a revision and bounded audit. Returns paginated records with match/relationship reasons. Every term must match a seed; neighbours need not match. Both stay in scope.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | Restrict results to decisions or to attempts. A structured filter, never a content match. | |
| limit | No | Maximum items to return, 1-1000; the default is 50 and completeness.limitSource reports which applied. Out of range is rejected, never silently clamped. | |
| query | No | Whitespace-separated terms matched against the declared content fields (title, goal, chosen, assumption, evidence, alternative, attempt solution, attempt result, attempt reason, environment), exactly as in shadowgraph_search. Omit to retrieve by filters alone. | |
| offset | No | Items to skip before this window. Ordering is total and deterministic, so paging cannot drop or duplicate an item. | |
| status | No | Return only decisions in this lifecycle state. A structured filter, so matching it is never counted as a content match. | |
| grantId | No | Alias for accessId; conflicting identifiers are refused. | |
| project | No | Project or confirmed workspace binding; otherwise origin-only. No identity returns an empty scoped view. | |
| accessId | No | Grant ID, rechecked at use. Widens reads only, never write authority. Presenting an access key commits a revision and bounded operational audit: at most one aggregate per grant, surface, outcome and UTC day. Conflicts with a different grantId are refused. | |
| originId | No | Capture-origin id; with no project the record belongs to it alone. | |
| minConfidence | No | Return only decisions whose current confidence is at least this value, 0-1. A structured filter, never a content match. | |
| readProvenance | No | Original expansion bounds; cannot widen access. |
Output Schema
| Name | Required | Description |
|---|---|---|
| page | Yes | The window actually applied to the matching items. |
| items | Yes | The items in this window, in deterministic order. |
| completeness | Yes | Declares exactly what this response left out, so a truncated result can never look complete. |
| readProvenance | No | Original read bounds; reuse intersects these with currently valid authority. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial non-obvious behavior beyond annotations: an access key commits a revision and a bounded audit (at most one aggregate per grant/surface/outcome/UTC day), which explains the readOnlyHint=false and idempotentHint=false flags rather than contradicting them. Also discloses total deterministic ordering, rejection-not-clamping on limit, and that results carry match/relationship reasons.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose and alternatives, with no filler sentences. Some clauses are telegraphic to the point of opacity ('Own-scope read saves nothing'), which costs a bit of first-read clarity but keeps the payload dense.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 11-parameter, nested-object, output-schema-backed read tool, the description covers matching semantics, scope, paging behavior, audit side effects, and result shape — everything an agent needs before calling, without restating the return schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3; the description nonetheless adds semantics the schema does not — 'every term must match a seed; neighbours need not match' clarifies query matching scope, and 'both stay in scope' constrains the result set. Structured filters (kind, status, minConfidence) being 'never a content match' is reinforced in the description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — 'Find content matches and their one-hop graph neighbours' — and immediately contrasts with three named siblings (shadowgraph_search, shadowgraph_recall, shadowgraph_context). An agent can distinguish this from every sibling without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly positions the tool against alternatives: search returns matches only, recall ranks relevance, context prepares a working set — implying this is the one that adds neighbour expansion. Lacks an explicit 'do not use when' or a stated prerequisite, but the routing information is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shadowgraph_reviewA
Recheck decision conditions and save review reminders; return decisions to revisit as { items, completeness }, with signal IDs. shadowgraph_review_signals reads saved reminders; shadowgraph_reconsider explains all verdicts; shadowgraph_review_context adds context; shadowgraph_ack_review closes one. Persists deduplicated owned signals; every call commits a revision. Grants widen audited reads only. No choice or lifecycle changes.
| Name | Required | Description | Default |
|---|---|---|---|
| facts | No | Temporary key/value overrides for object rules; unlisted keys use stored facts. Example: facts:{ready:true} tests {key:"ready",value:true}. This does not record a fact or fire a string rule; changedFacts supplies those changed-key signals. | |
| grantId | No | Alias for accessId; conflicting identifiers are refused. | |
| project | No | Project or confirmed workspace binding; otherwise origin-only. No identity returns an empty scoped view. | |
| accessId | No | Grant ID, rechecked at use. Widens reads only, never write authority. Presenting an access key commits a revision and bounded operational audit: at most one aggregate per grant, surface, outcome and UTC day. Conflicts with a different grantId are refused. | |
| originId | No | Capture-origin id; with no project the record belongs to it alone. | |
| changedFacts | No | Ephemeral changed-key signals for string-form reopenWhen rules; not stored facts. Example: changedFacts:["budget"] fires reopenWhen:["budget"]. Object rules instead read values from facts overrides or stored facts. |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | Yes | All known matching items inside this boundary. |
| completeness | Yes | Declares exactly what this response left out, so a truncated result can never look complete. |
| readProvenance | No | Original read bounds; reuse intersects these with currently valid authority. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag readOnlyHint=false and idempotentHint=false, and the description adds real signal beyond that: deduplicated persistence of owned signals, a revision committed on every call, bounded per-grant/surface/outcome/day audit aggregation, and the scope limit "no choice or lifecycle changes." It does not explain failure modes or what a revision means concretely, so it is strong but not exhaustive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and return shape are front-loaded, followed by sibling routing and then behavioral constraints, so the important content arrives first. The telegraphic semicolon-heavy phrasing is dense but nearly every clause carries distinct information, with only minor redundancy about grants duplicating the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the description still sketches them. For a 6-parameter, non-idempotent mutation tool with nested objects, it covers persistence, dedup, auditing, scope limits and sibling routing, leaving only edge-case behavior (what happens on refused identifiers or empty scoped views) to the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all six parameters including the facts/changedFacts distinction and the grantId/accessId alias conflict. The description only loosely echoes this ("Grants widen audited reads only", "with signal IDs"), adding little syntax or meaning the schema doesn't already carry, which matches the baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb pair ("Recheck decision conditions and save review reminders") plus the exact return shape ({ items, completeness } with signal IDs). The four sibling comparisons pin down what this tool is not, so an agent can distinguish it from review_signals, reconsider, review_context and ack_review without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent among four adjacent siblings by naming what each one does (reads saved reminders, explains all verdicts, adds context, closes one), which effectively tells the caller when to pick an alternative. It stops short of stating when-not to use this tool or any prerequisite ordering, so it lands just below the top mark.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shadowgraph_review_contextA
Recheck conditions, save review reminders and load the project working set. shadowgraph_context does not save reminders; shadowgraph_review also persists them, returning due decisions only; shadowgraph_ack_review acknowledges one. Deduplicates owned signals; every call commits a revision. Grants widen audited reads only. No choice or lifecycle changes.
| Name | Required | Description | Default |
|---|---|---|---|
| facts | No | Temporary key/value overrides for object rules; unlisted keys use stored facts. Example: facts:{ready:true} tests {key:"ready",value:true}. This does not record a fact or fire a string rule; changedFacts supplies those changed-key signals. | |
| limit | No | Maximum items per collection, 1-1000, applied to each collection independently. Omit for the default of 50. | |
| grantId | No | Alias for accessId; conflicting identifiers are refused. | |
| project | No | Project or confirmed workspace binding; otherwise origin-only. No identity returns an empty scoped view. | |
| accessId | No | Grant ID, rechecked at use. Widens reads only, never write authority. Presenting an access key commits a revision and bounded operational audit: at most one aggregate per grant, surface, outcome and UTC day. Conflicts with a different grantId are refused. | |
| originId | No | Capture-origin id; with no project the record belongs to it alone. | |
| changedFacts | No | Ephemeral changed-key signals for string-form reopenWhen rules; not stored facts. Example: changedFacts:["budget"] fires reopenWhen:["budget"]. Object rules instead read values from facts overrides or stored facts. |
Output Schema
| Name | Required | Description |
|---|---|---|
| project | Yes | The resolved project, or null when unresolved. |
| openReviews | Yes | Decisions currently due for reconsideration. |
| completeness | Yes | Per-collection completeness. context returns several named collections, so one page object cannot describe it. |
| readProvenance | No | Original read bounds; reuse intersects these with currently valid authority. |
| activeDecisions | Yes | Decisions in a current, actionable state: proposed, planned, in_progress, executed, validated, or reconsidered. |
| reusableAttempts | No | Attempts whose reusableWhen conditions all hold now. Worth reconsidering, not authorised to retry. |
| staleAssumptions | Yes | Facts that are no longer active, such as superseded or expired ones, which earlier decisions may still rest on. |
| suggestedQuestions | Yes | Questions for the low-confidence decisions in this project. |
| conditionDiagnostics | No | Conditions that could not be settled, or that rest on facts which disagree. Neither a breach nor a confirmed-safe decision. |
| failedAttemptsToAvoid | Yes | Attempts that failed: resultClass failed or, with none and not captured, a result mentioning failure, regression, or error. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare non-read-only, non-idempotent, non-destructive; the description goes further with 'every call commits a revision', 'grants widen audited reads only', '(grants) never write authority', and bounded per-day audit aggregation — real side-effect disclosure an agent needs before calling. It stops short of saying what the commit/revision means downstream, which keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in the first sentence and the following clauses are dense but each carries distinct information (sibling routing, dedup, revision commit, grant scope, lifecycle exclusions). The semicolon-chained, near-telegraphic style costs some readability, but there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 7-parameter, nested-object, state-committing tool with an output schema, the description covers purpose, sibling routing, mutation side effects, and grant scope — the pieces the schema cannot express. What remains thin is the meaning of the committed revision and the reminder lifecycle, but the output schema can carry return details.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the schema already explains facts, changedFacts, grantId/accessId aliasing, and limit semantics in more detail than the description. The description adds only the grant-scope constraint (reads widen, never write authority), so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening clause states concrete actions (recheck conditions, save review reminders, load the project working set) and explicitly separates this tool from three named siblings. The verb+resource is clear enough to distinguish it in a 20-tool family, though 'load the project working set' stays jargon-level vague compared to the rest.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It names shadowgraph_context (does not save reminders), shadowgraph_review (also persists reminders but returns due decisions only), and shadowgraph_ack_review (acknowledges one), giving an agent concrete selection criteria. It lacks an explicit 'do not use when' statement, but the routing guidance is unusually specific for this family.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shadowgraph_review_signalsA
List saved review reminders without rechecking conditions or creating signals. shadowgraph_review rechecks conditions and creates reminders; shadowgraph_ack_review acknowledges one. Without an access key, this read saves nothing. An access key commits a revision and bounded audit. Returns { items, completeness }, unpaginated.
| Name | Required | Description | Default |
|---|---|---|---|
| status | No | Filter by state. Omit to return both. | |
| grantId | No | Alias for accessId; conflicting identifiers are refused. | |
| project | No | Project or confirmed workspace binding; otherwise origin-only. No identity returns an empty scoped view. | |
| accessId | No | Grant ID, rechecked at use. Widens reads only, never write authority. Presenting an access key commits a revision and bounded operational audit: at most one aggregate per grant, surface, outcome and UTC day. Conflicts with a different grantId are refused. | |
| originId | No | Capture-origin id; with no project the record belongs to it alone. |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | Yes | All known matching items inside this boundary. |
| completeness | Yes | Declares exactly what this response left out, so a truncated result can never look complete. |
| readProvenance | No | Original read bounds; reuse intersects these with currently valid authority. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description explains precisely why readOnlyHint=false despite the word 'List': presenting an accessId 'commits a revision and bounded operational audit', and it quantifies the bound ('at most one aggregate per grant, surface, outcome and UTC day'). It also discloses that without a key nothing is persisted and that results are unpaginated — traits that go well beyond the annotation flags and are not derivable from them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short clauses, front-loaded with the verb+resource and the sibling disambiguation before the caveats; almost no filler. The telegraphic phrasing ('this read saves nothing') is dense but does cost a little parseability, keeping it below 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists, so the brief return-shape note is a bonus rather than a necessity, and the non-idempotent, non-read-only profile is fully explained. Remaining gaps are conceptual rather than operational: neither 'signals' nor what 'completeness' conveys is defined, and empty scoped views are only hinted at via the 'saves nothing' clause.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents status enum filtering, grantId aliasing, project/originId scoping, and the accessId widening rule. The description rehearses the access-key side effect in prose but adds no new parameter-level semantics such as precedence between project and originId or how completeness relates to filters. Baseline 3 applies when the schema carries the parameter burden.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — 'List saved review reminders' — and immediately scopes it against the two nearest siblings: shadowgraph_review 'rechecks conditions and creates reminders' and shadowgraph_ack_review 'acknowledges one'. An agent can identify this tool as the non-mutating listing surface without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names both relevant alternatives and the exact behaviors that distinguish them (rechecking/creating vs. acknowledging), which routes the agent correctly. It also states the practical precondition ('Without an access key, this read saves nothing'), though it never says a plain 'use this when you only need to view saved reminders' or any exclusion beyond the sibling comparison.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shadowgraph_searchA
Find records containing every query term for a precise content lookup. shadowgraph_retrieve adds one-hop neighbours; shadowgraph_recall ranks matches; shadowgraph_context prepares a working set. Own-scope read saves nothing; an access key commits a revision and bounded audit. Returns paginated matches and completeness. "redis timeout" requires both terms, not an exact phrase; empty query applies filters only.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | Restrict results to decisions or to attempts. A structured filter, never a content match. | |
| limit | No | Maximum items to return, 1-1000; the default is 50 and completeness.limitSource reports which applied. Out of range is rejected, never silently clamped. | |
| query | No | Whitespace-separated terms, matched case-insensitively as substrings against the declared content fields (title, goal, chosen, assumption, evidence, alternative, attempt solution, attempt result, attempt reason, environment). Every term must match something, so more terms narrow the result. Omit to filter without searching. | |
| offset | No | Items to skip before this window. Ordering is total and deterministic, so paging cannot drop or duplicate an item. | |
| status | No | Return only decisions in this lifecycle state. A structured filter, so matching it is never counted as a content match. | |
| grantId | No | Alias for accessId; conflicting identifiers are refused. | |
| project | No | Project or confirmed workspace binding; otherwise origin-only. No identity returns an empty scoped view. | |
| accessId | No | Grant ID, rechecked at use. Widens reads only, never write authority. Presenting an access key commits a revision and bounded operational audit: at most one aggregate per grant, surface, outcome and UTC day. Conflicts with a different grantId are refused. | |
| originId | No | Capture-origin id; with no project the record belongs to it alone. | |
| sourceClass | No | Return only records carrying this claimed origin class. A structured filter, never a content match. | |
| minConfidence | No | Return only decisions whose current confidence is at least this value, 0-1. A structured filter, never a content match. |
Output Schema
| Name | Required | Description |
|---|---|---|
| page | Yes | The window actually applied to the matching items. |
| items | Yes | The items in this window, in deterministic order. |
| completeness | Yes | Declares exactly what this response left out, so a truncated result can never look complete. |
| readProvenance | No | Original read bounds; reuse intersects these with currently valid authority. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes beyond the annotations by disclosing a non-obvious side effect: presenting an access key commits a revision and a bounded operational audit (at most one aggregate per grant/surface/outcome/UTC day). That is exactly the kind of hidden write behavior an agent needs, and it is consistent with readOnlyHint=false. It omits failure behavior for the scoped-view empty-result case and pagination mechanics, but annotations carry the safety fundamentals.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core verb and scope, then sibling routing, then the caveats. It is dense and somewhat telegraphic (clause-stacked with semicolons), but almost every clause carries real information; no filler sentences.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 11-parameter tool with 100% schema coverage, an output schema, and annotations, the description supplies the remaining pieces: return shape ('paginated matches and completeness'), matching semantics, filter-only mode, and the access-key write side effect. Nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description earns the extra point by clarifying query semantics beyond the schema text — '"redis timeout" requires both terms, not an exact phrase' and 'empty query applies filters only' disambiguate AND-matching vs phrase-matching, which the schema alone does not state as crisply.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Find records containing every query term for a precise content lookup,' and immediately contrasts with shadowgraph_retrieve, shadowgraph_recall, and shadowgraph_context by role. An agent can pick this tool over its siblings without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names the four nearest alternatives and what each does instead ('adds one-hop neighbours', 'ranks matches', 'prepares a working set'), which gives clear routing guidance. It stops short of explicit when-not-to-use conditions or precedence, so it falls just short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shadowgraph_supersedeADestructive
Mark one decision superseded by a replacement in the same project. shadowgraph_record_decision creates the replacement; shadowgraph_update_status changes state without replacement. Returns previous, replacement and relation. Both IDs must be owned in the same project/origin. History stays searchable; even repeats commit a revision.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Owning project; required unless originId is set, else the write is refused. | |
| originId | No | Capture-origin id; with no project the record belongs to it alone. | |
| decisionId | Yes | The decision being replaced. It becomes superseded and is excluded from current context. | |
| replacementId | Yes | The decision replacing it. Must be in the same project and must not be superseded, archived, abandoned, or stale. |
Output Schema
| Name | Required | Description |
|---|---|---|
| previous | Yes | A stored decision, including its alternatives and auditable confidence basis. |
| relation | Yes | The supersedes relationship, or null when a repeated supersession found none to report. |
| replacement | Yes | A stored decision, including its alternatives and auditable confidence basis. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the write as destructive, non-idempotent, and non-readonly, so the description need not repeat safety flags. It adds useful behavior beyond those annotations: it returns previous, replacement, and relation; history remains searchable; and even repeat calls commit a revision. It does not explicitly describe reversibility or authorization requirements, which keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core action and then adds only high-value clauses: sibling differentiation, return shape, ownership constraint, and history/revision behavior. Every sentence earns its place and there is no redundant restatement of the schema or annotations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the destructive write annotation, full schema coverage, and an output schema, the description supplies the remaining context an agent needs: when to use this versus sibling tools, the same-project/origin ownership rule, and the fact that history remains searchable and repeats create revisions. It is complete for correct selection and invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents each parameter thoroughly, including that decisionId becomes superseded and replacementId must not be superseded, archived, abandoned, or stale. The description adds a cross-parameter ownership constraint (same project/origin) beyond individual field definitions, but otherwise relies on the schema for parameter meaning. A 3 reflects the baseline when schema does the heavy lifting plus modest added constraint context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: marking one decision as superseded by a replacement in the same project. It explicitly distinguishes this from shadowgraph_record_decision (creates the replacement) and shadowgraph_update_status (changes state without replacement), so an agent can route correctly without opening sibling schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It names the two relevant alternative tools and explains the conditions that select them: record_decision creates the replacement, while update_status changes state without one. It also states the ownership constraint that both IDs must belong to the same project/origin, giving clear preconditions for use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shadowgraph_update_statusADestructive
Move one decision to another lifecycle state. shadowgraph_supersede replaces a decision, shadowgraph_maintain alone produces stale, shadowgraph_record_outcome records the result. stale and superseded are system-owned and rejected. Setting the current state writes nothing but still commits a revision.
| Name | Required | Description | Default |
|---|---|---|---|
| status | Yes | Target state. Legal moves are proposed to planned/in_progress/abandoned/archived; planned to in_progress/abandoned/archived; in_progress to executed/failed/abandoned/archived; executed to validated/failed/reconsidered/archived; validated to reconsidered/archived; failed to reconsidered/abandoned/archived; reconsidered to planned/in_progress/abandoned/archived; stale to reconsidered/archived; abandoned to archived. stale and superseded cannot be set by a caller. | |
| project | No | Owning project; required unless originId is set, else the write is refused. | |
| originId | No | Capture-origin id; with no project the record belongs to it alone. | |
| decisionId | Yes | Identifier of an existing decision, as returned by shadowgraph_record_decision, shadowgraph_search, or shadowgraph_retrieve. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | Stable entity identifier. |
| goal | No | What the decision was trying to achieve. |
| kind | Yes | Entity kind: decision, attempt, memory, fact, relation, review, or alternative. |
| actor | No | Who performed the write. |
| title | No | Short name of the decision. |
| chosen | No | The option that was chosen. |
| client | No | Which client performed the write. |
| status | No | Lifecycle state. Legacy records may carry a value this build does not recognise; shadowgraph_validate reports those. |
| outcome | No | The recorded outcome, or null until one is recorded. |
| project | No | Project namespace; null for an unattributed record or one imported from before projects. |
| evidence | No | Normalised evidence entries: source, type, sourceClass, confidence, observedAt, detail. |
| createdAt | No | ISO 8601 creation time. |
| migration | No | Present only on migrated records; records the legacy value a field was mapped from. |
| sessionId | No | Session identifier recorded with the write. |
| sourceRaw | No | The original origin label when it differed from sourceClass. Audit only; never evidence. |
| updatedAt | No | ISO 8601 time of the last change. |
| confidence | No | Auditable confidence: initial, current (0-1), policy, a history entry per move, and a basis summarising the contributions it was folded from. Legacy records may lack basis. |
| supersedes | No | Identifiers of decisions this one replaced. |
| assumptions | No | Assumptions the decision rests on. Searchable content. |
| reviewAfter | No | ISO 8601 instant after which shadowgraph_maintain marks this decision stale. |
| sourceClass | No | Claimed origin class recorded with the write. A claim, never proof. |
| alternatives | No | Rejected alternatives, each with id, label, reasonRejected, status, and the reopenWhen rules that make it reconsiderable. |
| supersededBy | No | Identifier of the decision that replaced this one. |
| schemaVersion | No | Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded. |
| failedAttempts | No | Attempt identifiers or notes attached to this decision. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds genuinely non-obvious behavior beyond the annotations: stale and superseded are rejected as caller-set targets, and setting the current state is a no-op write that still commits a revision. That no-op/revision detail is exactly the kind of trait an agent cannot infer. The one gap is that destructiveHint=true is never explained — nothing says what a transition destroys or whether it is reversible.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, front-loaded with the action, then the sibling disambiguation, then the two edge-case rules. No filler and no repetition of the enum contents.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists and all four parameters are documented, so the description only needs to carry the tricky behavioral facts — which it does. It leaves the destructive annotation unexplained and does not address the project/originId requirement, though the schema covers the latter.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the status parameter's own description already enumerates the legal moves and the system-owned exclusions, so the description largely restates it. The 'writes nothing but still commits a revision' note adds a little semantic value, but not much beyond the schema baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Move one decision to another lifecycle state.' It then explicitly separates the tool from three siblings (supersede replaces, maintain marks stale, record_outcome records results), so an agent can route without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Alternatives and their distinct roles are named, which gives strong implicit routing guidance — use this for transitions, supersede for replacement, record_outcome for results. What's missing is an explicit statement of the triggering condition ('use when a decision advances or is abandoned') and any prerequisite/permission notes.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shadowgraph_validateA
Diagnose record, graph and journal integrity without applying repairs. shadowgraph_maintain ages records; shadowgraph_review checks decision rules; shadowgraph_repair_plan (full mode only) proposes repairs; shadowgraph_rebuild (full mode only) checks journal replay. Own-scope read saves nothing; an access key commits a revision and bounded audit. For full-mode tools, ask the operator to unset SHADOWGRAPH_MCP_PROFILE and restart with SHADOWGRAPH_MCP_COMPACT=0.
| Name | Required | Description | Default |
|---|---|---|---|
| grantId | No | Alias for accessId; conflicting identifiers are refused. | |
| project | No | Project or confirmed workspace binding; otherwise origin-only. No identity returns an empty scoped view. | |
| accessId | No | Grant ID, rechecked at use. Widens reads only, never write authority. Presenting an access key commits a revision and bounded operational audit: at most one aggregate per grant, surface, outcome and UTC day. Conflicts with a different grantId are refused. | |
| originId | No | Capture-origin id; with no project the record belongs to it alone. |
Output Schema
| Name | Required | Description |
|---|---|---|
| valid | Yes | False when any error or unsupported issue is present. |
| counts | Yes | Issue counts per severity. |
| issues | Yes | Every diagnostic found, each with a stable code and severity. |
| readProvenance | No | Original read bounds; reuse intersects these with currently valid authority. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes beyond the annotations to explain the surprising non-readOnly profile: an own-scope read persists nothing, but presenting an access key commits a revision and a bounded audit capped at one aggregate per grant/surface/outcome/UTC day. That is exactly the side-effect disclosure an agent needs before calling a diagnostic tool that is not marked readOnly, and it is consistent with readOnlyHint=false.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded and dense, with the core purpose in the first clause and alternatives enumerated compactly. Some phrasing is telegraphic ('Own-scope read saves nothing'), which trades clarity for brevity, but no sentence is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and full annotation coverage, the description supplies the missing pieces: how it differs from four siblings, the audit side effect, and the profile-gated availability. Only the concrete trigger condition for running a diagnostic versus reviewing is left implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, including the grantId/accessId alias conflict rule and the 'widens reads only, never write authority' semantics, so the baseline is 3. The description reinforces the access-key commit behavior but adds no parameter detail the schema does not already carry.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and resource set: 'Diagnose record, graph and journal integrity without applying repairs.' The negative scope ('without applying repairs') immediately separates it from repair-oriented siblings, so an agent can identify it without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly maps four alternatives to their jobs: maintain ages records, review checks decision rules, repair_plan proposes repairs, rebuild checks journal replay. It also gives a prerequisite for the full-mode tools (unset SHADOWGRAPH_MCP_PROFILE, restart with SHADOWGRAPH_MCP_COMPACT=0). It stops short of stating the trigger condition for choosing this tool, but the routing coverage is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
8 tool updates
v0.42.4- Changed
shadowgraph_context6 fields changed- changed
Output schema / properties / completeness / properties / capture / properties / gaps / items / properties / reason / enumPrevious value: -[ - "maxQueueDepth", - "maxStoreBytes", - "maxItemsPerSession", - "session_in_another_project", - "raw_expired", - "transcript_unrecognised", - "session_left_project", - "transcript_rewritten", - "transcript_reanchored", - "transcript_incomplete_at_end", - "transcript_line_oversized", - "tool_calls_not_captured" -]New value: +[ + "maxQueueDepth", + "maxStoreBytes", + "maxItemsPerSession", + "session_in_another_project", + "raw_expired", + "prior_setup", + "transcript_unrecognised", + "session_left_project", + "transcript_rewritten", + "transcript_reanchored", + "transcript_incomplete_at_end", + "transcript_line_oversized", + "tool_calls_not_captured" +] - added
Output schema / properties / completeness / properties / capture / properties / priorSetupAdded value: +{ + "description": "Unextracted items of no or an earlier setup; never extracted by the current one.", + "minimum": 0, + "type": "integer" +} - changed
Output schema / properties / relevant / properties / capture / properties / gaps / items / properties / reason / enumPrevious value: -[ - "maxQueueDepth", - "maxStoreBytes", - "maxItemsPerSession", - "session_in_another_project", - "raw_expired", - "transcript_unrecognised", - "session_left_project", - "transcript_rewritten", - "transcript_reanchored", - "transcript_incomplete_at_end", - "transcript_line_oversized", - "tool_calls_not_captured" -]New value: +[ + "maxQueueDepth", + "maxStoreBytes", + "maxItemsPerSession", + "session_in_another_project", + "raw_expired", + "prior_setup", + "transcript_unrecognised", + "session_left_project", + "transcript_rewritten", + "transcript_reanchored", + "transcript_incomplete_at_end", + "transcript_line_oversized", + "tool_calls_not_captured" +] - added
Output schema / properties / relevant / properties / capture / properties / priorSetupAdded value: +{ + "description": "Unextracted items of no or an earlier setup; never extracted by the current one.", + "minimum": 0, + "type": "integer" +} - changed
Output schema / properties / relevant / properties / processing / properties / gaps / items / properties / reason / enumPrevious value: -[ - "maxQueueDepth", - "maxStoreBytes", - "maxItemsPerSession", - "session_in_another_project", - "raw_expired", - "transcript_unrecognised", - "session_left_project", - "transcript_rewritten", - "transcript_reanchored", - "transcript_incomplete_at_end", - "transcript_line_oversized", - "tool_calls_not_captured" -]New value: +[ + "maxQueueDepth", + "maxStoreBytes", + "maxItemsPerSession", + "session_in_another_project", + "raw_expired", + "prior_setup", + "transcript_unrecognised", + "session_left_project", + "transcript_rewritten", + "transcript_reanchored", + "transcript_incomplete_at_end", + "transcript_line_oversized", + "tool_calls_not_captured" +] - added
Output schema / properties / relevant / properties / processing / properties / priorSetupAdded value: +{ + "description": "Unextracted items of no or an earlier setup; never extracted by the current one.", + "minimum": 0, + "type": "integer" +}
- Changed
shadowgraph_expand2 fields changed- changed
Output schema / properties / completeness / properties / capture / properties / gaps / items / properties / reason / enumPrevious value: -[ - "maxQueueDepth", - "maxStoreBytes", - "maxItemsPerSession", - "session_in_another_project", - "raw_expired", - "transcript_unrecognised", - "session_left_project", - "transcript_rewritten", - "transcript_reanchored", - "transcript_incomplete_at_end", - "transcript_line_oversized", - "tool_calls_not_captured" -]New value: +[ + "maxQueueDepth", + "maxStoreBytes", + "maxItemsPerSession", + "session_in_another_project", + "raw_expired", + "prior_setup", + "transcript_unrecognised", + "session_left_project", + "transcript_rewritten", + "transcript_reanchored", + "transcript_incomplete_at_end", + "transcript_line_oversized", + "tool_calls_not_captured" +] - added
Output schema / properties / completeness / properties / capture / properties / priorSetupAdded value: +{ + "description": "Unextracted items of no or an earlier setup; never extracted by the current one.", + "minimum": 0, + "type": "integer" +}
- Changed
shadowgraph_recall2 fields changed- changed
Output schema / properties / completeness / properties / capture / properties / gaps / items / properties / reason / enumPrevious value: -[ - "maxQueueDepth", - "maxStoreBytes", - "maxItemsPerSession", - "session_in_another_project", - "raw_expired", - "transcript_unrecognised", - "session_left_project", - "transcript_rewritten", - "transcript_reanchored", - "transcript_incomplete_at_end", - "transcript_line_oversized", - "tool_calls_not_captured" -]New value: +[ + "maxQueueDepth", + "maxStoreBytes", + "maxItemsPerSession", + "session_in_another_project", + "raw_expired", + "prior_setup", + "transcript_unrecognised", + "session_left_project", + "transcript_rewritten", + "transcript_reanchored", + "transcript_incomplete_at_end", + "transcript_line_oversized", + "tool_calls_not_captured" +] - added
Output schema / properties / completeness / properties / capture / properties / priorSetupAdded value: +{ + "description": "Unextracted items of no or an earlier setup; never extracted by the current one.", + "minimum": 0, + "type": "integer" +}
- Changed
shadowgraph_retrieve2 fields changed- changed
Output schema / properties / completeness / properties / capture / properties / gaps / items / properties / reason / enumPrevious value: -[ - "maxQueueDepth", - "maxStoreBytes", - "maxItemsPerSession", - "session_in_another_project", - "raw_expired", - "transcript_unrecognised", - "session_left_project", - "transcript_rewritten", - "transcript_reanchored", - "transcript_incomplete_at_end", - "transcript_line_oversized", - "tool_calls_not_captured" -]New value: +[ + "maxQueueDepth", + "maxStoreBytes", + "maxItemsPerSession", + "session_in_another_project", + "raw_expired", + "prior_setup", + "transcript_unrecognised", + "session_left_project", + "transcript_rewritten", + "transcript_reanchored", + "transcript_incomplete_at_end", + "transcript_line_oversized", + "tool_calls_not_captured" +] - added
Output schema / properties / completeness / properties / capture / properties / priorSetupAdded value: +{ + "description": "Unextracted items of no or an earlier setup; never extracted by the current one.", + "minimum": 0, + "type": "integer" +}
- Changed
shadowgraph_review2 fields changed- changed
Output schema / properties / completeness / properties / capture / properties / gaps / items / properties / reason / enumPrevious value: -[ - "maxQueueDepth", - "maxStoreBytes", - "maxItemsPerSession", - "session_in_another_project", - "raw_expired", - "transcript_unrecognised", - "session_left_project", - "transcript_rewritten", - "transcript_reanchored", - "transcript_incomplete_at_end", - "transcript_line_oversized", - "tool_calls_not_captured" -]New value: +[ + "maxQueueDepth", + "maxStoreBytes", + "maxItemsPerSession", + "session_in_another_project", + "raw_expired", + "prior_setup", + "transcript_unrecognised", + "session_left_project", + "transcript_rewritten", + "transcript_reanchored", + "transcript_incomplete_at_end", + "transcript_line_oversized", + "tool_calls_not_captured" +] - added
Output schema / properties / completeness / properties / capture / properties / priorSetupAdded value: +{ + "description": "Unextracted items of no or an earlier setup; never extracted by the current one.", + "minimum": 0, + "type": "integer" +}
- Changed
shadowgraph_review_context2 fields changed- changed
Output schema / properties / completeness / properties / capture / properties / gaps / items / properties / reason / enumPrevious value: -[ - "maxQueueDepth", - "maxStoreBytes", - "maxItemsPerSession", - "session_in_another_project", - "raw_expired", - "transcript_unrecognised", - "session_left_project", - "transcript_rewritten", - "transcript_reanchored", - "transcript_incomplete_at_end", - "transcript_line_oversized", - "tool_calls_not_captured" -]New value: +[ + "maxQueueDepth", + "maxStoreBytes", + "maxItemsPerSession", + "session_in_another_project", + "raw_expired", + "prior_setup", + "transcript_unrecognised", + "session_left_project", + "transcript_rewritten", + "transcript_reanchored", + "transcript_incomplete_at_end", + "transcript_line_oversized", + "tool_calls_not_captured" +] - added
Output schema / properties / completeness / properties / capture / properties / priorSetupAdded value: +{ + "description": "Unextracted items of no or an earlier setup; never extracted by the current one.", + "minimum": 0, + "type": "integer" +}
- Changed
shadowgraph_review_signals2 fields changed- changed
Output schema / properties / completeness / properties / capture / properties / gaps / items / properties / reason / enumPrevious value: -[ - "maxQueueDepth", - "maxStoreBytes", - "maxItemsPerSession", - "session_in_another_project", - "raw_expired", - "transcript_unrecognised", - "session_left_project", - "transcript_rewritten", - "transcript_reanchored", - "transcript_incomplete_at_end", - "transcript_line_oversized", - "tool_calls_not_captured" -]New value: +[ + "maxQueueDepth", + "maxStoreBytes", + "maxItemsPerSession", + "session_in_another_project", + "raw_expired", + "prior_setup", + "transcript_unrecognised", + "session_left_project", + "transcript_rewritten", + "transcript_reanchored", + "transcript_incomplete_at_end", + "transcript_line_oversized", + "tool_calls_not_captured" +] - added
Output schema / properties / completeness / properties / capture / properties / priorSetupAdded value: +{ + "description": "Unextracted items of no or an earlier setup; never extracted by the current one.", + "minimum": 0, + "type": "integer" +}
- Changed
shadowgraph_search2 fields changed- changed
Output schema / properties / completeness / properties / capture / properties / gaps / items / properties / reason / enumPrevious value: -[ - "maxQueueDepth", - "maxStoreBytes", - "maxItemsPerSession", - "session_in_another_project", - "raw_expired", - "transcript_unrecognised", - "session_left_project", - "transcript_rewritten", - "transcript_reanchored", - "transcript_incomplete_at_end", - "transcript_line_oversized", - "tool_calls_not_captured" -]New value: +[ + "maxQueueDepth", + "maxStoreBytes", + "maxItemsPerSession", + "session_in_another_project", + "raw_expired", + "prior_setup", + "transcript_unrecognised", + "session_left_project", + "transcript_rewritten", + "transcript_reanchored", + "transcript_incomplete_at_end", + "transcript_line_oversized", + "tool_calls_not_captured" +] - added
Output schema / properties / completeness / properties / capture / properties / priorSetupAdded value: +{ + "description": "Unextracted items of no or an earlier setup; never extracted by the current one.", + "minimum": 0, + "type": "integer" +}
10 tool updates
v0.42.3- Changed
shadowgraph_ack_review1 field changed- changed
Input schema / properties / id / descriptionPrevious value: -"Review signal id, as returned in reviewSignalId by shadowgraph_context, in the id field by shadowgraph_review_signals (full mode only), or in reviewSignals by shadowgraph_maintain. This is the signal id, not the decisionId it refers to."New value: +"Persisted signal id: reviewSignalId from shadowgraph_review or shadowgraph_review_context, or id from shadowgraph_review_signals. A fresh context evaluation can be unpersisted and have no ID. This is not the decisionId."
- Added
shadowgraph_confidence_evidence - Changed
shadowgraph_context3 fields changed- changed
Input schema / properties / changedFacts / descriptionPrevious value: -"Fact keys that just changed. Only string-form reopenWhen rules match this list; it is an ephemeral signal, not durable state."New value: +"Ephemeral changed-key signals for string-form reopenWhen rules; not stored facts. Example: changedFacts:[\"budget\"] fires reopenWhen:[\"budget\"]. Object rules instead read values from facts overrides or stored facts." - changed
Input schema / properties / compact / descriptionPrevious value: -"With query or focalId, true delivers each relevant record as a shortened claim line (T1); false or omitted delivers full records. A line that would omit decisive meaning falls back to the full record. This controls record presentation, not the server tool mode."New value: +"With query or focalId, true delivers each relevant record as a shortened claim line (T1); false or omitted delivers full records. A line that would omit decisive meaning falls back to the full record. This controls record presentation, not the server tool mode. For example, query:\"cache\", compact:true adds relevant.items with expansion handles; compact:true alone does not add relevant." - changed
Input schema / properties / facts / descriptionPrevious value: -"Fact key/value overrides evaluated instead of the stored facts of the same key. Stored facts are used for every key not listed here, so reopen rules still work after a restart."New value: +"Temporary key/value overrides for object rules; unlisted keys use stored facts. Example: facts:{ready:true} tests {key:\"ready\",value:true}. This does not record a fact or fire a string rule; changedFacts supplies those changed-key signals."
- Changed
shadowgraph_maintain2 fields changed- changed
Input schema / properties / changedFacts / descriptionPrevious value: -"Fact keys that just changed. Only string-form reopenWhen rules match this list; it is an ephemeral signal, not durable state."New value: +"Ephemeral changed-key signals for string-form reopenWhen rules; not stored facts. Example: changedFacts:[\"budget\"] fires reopenWhen:[\"budget\"]. Object rules instead read values from facts overrides or stored facts." - changed
Input schema / properties / facts / descriptionPrevious value: -"Fact key/value overrides evaluated instead of the stored facts of the same key. Stored facts are used for every key not listed here, so reopen rules still work after a restart."New value: +"Temporary key/value overrides for object rules; unlisted keys use stored facts. Example: facts:{ready:true} tests {key:\"ready\",value:true}. This does not record a fact or fire a string rule; changedFacts supplies those changed-key signals."
- Changed
shadowgraph_reconsider3 fields changed- changed
Input schema / properties / changedFacts / descriptionPrevious value: -"Fact keys that just changed. Only string-form reopenWhen rules match this list; it is an ephemeral signal, not durable state."New value: +"Ephemeral changed-key signals for string-form reopenWhen rules; not stored facts. Example: changedFacts:[\"budget\"] fires reopenWhen:[\"budget\"]. Object rules instead read values from facts overrides or stored facts." - changed
Input schema / properties / decisionId / descriptionPrevious value: -"Reconsider only this decision. An unknown id, or one belonging to another project, is an error rather than an empty result, so a mis-addressed request can never read as \"nothing changed\"."New value: +"Limit the resolved project/origin to this decision; the ID does not supply scope. Unknown, out-of-scope, archived, abandoned or superseded decisions are rejected. Omit to explain all eligible decisions in scope." - changed
Input schema / properties / facts / descriptionPrevious value: -"Fact key/value overrides evaluated instead of the stored facts of the same key. Stored facts are used for every key not listed here, so reopen rules still work after a restart."New value: +"Temporary key/value overrides for object rules; unlisted keys use stored facts. Example: facts:{ready:true} tests {key:\"ready\",value:true}. This does not record a fact or fire a string rule; changedFacts supplies those changed-key signals."
- Changed
shadowgraph_review2 fields changed- changed
Input schema / properties / changedFacts / descriptionPrevious value: -"Fact keys that just changed. Only string-form reopenWhen rules match this list; it is an ephemeral signal, not durable state."New value: +"Ephemeral changed-key signals for string-form reopenWhen rules; not stored facts. Example: changedFacts:[\"budget\"] fires reopenWhen:[\"budget\"]. Object rules instead read values from facts overrides or stored facts." - changed
Input schema / properties / facts / descriptionPrevious value: -"Fact key/value overrides evaluated instead of the stored facts of the same key. Stored facts are used for every key not listed here, so reopen rules still work after a restart."New value: +"Temporary key/value overrides for object rules; unlisted keys use stored facts. Example: facts:{ready:true} tests {key:\"ready\",value:true}. This does not record a fact or fire a string rule; changedFacts supplies those changed-key signals."
- Changed
shadowgraph_review_context2 fields changed- changed
Input schema / properties / changedFacts / descriptionPrevious value: -"Fact keys that just changed. Only string-form reopenWhen rules match this list; it is an ephemeral signal, not durable state."New value: +"Ephemeral changed-key signals for string-form reopenWhen rules; not stored facts. Example: changedFacts:[\"budget\"] fires reopenWhen:[\"budget\"]. Object rules instead read values from facts overrides or stored facts." - changed
Input schema / properties / facts / descriptionPrevious value: -"Fact key/value overrides evaluated instead of the stored facts of the same key. Stored facts are used for every key not listed here, so reopen rules still work after a restart."New value: +"Temporary key/value overrides for object rules; unlisted keys use stored facts. Example: facts:{ready:true} tests {key:\"ready\",value:true}. This does not record a fact or fire a string rule; changedFacts supplies those changed-key signals."
- Added
shadowgraph_review_signals - Added
shadowgraph_supersede - Added
shadowgraph_update_status
11 tool updates
v0.42.2- Changed
shadowgraph_ack_review1 field changed- changed
Input schema / properties / id / descriptionPrevious value: -"Review signal id, as returned in reviewSignalId by shadowgraph_context, in the id field by shadowgraph_review_signals, or in reviewSignals by shadowgraph_maintain. This is the signal id, not the decisionId it refers to."New value: +"Review signal id, as returned in reviewSignalId by shadowgraph_context, in the id field by shadowgraph_review_signals (full mode only), or in reviewSignals by shadowgraph_maintain. This is the signal id, not the decisionId it refers to."
- Changed
shadowgraph_context3 fields changed- changed
Input schema / properties / accessId / descriptionPrevious value: -"Grant ID, rechecked at use."New value: +"Grant ID, rechecked at use. Widens reads only, never write authority. Presenting an access key commits a revision and bounded operational audit: at most one aggregate per grant, surface, outcome and UTC day. Conflicts with a different grantId are refused." - changed
Input schema / properties / compact / descriptionPrevious value: -"Deliver each relevant record as a derived claim line (T1) instead of the full record. A line that cannot carry its decisive meaning is delivered as the full record."New value: +"With query or focalId, true delivers each relevant record as a shortened claim line (T1); false or omitted delivers full records. A line that would omit decisive meaning falls back to the full record. This controls record presentation, not the server tool mode." - changed
Output schema / properties / relevant / properties / processing / descriptionPrevious value: -"Scoped capture processing; extraction is inactive in this build."New value: +"Scoped capture processing and current extraction availability."
- Changed
shadowgraph_expand2 fields changed- added
Input schema / descriptionAdded value: +"Input recipe: copy the line.expansion fields, omit null optional values, and put its scope.project, scope.originId and scope.grantId at top level. Do not pass the operation name or nest a scope object. Keep the digest and original read bounds; no handle field grants wider authority." - changed
Input schema / properties / accessId / descriptionPrevious value: -"Grant ID, rechecked at use."New value: +"Grant ID, rechecked at use. Widens reads only, never write authority. Presenting an access key commits a revision and bounded operational audit: at most one aggregate per grant, surface, outcome and UTC day. Conflicts with a different grantId are refused."
- Changed
shadowgraph_maintain1 field changed- changed
Input schema / properties / accessId / descriptionPrevious value: -"Grant ID, rechecked at use."New value: +"Grant ID, rechecked at use. Widens reads only, never write authority. Presenting an access key commits a revision and bounded operational audit: at most one aggregate per grant, surface, outcome and UTC day. Conflicts with a different grantId are refused."
- Changed
shadowgraph_recall1 field changed- changed
Input schema / properties / accessId / descriptionPrevious value: -"Grant ID, rechecked at use."New value: +"Grant ID, rechecked at use. Widens reads only, never write authority. Presenting an access key commits a revision and bounded operational audit: at most one aggregate per grant, surface, outcome and UTC day. Conflicts with a different grantId are refused."
- Changed
shadowgraph_reconsider1 field changed- changed
Input schema / properties / accessId / descriptionPrevious value: -"Grant ID, rechecked at use."New value: +"Grant ID, rechecked at use. Widens reads only, never write authority. Presenting an access key commits a revision and bounded operational audit: at most one aggregate per grant, surface, outcome and UTC day. Conflicts with a different grantId are refused."
- Changed
shadowgraph_retrieve1 field changed- changed
Input schema / properties / accessId / descriptionPrevious value: -"Grant ID, rechecked at use."New value: +"Grant ID, rechecked at use. Widens reads only, never write authority. Presenting an access key commits a revision and bounded operational audit: at most one aggregate per grant, surface, outcome and UTC day. Conflicts with a different grantId are refused."
- Changed
shadowgraph_review1 field changed- changed
Input schema / properties / accessId / descriptionPrevious value: -"Grant ID, rechecked at use."New value: +"Grant ID, rechecked at use. Widens reads only, never write authority. Presenting an access key commits a revision and bounded operational audit: at most one aggregate per grant, surface, outcome and UTC day. Conflicts with a different grantId are refused."
- Changed
shadowgraph_review_context1 field changed- changed
Input schema / properties / accessId / descriptionPrevious value: -"Grant ID, rechecked at use."New value: +"Grant ID, rechecked at use. Widens reads only, never write authority. Presenting an access key commits a revision and bounded operational audit: at most one aggregate per grant, surface, outcome and UTC day. Conflicts with a different grantId are refused."
- Changed
shadowgraph_search1 field changed- changed
Input schema / properties / accessId / descriptionPrevious value: -"Grant ID, rechecked at use."New value: +"Grant ID, rechecked at use. Widens reads only, never write authority. Presenting an access key commits a revision and bounded operational audit: at most one aggregate per grant, surface, outcome and UTC day. Conflicts with a different grantId are refused."
- Changed
shadowgraph_validate1 field changed- changed
Input schema / properties / accessId / descriptionPrevious value: -"Grant ID, rechecked at use."New value: +"Grant ID, rechecked at use. Widens reads only, never write authority. Presenting an access key commits a revision and bounded operational audit: at most one aggregate per grant, surface, outcome and UTC day. Conflicts with a different grantId are refused."
30 tool updates
v0.42.1- Changed
shadowgraph_ack_review5 fields changed- changed
Input schema / properties / id / descriptionPrevious value: -"Review signal id, as returned in the id field by shadowgraph_review_signals or in reviewSignals by shadowgraph_maintain. This is the signal id, not the decisionId it refers to."New value: +"Review signal id, as returned in reviewSignalId by shadowgraph_context, in the id field by shadowgraph_review_signals, or in reviewSignals by shadowgraph_maintain. This is the signal id, not the decisionId it refers to." - added
Input schema / properties / originIdAdded value: +{ + "description": "Capture-origin id; with no project the record belongs to it alone.", + "type": "string" +} - added
Input schema / properties / projectAdded value: +{ + "description": "Owning project; required unless originId is set, else the write is refused.", + "type": "string" +} - added
Output schema / properties / coverageAdded value: +{ + "description": "Exact conditions covered, and part of this identity.", + "items": { + "type": "string" + }, + "type": "array" +} - changed
Output schema / properties / reason / descriptionPrevious value: -"Why the signal was raised. Together with decisionId this is the dedupe identity, so the same cause never raises a second signal."New value: +"Why it was raised. Identity is this plus decisionId and coverage."
- Removed
shadowgraph_backup - Removed
shadowgraph_confidence_evidence - Changed
shadowgraph_context44 fields changed- added
Input schema / properties / accessIdAdded value: +{ + "description": "Grant ID, rechecked at use.", + "type": "string" +} - added
Input schema / properties / asOfAdded value: +{ + "description": "ISO 8601 instant for relevant: facts and memories valid then, recency ordered from it, and lines derived as of it.", + "type": "string" +} - added
Input schema / properties / compactAdded value: +{ + "description": "Deliver each relevant record as a derived claim line (T1) instead of the full record. A line that cannot carry its decisive meaning is delivered as the full record.", + "type": "boolean" +} - added
Input schema / properties / focalIdAdded value: +{ + "description": "Entity id to rank graph neighbours from. An id outside the scope reaches nothing, like an unknown one.", + "type": "string" +} - added
Input schema / properties / grantIdAdded value: +{ + "description": "Alias for accessId; conflicting identifiers are refused.", + "type": "string" +} - added
Input schema / properties / originIdAdded value: +{ + "description": "Capture-origin id; with no project the record belongs to it alone.", + "type": "string" +} - changed
Input schema / properties / project / descriptionPrevious value: -"Project namespace. Defaults to \"default\"; an empty string is rejected."New value: +"Project or confirmed workspace binding; otherwise origin-only. No identity returns an empty scoped view." - added
Input schema / properties / queryAdded value: +{ + "description": "Free text. With it or focalId, the response adds relevant: the records in scope that the lexical or graph signal ranks, ahead of the working set. No semantic signal is computed on this read.", + "type": "string" +} - changed
Output schema / properties / activeDecisions / descriptionPrevious value: -"Decisions in a current, actionable state: proposed, planned, in_progress, executed, validated, or reconsidered."New value: +"Decisions whose lifecycle status is current: proposed, planned, in_progress, executed, validated, or reconsidered." - changed
Output schema / properties / activeDecisions / items / properties / project / descriptionPrevious value: -"Project namespace; records imported from a schema that predates projects may carry null."New value: +"Project namespace; null for an unattributed record or one imported from before projects." - added
Output schema / properties / belowConfidenceThresholdAdded value: +{ + "description": "Decisions of any status whose recorded confidence is below the policy threshold.", + "items": { + "description": "One decision whose recorded confidence is below the policy threshold.", + "properties": { + "confidence": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "Recorded current confidence, normally 0-1; null when none is recorded, which counts as below." + }, + "decisionId": { + "description": "The decision.", + "type": "string" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "Its lifecycle status as recorded, whatever it is; null when none is recorded." + }, + "threshold": { + "description": "The policy threshold the confidence is below.", + "type": "number" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Decision title, when the stored decision has one." + } + }, + "required": [ + "decisionId", + "status", + "confidence", + "threshold" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / properties / completeness / descriptionPrevious value: -"Per-collection completeness. context returns five named collections, so one page object cannot describe it."New value: +"Per-collection completeness. context returns several named collections, so one page object cannot describe it." - added
Output schema / properties / completeness / properties / captureAdded value: +{ + "description": "Scoped unprocessed capture, when present.", + "properties": { + "blocked": { + "description": "Items blocked.", + "minimum": 0, + "type": "integer" + }, + "expired": { + "description": "Raw expired before extraction; a gap, not backlog.", + "minimum": 0, + "type": "integer" + }, + "extractionAvailable": { + "description": "Whether extraction runs.", + "type": "boolean" + }, + "failed": { + "description": "Items failed.", + "minimum": 0, + "type": "integer" + }, + "gaps": { + "description": "Capture refusal/unread gaps; no identities.", + "items": { + "properties": { + "from": { + "description": "Gap start time.", + "type": "string" + }, + "reason": { + "description": "Why capture has a gap.", + "enum": [ + "maxQueueDepth", + "maxStoreBytes", + "maxItemsPerSession", + "session_in_another_project", + "raw_expired", + "transcript_unrecognised", + "session_left_project", + "transcript_rewritten", + "transcript_reanchored", + "transcript_incomplete_at_end", + "transcript_line_oversized", + "tool_calls_not_captured" + ], + "type": "string" + }, + "sessions": { + "description": "Sessions covered by this gap.", + "minimum": 0, + "type": "integer" + }, + "to": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "End time, if known." + } + }, + "required": [ + "reason", + "from", + "to" + ], + "type": "object" + }, + "type": "array" + }, + "limited": { + "description": "Admission limits; accepted items kept.", + "items": { + "properties": { + "ceiling": { + "description": "The limit value.", + "minimum": 0, + "type": "integer" + }, + "limit": { + "description": "The limit reached.", + "enum": [ + "maxQueueDepth", + "maxStoreBytes" + ], + "type": "string" + }, + "since": { + "description": "When refusal began.", + "type": "string" + } + }, + "required": [ + "limit", + "ceiling", + "since" + ], + "type": "object" + }, + "type": "array" + }, + "oldestPendingAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Oldest pending capture." + }, + "pending": { + "description": "Items waiting.", + "minimum": 0, + "type": "integer" + }, + "processing": { + "description": "Items claimed.", + "minimum": 0, + "type": "integer" + }, + "workerErrors": { + "description": "Scoped worker stops; fixed codes.", + "items": { + "properties": { + "at": { + "description": "Stop timestamp.", + "type": "string" + }, + "reason": { + "description": "Worker stop code.", + "type": "string" + } + }, + "required": [ + "reason", + "at" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "pending", + "processing", + "failed", + "blocked", + "oldestPendingAt", + "extractionAvailable", + "limited", + "gaps" + ], + "type": "object" +} - added
Output schema / properties / completeness / properties / collections / properties / belowConfidenceThresholdAdded value: +{ + "description": "Counts for belowConfidenceThreshold.", + "properties": { + "hasMore": { + "description": "True when this collection was truncated.", + "type": "boolean" + }, + "omitted": { + "description": "total minus returned for this collection.", + "minimum": 0, + "type": "integer" + }, + "returned": { + "description": "Items returned for this collection.", + "minimum": 0, + "type": "integer" + }, + "total": { + "description": "Items that matched for this collection.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "returned", + "total", + "hasMore", + "omitted" + ], + "type": "object" +} - added
Output schema / properties / completeness / properties / collections / properties / conditionDiagnosticsAdded value: +{ + "description": "Counts for conditionDiagnostics.", + "properties": { + "hasMore": { + "description": "True when this collection was truncated.", + "type": "boolean" + }, + "omitted": { + "description": "total minus returned for this collection.", + "minimum": 0, + "type": "integer" + }, + "returned": { + "description": "Items returned for this collection.", + "minimum": 0, + "type": "integer" + }, + "total": { + "description": "Items that matched for this collection.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "returned", + "total", + "hasMore", + "omitted" + ], + "type": "object" +} - added
Output schema / properties / completeness / properties / collections / properties / failedAttemptsAdded value: +{ + "description": "Counts for failedAttempts.", + "properties": { + "hasMore": { + "description": "True when this collection was truncated.", + "type": "boolean" + }, + "omitted": { + "description": "total minus returned for this collection.", + "minimum": 0, + "type": "integer" + }, + "returned": { + "description": "Items returned for this collection.", + "minimum": 0, + "type": "integer" + }, + "total": { + "description": "Items that matched for this collection.", + "minimum": 0, + "type": "integer" + }, + "undetermined": { + "description": "Captured attempts with no resultClass: undetermined, in no collection.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "returned", + "total", + "hasMore", + "omitted", + "undetermined" + ], + "type": "object" +} - removed
Output schema / properties / completeness / properties / collections / properties / failedAttemptsToAvoidRemoved value: -{ - "description": "Counts for failedAttemptsToAvoid.", - "properties": { - "hasMore": { - "description": "True when this collection was truncated.", - "type": "boolean" - }, - "omitted": { - "description": "total minus returned for this collection.", - "minimum": 0, - "type": "integer" - }, - "returned": { - "description": "Items returned for this collection.", - "minimum": 0, - "type": "integer" - }, - "total": { - "description": "Items that matched for this collection.", - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "returned", - "total", - "hasMore", - "omitted" - ], - "type": "object" -} - added
Output schema / properties / completeness / properties / collections / properties / firedConditionsAdded value: +{ + "description": "Counts for firedConditions.", + "properties": { + "hasMore": { + "description": "True when this collection was truncated.", + "type": "boolean" + }, + "omitted": { + "description": "total minus returned for this collection.", + "minimum": 0, + "type": "integer" + }, + "returned": { + "description": "Items returned for this collection.", + "minimum": 0, + "type": "integer" + }, + "total": { + "description": "Items that matched for this collection.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "returned", + "total", + "hasMore", + "omitted" + ], + "type": "object" +} - removed
Output schema / properties / completeness / properties / collections / properties / openReviewsRemoved value: -{ - "description": "Counts for openReviews.", - "properties": { - "hasMore": { - "description": "True when this collection was truncated.", - "type": "boolean" - }, - "omitted": { - "description": "total minus returned for this collection.", - "minimum": 0, - "type": "integer" - }, - "returned": { - "description": "Items returned for this collection.", - "minimum": 0, - "type": "integer" - }, - "total": { - "description": "Items that matched for this collection.", - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "returned", - "total", - "hasMore", - "omitted" - ], - "type": "object" -} - added
Output schema / properties / completeness / properties / collections / properties / reusableAttemptsAdded value: +{ + "description": "Counts for reusableAttempts.", + "properties": { + "hasMore": { + "description": "True when this collection was truncated.", + "type": "boolean" + }, + "omitted": { + "description": "total minus returned for this collection.", + "minimum": 0, + "type": "integer" + }, + "returned": { + "description": "Items returned for this collection.", + "minimum": 0, + "type": "integer" + }, + "total": { + "description": "Items that matched for this collection.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "returned", + "total", + "hasMore", + "omitted" + ], + "type": "object" +} - removed
Output schema / properties / completeness / properties / collections / properties / suggestedQuestionsRemoved value: -{ - "description": "Counts for suggestedQuestions.", - "properties": { - "hasMore": { - "description": "True when this collection was truncated.", - "type": "boolean" - }, - "omitted": { - "description": "total minus returned for this collection.", - "minimum": 0, - "type": "integer" - }, - "returned": { - "description": "Items returned for this collection.", - "minimum": 0, - "type": "integer" - }, - "total": { - "description": "Items that matched for this collection.", - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "returned", - "total", - "hasMore", - "omitted" - ], - "type": "object" -} - changed
Output schema / properties / completeness / properties / collections / requiredPrevious value: -[ - "activeDecisions", - "staleAssumptions", - "failedAttemptsToAvoid", - "openReviews", - "suggestedQuestions" -]New value: +[ + "activeDecisions", + "staleAssumptions", + "failedAttempts", + "firedConditions", + "belowConfidenceThreshold" +] - changed
Output schema / properties / completeness / properties / complete / descriptionPrevious value: -"True only when no collection was truncated."New value: +"Known-candidate coverage; false for unresolved scope, withheld detail or pending capture; not recall." - added
Output schema / properties / completeness / properties / limitationAdded value: +{ + "description": "Limits of this view.", + "properties": { + "code": { + "description": "Stable limitation code.", + "type": "string" + }, + "detail": { + "description": "What this view cannot establish.", + "type": "string" + } + }, + "required": [ + "code", + "detail" + ], + "type": "object" +} - changed
Output schema / properties / completeness / properties / losslessItems / descriptionPrevious value: -"Always true: items are full records, never summaries."New value: +"False when returned items have withheld or transformed detail." - added
Output schema / properties / completeness / properties / quarantinedAdded value: +{ + "description": "Items withheld as possibly purged.", + "minimum": 0, + "type": "integer" +} - changed
Output schema / properties / completeness / properties / scope / descriptionPrevious value: -"The project this result covers."New value: +"The resolved read boundary." - added
Output schema / properties / completeness / properties / scope / propertiesAdded value: +{ + "grant": { + "anyOf": [ + { + "type": "null" + }, + { + "properties": { + "accessId": { + "description": "The currently rechecked grant identifier.", + "type": "string" + }, + "expiresAt": { + "description": "Earliest effective expiry of this read authority.", + "type": "string" + }, + "surface": { + "description": "Actual runtime surface of this read.", + "enum": [ + "cli", + "mcp", + "http" + ], + "type": "string" + } + }, + "required": [ + "accessId", + "expiresAt", + "surface" + ], + "type": "object" + } + ], + "description": "Effective rechecked grant, or null." + }, + "originPresented": { + "description": "Usable origin presented; not project selection.", + "type": "boolean" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Resolved project, or null." + }, + "requestState": { + "description": "Whether a project was resolved.", + "enum": [ + "project_selected", + "project_unresolved" + ], + "type": "string" + } +} - added
Output schema / properties / completeness / properties / scope / requiredAdded value: +[ + "project", + "requestState", + "originPresented", + "grant" +] - added
Output schema / properties / conditionDiagnosticsAdded value: +{ + "description": "Conditions that could not be settled, or that rest on facts which disagree. Neither a breach nor a confirmed-safe decision.", + "items": { + "description": "Unresolved or contested conditions on one decision or attempt. Not a review signal: neither a breach nor a confirmed-safe decision.", + "properties": { + "attemptId": { + "description": "The attempt involved, for reusableWhen conditions.", + "type": "string" + }, + "conditions": { + "description": "The unresolved or contested conditions.", + "items": { + "description": "One evaluated reopen condition. Verdict \"unknown\" means it could not be evaluated from available evidence, which is not a pass.", + "properties": { + "alternativeId": { + "description": "Alternative carrying it.", + "type": "string" + }, + "alternativeLabel": { + "description": "Label of that alternative.", + "type": "string" + }, + "attemptId": { + "description": "Attempt the condition belongs to, for a reusableWhen rule.", + "type": "string" + }, + "conflictingEvidence": { + "description": "Equally applicable facts that disagree. The verdict rests on the deterministic winner.", + "items": { + "description": "A fact a verdict came from. Unrecorded fields are omitted, never filled in.", + "properties": { + "factId": { + "description": "The observed fact.", + "type": "string" + }, + "observedAt": { + "description": "When observed, if recorded.", + "type": "string" + }, + "sourceClass": { + "description": "Provenance class, if recorded.", + "type": "string" + }, + "validFrom": { + "description": "Validity start, if recorded.", + "type": "string" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "A stored value, any lossless JSON value." + }, + "verificationStatus": { + "description": "Verification status, if recorded.", + "type": "string" + } + }, + "required": [ + "factId", + "value" + ], + "type": "object" + }, + "type": "array" + }, + "decisionId": { + "description": "Decision the condition belongs to, for a reopenWhen rule.", + "type": "string" + }, + "evidence": { + "description": "Provenance of the value used.", + "type": "object" + }, + "expected": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "A stored value, any lossless JSON value." + }, + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Fact key read." + }, + "observed": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "A stored value, any lossless JSON value." + }, + "operator": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Operator the rule declared." + }, + "reason": { + "description": "Why this verdict.", + "type": "string" + }, + "unit": { + "description": "Unit the rule declared, if any.", + "type": "string" + }, + "verdict": { + "description": "Evaluation result.", + "enum": [ + "true", + "false", + "unknown" + ], + "type": "string" + } + }, + "required": [ + "key", + "operator", + "verdict", + "reason" + ], + "type": "object" + }, + "type": "array" + }, + "decisionId": { + "description": "The decision involved, for reopenWhen conditions.", + "type": "string" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Decision title, when stored." + } + }, + "required": [ + "conditions" + ], + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / failedAttemptsAdded value: +{ + "description": "Attempts that failed: resultClass failed or, with none and not captured, a result mentioning failure, regression, or error.", + "items": { + "description": "A stored attempt and its result.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "causalClaim": { + "description": "The cause, attributed apart from the attempt: state recorded (the reason, agent_claimed), unknown, not_recorded, or legacy_freetext (a reason stored before causes were, never classed or evidenced).", + "type": "object" + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "environment": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Where it was tried." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; null for an unattributed record or one imported from before projects." + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why it turned out that way, verbatim as recorded." + }, + "relatedTo": { + "description": "Identifiers of related entities.", + "type": "array" + }, + "result": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "What happened." + }, + "resultClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Declared or observed: failed, succeeded, or inconclusive. If absent: not captured (no captureRef or outcomeEvidence), the wording heuristic classifies; captured, the outcome is undetermined." + }, + "reusableWhen": { + "description": "Conditions recorded for reusing the attempt. All must hold, and none may be unresolved.", + "type": "array" + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "solution": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "What was tried." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + } + }, + "required": [ + "id", + "kind" + ], + "type": "object" + }, + "type": "array" +} - removed
Output schema / properties / failedAttemptsToAvoidRemoved value: -{ - "description": "Attempts whose result mentions failure, regression, or error.", - "items": { - "description": "A stored attempt and its result.", - "properties": { - "actor": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Who performed the write." - }, - "client": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Which client performed the write." - }, - "createdAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "ISO 8601 creation time." - }, - "environment": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Where it was tried." - }, - "id": { - "description": "Stable entity identifier.", - "type": "string" - }, - "kind": { - "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", - "type": "string" - }, - "project": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Project namespace; records imported from a schema that predates projects may carry null." - }, - "reason": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Why it turned out that way." - }, - "relatedTo": { - "description": "Identifiers of related entities.", - "type": "array" - }, - "result": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "What happened." - }, - "reusableWhen": { - "description": "Conditions under which the attempt is worth repeating.", - "type": "array" - }, - "schemaVersion": { - "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", - "type": "integer" - }, - "sessionId": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Session identifier recorded with the write." - }, - "solution": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "What was tried." - }, - "sourceClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Claimed origin class recorded with the write. A claim, never proof." - }, - "sourceRaw": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." - }, - "updatedAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "ISO 8601 time of the last change." - } - }, - "required": [ - "id", - "kind" - ], - "type": "object" - }, - "type": "array" -} - added
Output schema / properties / firedConditionsAdded value: +{ + "description": "Decisions whose recorded review conditions fired, with the conditions and the facts they were computed from.", + "items": { + "description": "One decision whose recorded reopen conditions, review date or failed outcome fired.", + "properties": { + "affectedAlternatives": { + "description": "Labels of the recorded alternatives the fired conditions belong to; all of them when the trigger was not alternative-specific.", + "items": { + "type": "string" + }, + "type": "array" + }, + "decisionId": { + "description": "The decision whose conditions fired.", + "type": "string" + }, + "reason": { + "description": "Comma-separated causes: the fact keys whose reopenWhen rules matched, \"review date reached\", or \"decision outcome failed\".", + "type": "string" + }, + "reviewSignalId": { + "description": "The stored review signal for this decision; shadowgraph_ack_review takes this id.", + "type": "string" + }, + "reviewSignalStatus": { + "description": "Whether this review is open or acknowledged, or unpersisted: no stored signal, because context is a read or the evaluation was wider. Entries are recomputed from current evidence; an acknowledged one still appears.", + "enum": [ + "open", + "acknowledged", + "unpersisted" + ], + "type": "string" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Decision title, when the stored decision has one." + }, + "violatedConditions": { + "description": "The conditions that actually fired, each naming its operator, expected and observed value, and the fact it was computed from.", + "items": { + "description": "One evaluated reopen condition. Verdict \"unknown\" means it could not be evaluated from available evidence, which is not a pass.", + "properties": { + "alternativeId": { + "description": "Alternative carrying it.", + "type": "string" + }, + "alternativeLabel": { + "description": "Label of that alternative.", + "type": "string" + }, + "attemptId": { + "description": "Attempt the condition belongs to, for a reusableWhen rule.", + "type": "string" + }, + "conflictingEvidence": { + "description": "Equally applicable facts that disagree. The verdict rests on the deterministic winner.", + "items": { + "description": "A fact a verdict came from. Unrecorded fields are omitted, never filled in.", + "properties": { + "factId": { + "description": "The observed fact.", + "type": "string" + }, + "observedAt": { + "description": "When observed, if recorded.", + "type": "string" + }, + "sourceClass": { + "description": "Provenance class, if recorded.", + "type": "string" + }, + "validFrom": { + "description": "Validity start, if recorded.", + "type": "string" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "A stored value, any lossless JSON value." + }, + "verificationStatus": { + "description": "Verification status, if recorded.", + "type": "string" + } + }, + "required": [ + "factId", + "value" + ], + "type": "object" + }, + "type": "array" + }, + "decisionId": { + "description": "Decision the condition belongs to, for a reopenWhen rule.", + "type": "string" + }, + "evidence": { + "description": "Provenance of the value used.", + "type": "object" + }, + "expected": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "A stored value, any lossless JSON value." + }, + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Fact key read." + }, + "observed": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "A stored value, any lossless JSON value." + }, + "operator": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Operator the rule declared." + }, + "reason": { + "description": "Why this verdict.", + "type": "string" + }, + "unit": { + "description": "Unit the rule declared, if any.", + "type": "string" + }, + "verdict": { + "description": "Evaluation result.", + "enum": [ + "true", + "false", + "unknown" + ], + "type": "string" + } + }, + "required": [ + "key", + "operator", + "verdict", + "reason" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "decisionId", + "reason", + "affectedAlternatives" + ], + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / noticeAdded value: +{ + "description": "Declared interface metadata, not memory: context is a read, and reviewContext (shadowgraph_review_context) evaluates and persists.", + "properties": { + "code": { + "description": "Stable notice code.", + "enum": [ + "context_does_not_persist" + ], + "type": "string" + }, + "detail": { + "description": "Where the old evaluate-and-persist behaviour moved.", + "type": "string" + }, + "replacement": { + "description": "The replacement operation on each surface.", + "properties": { + "cli": { + "description": "CLI verb to run.", + "type": "string" + }, + "http": { + "description": "HTTP route to call.", + "type": "string" + }, + "kernel": { + "description": "Kernel method to call.", + "type": "string" + }, + "mcp": { + "description": "MCP tool to call.", + "type": "string" + } + }, + "type": "object" + } + }, + "required": [ + "code", + "detail", + "replacement" + ], + "type": "object" +} - removed
Output schema / properties / openReviewsRemoved value: -{ - "description": "Decisions currently due for reconsideration.", - "items": { - "description": "One decision whose rejected alternatives are due for reconsideration.", - "properties": { - "alternativesToReconsider": { - "description": "Labels of the alternatives to look at again; all of them when the trigger was not alternative-specific.", - "items": { - "type": "string" - }, - "type": "array" - }, - "decisionId": { - "description": "The decision to reconsider.", - "type": "string" - }, - "reason": { - "description": "Comma-separated causes: the fact keys whose reopenWhen rules matched, \"review date reached\", or \"decision outcome failed\".", - "type": "string" - }, - "title": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Decision title, when the stored decision has one." - } - }, - "required": [ - "decisionId", - "reason", - "alternativesToReconsider" - ], - "type": "object" - }, - "type": "array" -} - added
Output schema / properties / project / anyOfAdded value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / properties / project / descriptionPrevious value: -"The project this context describes."New value: +"The resolved project, or null when unresolved." - removed
Output schema / properties / project / typeRemoved value: -"string" - added
Output schema / properties / readProvenanceAdded value: +{ + "description": "Original read bounds; reuse intersects these with currently valid authority.", + "properties": { + "accessId": { + "description": "Original grant, revalidated on every reuse.", + "type": "string" + }, + "expiresAt": { + "description": "Original effective expiry; reuse cannot extend it.", + "type": "string" + }, + "request": { + "description": "Original request ownership, preserved during expansion.", + "properties": { + "originId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Original capture origin, or null when absent." + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Original resolved project, or null when unresolved." + } + }, + "required": [ + "project", + "originId" + ], + "type": "object" + }, + "scope": { + "description": "Finite explicit owner bounds; project names, origins and legacy attribution are disjoint.", + "properties": { + "legacyAttributions": { + "description": "Explicit legacy ownership classes; neither is a named project.", + "items": { + "enum": [ + "legacy_ambiguous", + "legacy_unattributed" + ], + "type": "string" + }, + "type": "array" + }, + "originIds": { + "description": "Exact nonempty origin identifiers for unattributed content.", + "items": { + "type": "string" + }, + "type": "array" + }, + "projects": { + "description": "Exact named projects, including a real project named default if requested.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "surfaces": { + "description": "Original permitted surfaces; reuse can only narrow them.", + "items": { + "enum": [ + "cli", + "mcp", + "http" + ], + "type": "string" + }, + "type": "array" + }, + "version": { + "const": 1, + "description": "Version of this bounded read provenance.", + "type": "integer" + } + }, + "required": [ + "version", + "request", + "accessId", + "scope", + "surfaces", + "expiresAt" + ], + "type": "object" +} - added
Output schema / properties / relevantAdded value: +{ + "description": "Present with query or focalId: records in scope ranked on the records themselves, head first.", + "properties": { + "byKind": { + "description": "Candidates by kind.", + "properties": { + "attempt": { + "description": "Candidate attempts.", + "minimum": 0, + "type": "integer" + }, + "decision": { + "description": "Candidate decisions.", + "minimum": 0, + "type": "integer" + }, + "fact": { + "description": "Candidate facts.", + "minimum": 0, + "type": "integer" + }, + "memory": { + "description": "Candidate memories.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "decision", + "attempt", + "memory", + "fact" + ], + "type": "object" + }, + "capture": { + "description": "Scoped unprocessed capture, when present.", + "properties": { + "blocked": { + "description": "Items blocked.", + "minimum": 0, + "type": "integer" + }, + "expired": { + "description": "Raw expired before extraction; a gap, not backlog.", + "minimum": 0, + "type": "integer" + }, + "extractionAvailable": { + "description": "Whether extraction runs.", + "type": "boolean" + }, + "failed": { + "description": "Items failed.", + "minimum": 0, + "type": "integer" + }, + "gaps": { + "description": "Capture refusal/unread gaps; no identities.", + "items": { + "properties": { + "from": { + "description": "Gap start time.", + "type": "string" + }, + "reason": { + "description": "Why capture has a gap.", + "enum": [ + "maxQueueDepth", + "maxStoreBytes", + "maxItemsPerSession", + "session_in_another_project", + "raw_expired", + "transcript_unrecognised", + "session_left_project", + "transcript_rewritten", + "transcript_reanchored", + "transcript_incomplete_at_end", + "transcript_line_oversized", + "tool_calls_not_captured" + ], + "type": "string" + }, + "sessions": { + "description": "Sessions covered by this gap.", + "minimum": 0, + "type": "integer" + }, + "to": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "End time, if known." + } + }, + "required": [ + "reason", + "from", + "to" + ], + "type": "object" + }, + "type": "array" + }, + "limited": { + "description": "Admission limits; accepted items kept.", + "items": { + "properties": { + "ceiling": { + "description": "The limit value.", + "minimum": 0, + "type": "integer" + }, + "limit": { + "description": "The limit reached.", + "enum": [ + "maxQueueDepth", + "maxStoreBytes" + ], + "type": "string" + }, + "since": { + "description": "When refusal began.", + "type": "string" + } + }, + "required": [ + "limit", + "ceiling", + "since" + ], + "type": "object" + }, + "type": "array" + }, + "oldestPendingAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Oldest pending capture." + }, + "pending": { + "description": "Items waiting.", + "minimum": 0, + "type": "integer" + }, + "processing": { + "description": "Items claimed.", + "minimum": 0, + "type": "integer" + }, + "workerErrors": { + "description": "Scoped worker stops; fixed codes.", + "items": { + "properties": { + "at": { + "description": "Stop timestamp.", + "type": "string" + }, + "reason": { + "description": "Worker stop code.", + "type": "string" + } + }, + "required": [ + "reason", + "at" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "pending", + "processing", + "failed", + "blocked", + "oldestPendingAt", + "extractionAvailable", + "limited", + "gaps" + ], + "type": "object" + }, + "complete": { + "description": "All counted candidates returned, relevance established and the scope resolved; not semantic recall.", + "type": "boolean" + }, + "expansion": { + "description": "The operation a line handle names.", + "properties": { + "available": { + "description": "True: shadowgraph_expand serves the full record behind a line.", + "type": "boolean" + }, + "operation": { + "description": "Operation name.", + "type": "string" + } + }, + "required": [ + "operation", + "available" + ], + "type": "object" + }, + "fallback": { + "description": "Whether fuller delivery replaced relevance or a line.", + "properties": { + "reason": { + "anyOf": [ + { + "enum": [ + "relevance_not_established", + "decisive_meaning_omitted" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "relevance_not_established: no signal ranked a record, so the working set is delivered. decisive_meaning_omitted: a line could not carry its decisive meaning, so that record is delivered in full." + }, + "used": { + "description": "True when the working set or a full record was delivered instead.", + "type": "boolean" + } + }, + "required": [ + "used", + "reason" + ], + "type": "object" + }, + "hasMore": { + "description": "True when limit left candidates out.", + "type": "boolean" + }, + "items": { + "description": "Ranked records, best first; the working set when fallback reason is relevance_not_established.", + "items": { + "description": "One relevant record, as its line (T1) or in full (T2), with the ranks that selected it.", + "properties": { + "line": { + "description": "A derived claim line (T1): never canonical, bound to the revision it was derived from.", + "properties": { + "boundRevision": { + "description": "The record id and the SHA-256 digest of what the line was derived from.", + "type": "object" + }, + "claimClass": { + "description": "The weakest class among its claims and its cause: quoted, entailed, ambiguous, unsupported, legacy_freetext, or not_classified.", + "type": "string" + }, + "decisiveOmitted": { + "description": "Decisive parts the line could not carry; empty on a delivered line.", + "items": { + "type": "string" + }, + "type": "array" + }, + "derivationVersion": { + "description": "Version of the template.", + "type": "string" + }, + "derived": { + "description": "Always true: a line is never canonical.", + "type": "boolean" + }, + "expansion": { + "description": "Handle for the full record: operation, record id, digest, as-of, derivation version, scope and derivation time.", + "type": "object" + }, + "kind": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The kind of that record." + }, + "line": { + "description": "The record in one line, from a versioned template: stored values quoted, recorded conditions stated as recorded.", + "type": "string" + }, + "outcome": { + "description": "Attempts only: result class, outcome-evidence state and cause state.", + "type": "object" + }, + "polarity": { + "description": "Whether decisive text negates, with the negating text verbatim.", + "type": "object" + }, + "preconditions": { + "description": "Recorded reopen and reuse conditions and assumptions, verbatim.", + "type": "object" + }, + "provenance": { + "description": "Source class and capture reference.", + "type": "object" + }, + "recordId": { + "description": "The record the line was derived from.", + "type": "string" + }, + "requiresExpansion": { + "description": "True when a negation is not settled by a verified claim stating it.", + "type": "boolean" + }, + "scope": { + "description": "Project, memory scope, environment and applicability window.", + "type": "object" + }, + "status": { + "description": "Lifecycle, supersession and verification state.", + "type": "object" + } + }, + "required": [ + "recordId", + "kind", + "line", + "claimClass", + "polarity", + "scope", + "preconditions", + "status", + "provenance", + "boundRevision", + "derived", + "derivationVersion", + "decisiveOmitted", + "requiresExpansion", + "expansion" + ], + "type": "object" + }, + "ranks": { + "anyOf": [ + { + "description": "Position this item held in each signal list, counting from 1, or null where that signal did not rank it.", + "properties": { + "graph": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Position in the graph-distance list; null when no focalId was supplied." + }, + "lexical": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Position in the BM25-style lexical list." + }, + "semantic": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Position in the vector list; null when no compatible query vector or provider existed." + }, + "temporal": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Position in the recency list; null when neither asOf nor preferRecent was supplied." + } + }, + "required": [ + "lexical", + "semantic", + "graph", + "temporal" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Position in each signal list; null for a working-set record delivered by the fallback." + }, + "record": { + "description": "One stored entity: a decision, attempt, memory, fact, or alternative. Fields vary by kind, and an entity imported from an older schema may carry fewer of them.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; null for an unattributed record or one imported from before projects." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + } + }, + "type": "object" + }, + "score": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Fused rank score; null for a working-set record delivered by the fallback." + }, + "temporalEvidence": { + "description": "What the stored times and supersession support: when it was recorded, when it held, whether it holds now.", + "properties": { + "currentState": { + "anyOf": [ + { + "description": "Whether it holds at the read instant, and on what basis.", + "properties": { + "basis": { + "anyOf": [ + { + "enum": [ + "explicit_supersession", + "validity_window", + "recording_order_only" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "What decides it; null when nothing temporal does." + }, + "evidence": { + "description": "The records that decide it, at most 10.", + "items": { + "type": "string" + }, + "type": "array" + }, + "evidenceOmitted": { + "description": "Deciding records not named.", + "minimum": 0, + "type": "integer" + }, + "state": { + "description": "unresolved: only the recording order sets it apart from another version. undetermined: no event time places it at the read instant.", + "enum": [ + "current", + "historical", + "not_yet_valid", + "unresolved", + "undetermined" + ], + "type": "string" + } + }, + "required": [ + "state", + "basis", + "evidence", + "evidenceOmitted" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "null for an attempt, an event." + }, + "eventTime": { + "description": "When it held, if stored apart from the recording time.", + "properties": { + "at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The event time, when known." + }, + "state": { + "description": "unknown: no event time stored apart from the recording time.", + "enum": [ + "known", + "unknown" + ], + "type": "string" + } + }, + "required": [ + "at", + "state" + ], + "type": "object" + }, + "recordedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When it was recorded." + } + }, + "required": [ + "recordedAt", + "eventTime", + "currentState" + ], + "type": "object" + }, + "tier": { + "description": "T1 carries line, T2 carries record.", + "enum": [ + "T1", + "T2" + ], + "type": "string" + } + }, + "required": [ + "tier", + "score", + "ranks", + "temporalEvidence" + ], + "type": "object" + }, + "type": "array" + }, + "limitSource": { + "description": "Whose choice bounded the items.", + "enum": [ + "caller", + "default" + ], + "type": "string" + }, + "limitation": { + "description": "Limits of this view.", + "properties": { + "code": { + "description": "Stable limitation code.", + "type": "string" + }, + "detail": { + "description": "What this view cannot establish.", + "type": "string" + } + }, + "required": [ + "code", + "detail" + ], + "type": "object" + }, + "lines": { + "description": "One entry per delivered line, in item order.", + "items": { + "description": "A delivered line.", + "properties": { + "claimClass": { + "description": "The claim class of that line.", + "type": "string" + }, + "recordId": { + "description": "The record the line was derived from.", + "type": "string" + }, + "requiresExpansion": { + "description": "Whether that line requires expansion.", + "type": "boolean" + } + }, + "required": [ + "recordId", + "claimClass", + "requiresExpansion" + ], + "type": "object" + }, + "type": "array" + }, + "omitted": { + "description": "total minus returned.", + "minimum": 0, + "type": "integer" + }, + "processing": { + "description": "Scoped capture processing; extraction is inactive in this build.", + "properties": { + "blocked": { + "description": "Items whose extraction is blocked.", + "minimum": 0, + "type": "integer" + }, + "extractionAvailable": { + "description": "Whether extraction runs.", + "type": "boolean" + }, + "failed": { + "description": "Items whose extraction failed.", + "minimum": 0, + "type": "integer" + }, + "gaps": { + "description": "Capture refusal/unread gaps; no identities.", + "items": { + "properties": { + "from": { + "description": "Gap start time.", + "type": "string" + }, + "reason": { + "description": "Why capture has a gap.", + "enum": [ + "maxQueueDepth", + "maxStoreBytes", + "maxItemsPerSession", + "session_in_another_project", + "raw_expired", + "transcript_unrecognised", + "session_left_project", + "transcript_rewritten", + "transcript_reanchored", + "transcript_incomplete_at_end", + "transcript_line_oversized", + "tool_calls_not_captured" + ], + "type": "string" + }, + "sessions": { + "description": "Sessions covered by this gap.", + "minimum": 0, + "type": "integer" + }, + "to": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "End time, if known." + } + }, + "required": [ + "reason", + "from", + "to" + ], + "type": "object" + }, + "type": "array" + }, + "limited": { + "description": "Admission limits; accepted items kept.", + "items": { + "properties": { + "ceiling": { + "description": "The limit value.", + "minimum": 0, + "type": "integer" + }, + "limit": { + "description": "The limit reached.", + "enum": [ + "maxQueueDepth", + "maxStoreBytes" + ], + "type": "string" + }, + "since": { + "description": "When refusal began.", + "type": "string" + } + }, + "required": [ + "limit", + "ceiling", + "since" + ], + "type": "object" + }, + "type": "array" + }, + "oldestPendingAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the oldest pending item arrived." + }, + "pending": { + "description": "Items awaiting extraction.", + "minimum": 0, + "type": "integer" + }, + "processing": { + "description": "Items an extraction has claimed; present when the store holds capture state.", + "minimum": 0, + "type": "integer" + }, + "workerErrors": { + "description": "Scoped worker stops; fixed codes.", + "items": { + "properties": { + "at": { + "description": "Stop timestamp.", + "type": "string" + }, + "reason": { + "description": "Worker stop code.", + "type": "string" + } + }, + "required": [ + "reason", + "at" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "pending", + "failed", + "blocked", + "oldestPendingAt", + "extractionAvailable" + ], + "type": "object" + }, + "relevance": { + "description": "Whether any signal established relevance, and which signals ran.", + "properties": { + "established": { + "description": "True when the lexical, semantic or graph signal ranked a record. Recency orders records; it never selects one.", + "type": "boolean" + }, + "signals": { + "description": "Availability of each signal.", + "properties": { + "graph": { + "description": "Distance from focalId.", + "properties": { + "available": { + "description": "Whether the signal ran.", + "type": "boolean" + }, + "matched": { + "description": "Records it ranked.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "available", + "matched" + ], + "type": "object" + }, + "lexical": { + "description": "Content-word matching: available when the query has a content word; matched counts records sharing one. Item ranks use every term.", + "properties": { + "available": { + "description": "Whether the signal ran.", + "type": "boolean" + }, + "matched": { + "description": "Records it ranked.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "available", + "matched" + ], + "type": "object" + }, + "semantic": { + "description": "Meaning; never available on this read.", + "properties": { + "available": { + "description": "Whether the signal ran.", + "type": "boolean" + }, + "matched": { + "description": "Records it ranked.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "available", + "matched" + ], + "type": "object" + }, + "temporal": { + "description": "Recency from asOf.", + "properties": { + "available": { + "description": "Whether the signal ran.", + "type": "boolean" + }, + "matched": { + "description": "Records it ranked.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "available", + "matched" + ], + "type": "object" + } + }, + "required": [ + "lexical", + "semantic", + "graph", + "temporal" + ], + "type": "object" + } + }, + "required": [ + "established", + "signals" + ], + "type": "object" + }, + "returned": { + "description": "Items in this response.", + "minimum": 0, + "type": "integer" + }, + "scope": { + "description": "The resolved read boundary.", + "properties": { + "grant": { + "anyOf": [ + { + "type": "null" + }, + { + "properties": { + "accessId": { + "description": "The currently rechecked grant identifier.", + "type": "string" + }, + "expiresAt": { + "description": "Earliest effective expiry of this read authority.", + "type": "string" + }, + "surface": { + "description": "Actual runtime surface of this read.", + "enum": [ + "cli", + "mcp", + "http" + ], + "type": "string" + } + }, + "required": [ + "accessId", + "expiresAt", + "surface" + ], + "type": "object" + } + ], + "description": "Effective rechecked grant, or null." + }, + "originPresented": { + "description": "Usable origin presented; not project selection.", + "type": "boolean" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Resolved project, or null." + }, + "requestState": { + "description": "Whether a project was resolved.", + "enum": [ + "project_selected", + "project_unresolved" + ], + "type": "string" + } + }, + "required": [ + "project", + "requestState", + "originPresented", + "grant" + ], + "type": "object" + }, + "temporal": { + "description": "The as-of instant, and how many items have no stored event time or rest on the recording order only.", + "properties": { + "asOf": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The asOf given, or null." + }, + "eventTimeUnknown": { + "description": "Items whose event time is unknown.", + "minimum": 0, + "type": "integer" + }, + "recordingOrderOnly": { + "description": "Items whose state rests on the recording order only.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "asOf", + "eventTimeUnknown", + "recordingOrderOnly" + ], + "type": "object" + }, + "total": { + "description": "Candidates in total.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "scope", + "relevance", + "fallback", + "byKind", + "total", + "returned", + "omitted", + "hasMore", + "complete", + "limitSource", + "limitation", + "temporal", + "lines", + "processing", + "expansion", + "items" + ], + "type": "object" +} - added
Output schema / properties / reusableAttemptsAdded value: +{ + "description": "Attempts whose reusableWhen conditions all hold now. The recorded failure still stands, and this is not authorisation to retry.", + "items": { + "description": "An attempt whose reusableWhen conditions ALL hold now, with none unresolved. The recorded failure still stands, and this is not authorisation to retry.", + "properties": { + "attemptId": { + "description": "The attempt.", + "type": "string" + }, + "resultClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Declared or observed result class, or null when the wording heuristic classified it." + }, + "satisfiedConditions": { + "description": "Every condition that had to hold, and the evidence for each.", + "items": { + "description": "One evaluated reopen condition. Verdict \"unknown\" means it could not be evaluated from available evidence, which is not a pass.", + "properties": { + "alternativeId": { + "description": "Alternative carrying it.", + "type": "string" + }, + "alternativeLabel": { + "description": "Label of that alternative.", + "type": "string" + }, + "attemptId": { + "description": "Attempt the condition belongs to, for a reusableWhen rule.", + "type": "string" + }, + "conflictingEvidence": { + "description": "Equally applicable facts that disagree. The verdict rests on the deterministic winner.", + "items": { + "description": "A fact a verdict came from. Unrecorded fields are omitted, never filled in.", + "properties": { + "factId": { + "description": "The observed fact.", + "type": "string" + }, + "observedAt": { + "description": "When observed, if recorded.", + "type": "string" + }, + "sourceClass": { + "description": "Provenance class, if recorded.", + "type": "string" + }, + "validFrom": { + "description": "Validity start, if recorded.", + "type": "string" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "A stored value, any lossless JSON value." + }, + "verificationStatus": { + "description": "Verification status, if recorded.", + "type": "string" + } + }, + "required": [ + "factId", + "value" + ], + "type": "object" + }, + "type": "array" + }, + "decisionId": { + "description": "Decision the condition belongs to, for a reopenWhen rule.", + "type": "string" + }, + "evidence": { + "description": "Provenance of the value used.", + "type": "object" + }, + "expected": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "A stored value, any lossless JSON value." + }, + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Fact key read." + }, + "observed": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "A stored value, any lossless JSON value." + }, + "operator": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Operator the rule declared." + }, + "reason": { + "description": "Why this verdict.", + "type": "string" + }, + "unit": { + "description": "Unit the rule declared, if any.", + "type": "string" + }, + "verdict": { + "description": "Evaluation result.", + "enum": [ + "true", + "false", + "unknown" + ], + "type": "string" + } + }, + "required": [ + "key", + "operator", + "verdict", + "reason" + ], + "type": "object" + }, + "type": "array" + }, + "solution": { + "description": "What was tried.", + "type": "string" + } + }, + "required": [ + "attemptId", + "satisfiedConditions" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / properties / staleAssumptions / items / properties / project / descriptionPrevious value: -"Project namespace; records imported from a schema that predates projects may carry null."New value: +"Project namespace; null for an unattributed record or one imported from before projects." - removed
Output schema / properties / suggestedQuestionsRemoved value: -{ - "description": "Questions for the low-confidence decisions in this project.", - "items": { - "type": "string" - }, - "type": "array" -} - changed
Output schema / requiredPrevious value: -[ - "project", - "activeDecisions", - "staleAssumptions", - "failedAttemptsToAvoid", - "openReviews", - "suggestedQuestions", - "completeness" -]New value: +[ + "project", + "activeDecisions", + "staleAssumptions", + "failedAttempts", + "firedConditions", + "belowConfidenceThreshold", + "completeness", + "notice" +]
- Added
shadowgraph_expand - Removed
shadowgraph_journal - Removed
shadowgraph_link - Changed
shadowgraph_maintain12 fields changed- added
Input schema / properties / accessIdAdded value: +{ + "description": "Grant ID, rechecked at use.", + "type": "string" +} - added
Input schema / properties / grantIdAdded value: +{ + "description": "Alias for accessId; conflicting identifiers are refused.", + "type": "string" +} - added
Input schema / properties / originIdAdded value: +{ + "description": "Capture-origin id; with no project the record belongs to it alone.", + "type": "string" +} - added
Input schema / properties / projectAdded value: +{ + "description": "Project or confirmed workspace binding; otherwise origin-only. No identity returns an empty scoped view.", + "type": "string" +} - added
Output schema / properties / diagnosticsAdded value: +{ + "description": "Conditions that could not be settled, or that rest on facts which disagree.", + "items": { + "description": "Unresolved or contested conditions on one decision or attempt. Not a review signal: neither a breach nor a confirmed-safe decision.", + "properties": { + "attemptId": { + "description": "The attempt involved, for reusableWhen conditions.", + "type": "string" + }, + "conditions": { + "description": "The unresolved or contested conditions.", + "items": { + "description": "One evaluated reopen condition. Verdict \"unknown\" means it could not be evaluated from available evidence, which is not a pass.", + "properties": { + "alternativeId": { + "description": "Alternative carrying it.", + "type": "string" + }, + "alternativeLabel": { + "description": "Label of that alternative.", + "type": "string" + }, + "attemptId": { + "description": "Attempt the condition belongs to, for a reusableWhen rule.", + "type": "string" + }, + "conflictingEvidence": { + "description": "Equally applicable facts that disagree. The verdict rests on the deterministic winner.", + "items": { + "description": "A fact a verdict came from. Unrecorded fields are omitted, never filled in.", + "properties": { + "factId": { + "description": "The observed fact.", + "type": "string" + }, + "observedAt": { + "description": "When observed, if recorded.", + "type": "string" + }, + "sourceClass": { + "description": "Provenance class, if recorded.", + "type": "string" + }, + "validFrom": { + "description": "Validity start, if recorded.", + "type": "string" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "A stored value, any lossless JSON value." + }, + "verificationStatus": { + "description": "Verification status, if recorded.", + "type": "string" + } + }, + "required": [ + "factId", + "value" + ], + "type": "object" + }, + "type": "array" + }, + "decisionId": { + "description": "Decision the condition belongs to, for a reopenWhen rule.", + "type": "string" + }, + "evidence": { + "description": "Provenance of the value used.", + "type": "object" + }, + "expected": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "A stored value, any lossless JSON value." + }, + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Fact key read." + }, + "observed": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "A stored value, any lossless JSON value." + }, + "operator": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Operator the rule declared." + }, + "reason": { + "description": "Why this verdict.", + "type": "string" + }, + "unit": { + "description": "Unit the rule declared, if any.", + "type": "string" + }, + "verdict": { + "description": "Evaluation result.", + "enum": [ + "true", + "false", + "unknown" + ], + "type": "string" + } + }, + "required": [ + "key", + "operator", + "verdict", + "reason" + ], + "type": "object" + }, + "type": "array" + }, + "decisionId": { + "description": "The decision involved, for reopenWhen conditions.", + "type": "string" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Decision title, when stored." + } + }, + "required": [ + "conditions" + ], + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / due / items / properties / reviewSignalIdAdded value: +{ + "description": "Pass this to shadowgraph_ack_review to acknowledge this review.", + "type": "string" +} - added
Output schema / properties / due / items / properties / reviewSignalStatusAdded value: +{ + "description": "Whether this review is open or acknowledged, or unpersisted: no stored signal, because context is a read or the evaluation was wider. Entries are recomputed from current evidence; an acknowledged one still appears.", + "enum": [ + "open", + "acknowledged", + "unpersisted" + ], + "type": "string" +} - added
Output schema / properties / due / items / properties / violatedConditionsAdded value: +{ + "description": "The conditions that actually fired, each naming its operator, expected and observed value, and the fact it was computed from.", + "items": { + "description": "One evaluated reopen condition. Verdict \"unknown\" means it could not be evaluated from available evidence, which is not a pass.", + "properties": { + "alternativeId": { + "description": "Alternative carrying it.", + "type": "string" + }, + "alternativeLabel": { + "description": "Label of that alternative.", + "type": "string" + }, + "attemptId": { + "description": "Attempt the condition belongs to, for a reusableWhen rule.", + "type": "string" + }, + "conflictingEvidence": { + "description": "Equally applicable facts that disagree. The verdict rests on the deterministic winner.", + "items": { + "description": "A fact a verdict came from. Unrecorded fields are omitted, never filled in.", + "properties": { + "factId": { + "description": "The observed fact.", + "type": "string" + }, + "observedAt": { + "description": "When observed, if recorded.", + "type": "string" + }, + "sourceClass": { + "description": "Provenance class, if recorded.", + "type": "string" + }, + "validFrom": { + "description": "Validity start, if recorded.", + "type": "string" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "A stored value, any lossless JSON value." + }, + "verificationStatus": { + "description": "Verification status, if recorded.", + "type": "string" + } + }, + "required": [ + "factId", + "value" + ], + "type": "object" + }, + "type": "array" + }, + "decisionId": { + "description": "Decision the condition belongs to, for a reopenWhen rule.", + "type": "string" + }, + "evidence": { + "description": "Provenance of the value used.", + "type": "object" + }, + "expected": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "A stored value, any lossless JSON value." + }, + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Fact key read." + }, + "observed": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "A stored value, any lossless JSON value." + }, + "operator": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Operator the rule declared." + }, + "reason": { + "description": "Why this verdict.", + "type": "string" + }, + "unit": { + "description": "Unit the rule declared, if any.", + "type": "string" + }, + "verdict": { + "description": "Evaluation result.", + "enum": [ + "true", + "false", + "unknown" + ], + "type": "string" + } + }, + "required": [ + "key", + "operator", + "verdict", + "reason" + ], + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / readProvenanceAdded value: +{ + "description": "Original read bounds; reuse intersects these with currently valid authority.", + "properties": { + "accessId": { + "description": "Original grant, revalidated on every reuse.", + "type": "string" + }, + "expiresAt": { + "description": "Original effective expiry; reuse cannot extend it.", + "type": "string" + }, + "request": { + "description": "Original request ownership, preserved during expansion.", + "properties": { + "originId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Original capture origin, or null when absent." + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Original resolved project, or null when unresolved." + } + }, + "required": [ + "project", + "originId" + ], + "type": "object" + }, + "scope": { + "description": "Finite explicit owner bounds; project names, origins and legacy attribution are disjoint.", + "properties": { + "legacyAttributions": { + "description": "Explicit legacy ownership classes; neither is a named project.", + "items": { + "enum": [ + "legacy_ambiguous", + "legacy_unattributed" + ], + "type": "string" + }, + "type": "array" + }, + "originIds": { + "description": "Exact nonempty origin identifiers for unattributed content.", + "items": { + "type": "string" + }, + "type": "array" + }, + "projects": { + "description": "Exact named projects, including a real project named default if requested.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "surfaces": { + "description": "Original permitted surfaces; reuse can only narrow them.", + "items": { + "enum": [ + "cli", + "mcp", + "http" + ], + "type": "string" + }, + "type": "array" + }, + "version": { + "const": 1, + "description": "Version of this bounded read provenance.", + "type": "integer" + } + }, + "required": [ + "version", + "request", + "accessId", + "scope", + "surfaces", + "expiresAt" + ], + "type": "object" +} - added
Output schema / properties / reviewSignals / items / properties / coverageAdded value: +{ + "description": "Exact conditions covered, and part of this identity.", + "items": { + "type": "string" + }, + "type": "array" +} - changed
Output schema / properties / reviewSignals / items / properties / reason / descriptionPrevious value: -"Why the signal was raised. Together with decisionId this is the dedupe identity, so the same cause never raises a second signal."New value: +"Why it was raised. Identity is this plus decisionId and coverage." - changed
Output schema / properties / reviewSignals / items / requiredPrevious value: -[ - "id", - "kind", - "decisionId", - "reason", - "alternativesToReconsider", - "status", - "createdAt" -]New value: +[ + "id", + "kind", + "decisionId", + "status", + "createdAt" +]
- Removed
shadowgraph_purge - Removed
shadowgraph_purge_preview - Removed
shadowgraph_rebuild - Changed
shadowgraph_recall17 fields changed- added
Input schema / properties / accessIdAdded value: +{ + "description": "Grant ID, rechecked at use.", + "type": "string" +} - added
Input schema / properties / grantIdAdded value: +{ + "description": "Alias for accessId; conflicting identifiers are refused.", + "type": "string" +} - added
Input schema / properties / originIdAdded value: +{ + "description": "Capture-origin id; with no project the record belongs to it alone.", + "type": "string" +} - changed
Input schema / properties / project / descriptionPrevious value: -"Project to recall from. Defaults to \"default\" for memory records rather than meaning all projects."New value: +"Project or confirmed workspace binding; otherwise origin-only. No identity returns an empty scoped view." - added
Input schema / properties / readProvenanceAdded value: +{ + "description": "Original expansion bounds; cannot widen access.", + "type": "object" +} - added
Output schema / properties / completeness / properties / captureAdded value: +{ + "description": "Scoped unprocessed capture, when present.", + "properties": { + "blocked": { + "description": "Items blocked.", + "minimum": 0, + "type": "integer" + }, + "expired": { + "description": "Raw expired before extraction; a gap, not backlog.", + "minimum": 0, + "type": "integer" + }, + "extractionAvailable": { + "description": "Whether extraction runs.", + "type": "boolean" + }, + "failed": { + "description": "Items failed.", + "minimum": 0, + "type": "integer" + }, + "gaps": { + "description": "Capture refusal/unread gaps; no identities.", + "items": { + "properties": { + "from": { + "description": "Gap start time.", + "type": "string" + }, + "reason": { + "description": "Why capture has a gap.", + "enum": [ + "maxQueueDepth", + "maxStoreBytes", + "maxItemsPerSession", + "session_in_another_project", + "raw_expired", + "transcript_unrecognised", + "session_left_project", + "transcript_rewritten", + "transcript_reanchored", + "transcript_incomplete_at_end", + "transcript_line_oversized", + "tool_calls_not_captured" + ], + "type": "string" + }, + "sessions": { + "description": "Sessions covered by this gap.", + "minimum": 0, + "type": "integer" + }, + "to": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "End time, if known." + } + }, + "required": [ + "reason", + "from", + "to" + ], + "type": "object" + }, + "type": "array" + }, + "limited": { + "description": "Admission limits; accepted items kept.", + "items": { + "properties": { + "ceiling": { + "description": "The limit value.", + "minimum": 0, + "type": "integer" + }, + "limit": { + "description": "The limit reached.", + "enum": [ + "maxQueueDepth", + "maxStoreBytes" + ], + "type": "string" + }, + "since": { + "description": "When refusal began.", + "type": "string" + } + }, + "required": [ + "limit", + "ceiling", + "since" + ], + "type": "object" + }, + "type": "array" + }, + "oldestPendingAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Oldest pending capture." + }, + "pending": { + "description": "Items waiting.", + "minimum": 0, + "type": "integer" + }, + "processing": { + "description": "Items claimed.", + "minimum": 0, + "type": "integer" + }, + "workerErrors": { + "description": "Scoped worker stops; fixed codes.", + "items": { + "properties": { + "at": { + "description": "Stop timestamp.", + "type": "string" + }, + "reason": { + "description": "Worker stop code.", + "type": "string" + } + }, + "required": [ + "reason", + "at" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "pending", + "processing", + "failed", + "blocked", + "oldestPendingAt", + "extractionAvailable", + "limited", + "gaps" + ], + "type": "object" +} - changed
Output schema / properties / completeness / properties / complete / descriptionPrevious value: -"True only when every matching item is present."New value: +"Known-candidate coverage; false for unresolved scope, withheld detail or pending capture; not recall." - added
Output schema / properties / completeness / properties / limitationAdded value: +{ + "description": "Limits of this view.", + "properties": { + "code": { + "description": "Stable limitation code.", + "type": "string" + }, + "detail": { + "description": "What this view cannot establish.", + "type": "string" + } + }, + "required": [ + "code", + "detail" + ], + "type": "object" +} - changed
Output schema / properties / completeness / properties / losslessItems / descriptionPrevious value: -"Always true: each returned item is a full-fidelity record, never a summary or a truncated field."New value: +"False when returned items have withheld or transformed detail." - added
Output schema / properties / completeness / properties / quarantinedAdded value: +{ + "description": "Items withheld as possibly purged.", + "minimum": 0, + "type": "integer" +} - changed
Output schema / properties / completeness / properties / scope / descriptionPrevious value: -"The project, query, and structured filters that produced this result, so it explains its own derivation."New value: +"The resolved read boundary." - added
Output schema / properties / completeness / properties / scope / propertiesAdded value: +{ + "grant": { + "anyOf": [ + { + "type": "null" + }, + { + "properties": { + "accessId": { + "description": "The currently rechecked grant identifier.", + "type": "string" + }, + "expiresAt": { + "description": "Earliest effective expiry of this read authority.", + "type": "string" + }, + "surface": { + "description": "Actual runtime surface of this read.", + "enum": [ + "cli", + "mcp", + "http" + ], + "type": "string" + } + }, + "required": [ + "accessId", + "expiresAt", + "surface" + ], + "type": "object" + } + ], + "description": "Effective rechecked grant, or null." + }, + "originPresented": { + "description": "Usable origin presented; not project selection.", + "type": "boolean" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Resolved project, or null." + }, + "requestState": { + "description": "Whether a project was resolved.", + "enum": [ + "project_selected", + "project_unresolved" + ], + "type": "string" + } +} - added
Output schema / properties / completeness / properties / scope / requiredAdded value: +[ + "project", + "requestState", + "originPresented", + "grant" +] - added
Output schema / properties / completeness / properties / signals / properties / semantic / properties / indexedAdded value: +{ + "description": "Candidates carrying a stored vector, with or without a query vector.", + "minimum": 0, + "type": "integer" +} - changed
Output schema / properties / completeness / properties / signals / properties / semantic / requiredPrevious value: -[ - "available", - "matched", - "reason" -]New value: +[ + "available", + "matched", + "indexed", + "reason" +] - changed
Output schema / properties / items / items / properties / record / properties / project / descriptionPrevious value: -"Project namespace; records imported from a schema that predates projects may carry null."New value: +"Project namespace; null for an unattributed record or one imported from before projects." - added
Output schema / properties / readProvenanceAdded value: +{ + "description": "Original read bounds; reuse intersects these with currently valid authority.", + "properties": { + "accessId": { + "description": "Original grant, revalidated on every reuse.", + "type": "string" + }, + "expiresAt": { + "description": "Original effective expiry; reuse cannot extend it.", + "type": "string" + }, + "request": { + "description": "Original request ownership, preserved during expansion.", + "properties": { + "originId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Original capture origin, or null when absent." + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Original resolved project, or null when unresolved." + } + }, + "required": [ + "project", + "originId" + ], + "type": "object" + }, + "scope": { + "description": "Finite explicit owner bounds; project names, origins and legacy attribution are disjoint.", + "properties": { + "legacyAttributions": { + "description": "Explicit legacy ownership classes; neither is a named project.", + "items": { + "enum": [ + "legacy_ambiguous", + "legacy_unattributed" + ], + "type": "string" + }, + "type": "array" + }, + "originIds": { + "description": "Exact nonempty origin identifiers for unattributed content.", + "items": { + "type": "string" + }, + "type": "array" + }, + "projects": { + "description": "Exact named projects, including a real project named default if requested.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "surfaces": { + "description": "Original permitted surfaces; reuse can only narrow them.", + "items": { + "enum": [ + "cli", + "mcp", + "http" + ], + "type": "string" + }, + "type": "array" + }, + "version": { + "const": 1, + "description": "Version of this bounded read provenance.", + "type": "integer" + } + }, + "required": [ + "version", + "request", + "accessId", + "scope", + "surfaces", + "expiresAt" + ], + "type": "object" +}
- Added
shadowgraph_reconsider - Changed
shadowgraph_record_attempt12 fields changed- added
Input schema / descriptionAdded value: +"ShadowGraph generates and returns canonical IDs. Supplying a creation id is refused before lookup or retry; keep returned IDs for later references." - added
Input schema / notAdded value: +{ + "required": [ + "id" + ] +} - changed
Input schema / properties / idempotencyKey / descriptionPrevious value: -"Retry key scoped by project and operation: reuse it so a retry returns the first result instead of writing a duplicate. Without it every call creates a new entity."New value: +"Retry identity within the project or origin and operation (also scope/type/key for memory). Reuse it to recover the original canonical ID; this key is never an entity ID." - added
Input schema / properties / originIdAdded value: +{ + "description": "Capture-origin id; with no project the record belongs to it alone.", + "type": "string" +} - changed
Input schema / properties / project / descriptionPrevious value: -"Project namespace. Defaults to \"default\"; an empty string is rejected."New value: +"Owning project; required unless originId is set, else the write is refused." - changed
Input schema / properties / result / descriptionPrevious value: -"What happened. Required, non-empty, and searchable content. Wording such as failed, error, or regression is what makes the attempt surface in shadowgraph_context as one to avoid."New value: +"What happened. Required, non-empty, and searchable content. With no resultClass, wording such as failed, error, or regression is what places the attempt in shadowgraph_context failedAttempts; a captured attempt's wording is never read." - added
Input schema / properties / resultClassAdded value: +{ + "description": "Classify the result instead of leaving it to the wording heuristic. Set it when the result text does not say failed, error, or regression, or when it does but the attempt did not fail.", + "enum": [ + "failed", + "succeeded", + "inconclusive" + ], + "type": "string" +} - added
Output schema / properties / causalClaimAdded value: +{ + "description": "The cause, attributed apart from the attempt: state recorded (the reason, agent_claimed), unknown, not_recorded, or legacy_freetext (a reason stored before causes were, never classed or evidenced).", + "type": "object" +} - changed
Output schema / properties / project / descriptionPrevious value: -"Project namespace; records imported from a schema that predates projects may carry null."New value: +"Project namespace; null for an unattributed record or one imported from before projects." - changed
Output schema / properties / reason / descriptionPrevious value: -"Why it turned out that way."New value: +"Why it turned out that way, verbatim as recorded." - added
Output schema / properties / resultClassAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Declared or observed: failed, succeeded, or inconclusive. If absent: not captured (no captureRef or outcomeEvidence), the wording heuristic classifies; captured, the outcome is undetermined." +} - changed
Output schema / properties / reusableWhen / descriptionPrevious value: -"Conditions under which the attempt is worth repeating."New value: +"Conditions recorded for reusing the attempt. All must hold, and none may be unresolved."
- Changed
shadowgraph_record_decision8 fields changed- added
Input schema / descriptionAdded value: +"ShadowGraph generates and returns canonical IDs. Supplying a creation id is refused before lookup or retry; keep returned IDs for later references." - added
Input schema / notAdded value: +{ + "required": [ + "id" + ] +} - added
Input schema / properties / alternatives / items / descriptionAdded value: +"ShadowGraph generates and returns canonical IDs. Supplying a creation id is refused before lookup or retry; keep returned IDs for later references." - added
Input schema / properties / alternatives / items / notAdded value: +{ + "required": [ + "id" + ] +} - changed
Input schema / properties / idempotencyKey / descriptionPrevious value: -"Retry key scoped by project and operation: reuse it so a retry returns the first result instead of writing a duplicate. Without it every call creates a new entity."New value: +"Retry identity within the project or origin and operation (also scope/type/key for memory). Reuse it to recover the original canonical ID; this key is never an entity ID." - added
Input schema / properties / originIdAdded value: +{ + "description": "Capture-origin id; with no project the record belongs to it alone.", + "type": "string" +} - changed
Input schema / properties / project / descriptionPrevious value: -"Project namespace. Defaults to \"default\"; an empty string is rejected."New value: +"Owning project; required unless originId is set, else the write is refused." - changed
Output schema / properties / project / descriptionPrevious value: -"Project namespace; records imported from a schema that predates projects may carry null."New value: +"Project namespace; null for an unattributed record or one imported from before projects."
- Changed
shadowgraph_record_fact6 fields changed- added
Input schema / descriptionAdded value: +"ShadowGraph generates and returns canonical IDs. Supplying a creation id is refused before lookup or retry; keep returned IDs for later references." - added
Input schema / notAdded value: +{ + "required": [ + "id" + ] +} - changed
Input schema / properties / idempotencyKey / descriptionPrevious value: -"Retry key scoped by project and operation: reuse it so a retry returns the first result instead of writing a duplicate. Without it every call creates a new entity."New value: +"Retry identity within the project or origin and operation (also scope/type/key for memory). Reuse it to recover the original canonical ID; this key is never an entity ID." - added
Input schema / properties / originIdAdded value: +{ + "description": "Capture-origin id; with no project the record belongs to it alone.", + "type": "string" +} - changed
Input schema / properties / project / descriptionPrevious value: -"Project namespace. Defaults to \"default\"; an empty string is rejected."New value: +"Owning project; required unless originId is set, else the write is refused." - changed
Output schema / properties / project / descriptionPrevious value: -"Project namespace; records imported from a schema that predates projects may carry null."New value: +"Project namespace; null for an unattributed record or one imported from before projects."
- Changed
shadowgraph_record_outcome3 fields changed- added
Input schema / properties / originIdAdded value: +{ + "description": "Capture-origin id; with no project the record belongs to it alone.", + "type": "string" +} - added
Input schema / properties / projectAdded value: +{ + "description": "Owning project; required unless originId is set, else the write is refused.", + "type": "string" +} - changed
Output schema / properties / project / descriptionPrevious value: -"Project namespace; records imported from a schema that predates projects may carry null."New value: +"Project namespace; null for an unattributed record or one imported from before projects."
- Removed
shadowgraph_redact - Changed
shadowgraph_remember7 fields changed- added
Input schema / descriptionAdded value: +"Every envelope and operation rejects a supplied id, including retries, DELETE and NOOP. Memory is selected by its scoped identity tuple; canonical IDs are generated and returned." - added
Input schema / notAdded value: +{ + "required": [ + "id" + ] +} - added
Input schema / properties / idempotencyKeyAdded value: +{ + "description": "Retry identity within the project or origin and operation (also scope/type/key for memory). Reuse it to recover the original canonical ID; this key is never an entity ID.", + "maxLength": 200, + "type": "string" +} - added
Input schema / properties / operations / items / notAdded value: +{ + "required": [ + "id" + ] +} - added
Input schema / properties / originIdAdded value: +{ + "description": "Capture-origin id; with no project the record belongs to it alone.", + "type": "string" +} - changed
Input schema / properties / project / descriptionPrevious value: -"Project namespace. Defaults to \"default\"; an empty string is rejected."New value: +"Owning project; required unless originId is set, else the write is refused." - changed
Output schema / anyOfPrevious value: -[ - { - "properties": { - "indexUpdated": { - "description": "Present when identical content arrived with a different embedding: the index was refreshed without minting a new version.", - "type": "boolean" - }, - "memory": { - "description": "A stored scoped memory version.", - "properties": { - "actor": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Who performed the write." - }, - "client": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Which client performed the write." - }, - "createdAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "ISO 8601 creation time." - }, - "embedding": { - "anyOf": [ - { - "type": "array" - }, - { - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The stored vector, or null when none was supplied and no provider was configured." - }, - "id": { - "description": "Stable entity identifier.", - "type": "string" - }, - "key": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Caller-chosen name within the scope and type." - }, - "kind": { - "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", - "type": "string" - }, - "memoryType": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "preference, profile, goal, instruction, procedure, episode, or note." - }, - "metadata": { - "description": "Caller-owned JSON stored with the memory.", - "type": "object" - }, - "project": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Project namespace; records imported from a schema that predates projects may carry null." - }, - "schemaVersion": { - "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", - "type": "integer" - }, - "scope": { - "description": "The userId, agentId, and runId this memory is scoped to; each is a string or null.", - "type": "object" - }, - "sessionId": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Session identifier recorded with the write." - }, - "sourceClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Claimed origin class recorded with the write. A claim, never proof." - }, - "sourceRaw": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." - }, - "status": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "active, superseded, or invalidated." - }, - "supersededBy": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Identifier of the version that replaced this one." - }, - "supersedes": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Identifier of the version this one replaced." - }, - "tags": { - "description": "Labels stored with the memory.", - "type": "array" - }, - "temporal": { - "description": "Bi-temporal window: validFrom, validTo, recordedAt, invalidatedAt.", - "type": "object" - }, - "text": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The memory content." - }, - "updatedAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "ISO 8601 time of the last change." - }, - "verificationStatus": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Always unverified for memories." - }, - "version": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Version number within this identity, incrementing on each superseding write." - } - }, - "required": [ - "id", - "kind" - ], - "type": "object" - }, - "operation": { - "description": "ADD when no active memory existed, UPDATE when one was superseded, NOOP when content was identical.", - "enum": [ - "ADD", - "UPDATE", - "NOOP" - ], - "type": "string" - }, - "previous": { - "description": "A stored scoped memory version.", - "properties": { - "actor": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Who performed the write." - }, - "client": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Which client performed the write." - }, - "createdAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "ISO 8601 creation time." - }, - "embedding": { - "anyOf": [ - { - "type": "array" - }, - { - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The stored vector, or null when none was supplied and no provider was configured." - }, - "id": { - "description": "Stable entity identifier.", - "type": "string" - }, - "key": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Caller-chosen name within the scope and type." - }, - "kind": { - "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", - "type": "string" - }, - "memoryType": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "preference, profile, goal, instruction, procedure, episode, or note." - }, - "metadata": { - "description": "Caller-owned JSON stored with the memory.", - "type": "object" - }, - "project": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Project namespace; records imported from a schema that predates projects may carry null." - }, - "schemaVersion": { - "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", - "type": "integer" - }, - "scope": { - "description": "The userId, agentId, and runId this memory is scoped to; each is a string or null.", - "type": "object" - }, - "sessionId": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Session identifier recorded with the write." - }, - "sourceClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Claimed origin class recorded with the write. A claim, never proof." - }, - "sourceRaw": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." - }, - "status": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "active, superseded, or invalidated." - }, - "supersededBy": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Identifier of the version that replaced this one." - }, - "supersedes": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Identifier of the version this one replaced." - }, - "tags": { - "description": "Labels stored with the memory.", - "type": "array" - }, - "temporal": { - "description": "Bi-temporal window: validFrom, validTo, recordedAt, invalidatedAt.", - "type": "object" - }, - "text": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The memory content." - }, - "updatedAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "ISO 8601 time of the last change." - }, - "verificationStatus": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Always unverified for memories." - }, - "version": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Version number within this identity, incrementing on each superseding write." - } - }, - "required": [ - "id", - "kind" - ], - "type": "object" - } - }, - "required": [ - "operation", - "memory" - ], - "type": "object" - }, - { - "properties": { - "completeness": { - "description": "Plan accounting. This is not the paginated completeness envelope.", - "properties": { - "applied": { - "description": "Results produced, one per submitted operation.", - "minimum": 0, - "type": "integer" - }, - "complete": { - "description": "Always true: a plan is applied in full or rejected in full.", - "type": "boolean" - }, - "requested": { - "description": "Operations submitted.", - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "complete", - "requested", - "applied" - ], - "type": "object" - }, - "results": { - "description": "One result per submitted operation, in order.", - "items": { - "properties": { - "indexUpdated": { - "description": "Present when only the embedding was refreshed.", - "type": "boolean" - }, - "memory": { - "anyOf": [ - { - "description": "A stored scoped memory version.", - "properties": { - "actor": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Who performed the write." - }, - "client": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Which client performed the write." - }, - "createdAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "ISO 8601 creation time." - }, - "embedding": { - "anyOf": [ - { - "type": "array" - }, - { - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The stored vector, or null when none was supplied and no provider was configured." - }, - "id": { - "description": "Stable entity identifier.", - "type": "string" - }, - "key": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Caller-chosen name within the scope and type." - }, - "kind": { - "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", - "type": "string" - }, - "memoryType": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "preference, profile, goal, instruction, procedure, episode, or note." - }, - "metadata": { - "description": "Caller-owned JSON stored with the memory.", - "type": "object" - }, - "project": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Project namespace; records imported from a schema that predates projects may carry null." - }, - "schemaVersion": { - "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", - "type": "integer" - }, - "scope": { - "description": "The userId, agentId, and runId this memory is scoped to; each is a string or null.", - "type": "object" - }, - "sessionId": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Session identifier recorded with the write." - }, - "sourceClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Claimed origin class recorded with the write. A claim, never proof." - }, - "sourceRaw": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." - }, - "status": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "active, superseded, or invalidated." - }, - "supersededBy": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Identifier of the version that replaced this one." - }, - "supersedes": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Identifier of the version this one replaced." - }, - "tags": { - "description": "Labels stored with the memory.", - "type": "array" - }, - "temporal": { - "description": "Bi-temporal window: validFrom, validTo, recordedAt, invalidatedAt.", - "type": "object" - }, - "text": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The memory content." - }, - "updatedAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "ISO 8601 time of the last change." - }, - "verificationStatus": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Always unverified for memories." - }, - "version": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Version number within this identity, incrementing on each superseding write." - } - }, - "required": [ - "id", - "kind" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The resulting memory, or null for a NOOP on an identity that has no memory." - }, - "operation": { - "description": "What was actually applied, which may differ from the requested action when content already matched.", - "enum": [ - "ADD", - "UPDATE", - "DELETE", - "NOOP" - ], - "type": "string" - }, - "previous": { - "description": "A stored scoped memory version.", - "properties": { - "actor": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Who performed the write." - }, - "client": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Which client performed the write." - }, - "createdAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "ISO 8601 creation time." - }, - "embedding": { - "anyOf": [ - { - "type": "array" - }, - { - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The stored vector, or null when none was supplied and no provider was configured." - }, - "id": { - "description": "Stable entity identifier.", - "type": "string" - }, - "key": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Caller-chosen name within the scope and type." - }, - "kind": { - "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", - "type": "string" - }, - "memoryType": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "preference, profile, goal, instruction, procedure, episode, or note." - }, - "metadata": { - "description": "Caller-owned JSON stored with the memory.", - "type": "object" - }, - "project": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Project namespace; records imported from a schema that predates projects may carry null." - }, - "schemaVersion": { - "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", - "type": "integer" - }, - "scope": { - "description": "The userId, agentId, and runId this memory is scoped to; each is a string or null.", - "type": "object" - }, - "sessionId": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Session identifier recorded with the write." - }, - "sourceClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Claimed origin class recorded with the write. A claim, never proof." - }, - "sourceRaw": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." - }, - "status": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "active, superseded, or invalidated." - }, - "supersededBy": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Identifier of the version that replaced this one." - }, - "supersedes": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Identifier of the version this one replaced." - }, - "tags": { - "description": "Labels stored with the memory.", - "type": "array" - }, - "temporal": { - "description": "Bi-temporal window: validFrom, validTo, recordedAt, invalidatedAt.", - "type": "object" - }, - "text": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The memory content." - }, - "updatedAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "ISO 8601 time of the last change." - }, - "verificationStatus": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Always unverified for memories." - }, - "version": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Version number within this identity, incrementing on each superseding write." - } - }, - "required": [ - "id", - "kind" - ], - "type": "object" - } - }, - "required": [ - "operation", - "memory" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "results", - "completeness" - ], - "type": "object" - } -]New value: +[ + { + "properties": { + "indexUpdated": { + "description": "Present when identical content arrived with a different embedding: the index was refreshed without minting a new version.", + "type": "boolean" + }, + "memory": { + "description": "A stored scoped memory version.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "embedding": { + "anyOf": [ + { + "type": "array" + }, + { + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The stored vector, or null when none was supplied and no provider was configured." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Caller-chosen name within the scope and type." + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "memoryType": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "preference, profile, goal, instruction, procedure, episode, or note." + }, + "metadata": { + "description": "Caller-owned JSON stored with the memory.", + "type": "object" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; null for an unattributed record or one imported from before projects." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "scope": { + "description": "The userId, agentId, and runId this memory is scoped to; each is a string or null.", + "type": "object" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "active, superseded, or invalidated." + }, + "supersededBy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the version that replaced this one." + }, + "supersedes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the version this one replaced." + }, + "tags": { + "description": "Labels stored with the memory.", + "type": "array" + }, + "temporal": { + "description": "Bi-temporal window: validFrom, validTo, recordedAt, invalidatedAt.", + "type": "object" + }, + "text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The memory content." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + }, + "verificationStatus": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Always unverified for memories." + }, + "version": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Version number within this identity, incrementing on each superseding write." + } + }, + "required": [ + "id", + "kind" + ], + "type": "object" + }, + "operation": { + "description": "ADD when no active memory existed, UPDATE when one was superseded, NOOP when content was identical.", + "enum": [ + "ADD", + "UPDATE", + "NOOP" + ], + "type": "string" + }, + "previous": { + "description": "A stored scoped memory version.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "embedding": { + "anyOf": [ + { + "type": "array" + }, + { + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The stored vector, or null when none was supplied and no provider was configured." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Caller-chosen name within the scope and type." + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "memoryType": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "preference, profile, goal, instruction, procedure, episode, or note." + }, + "metadata": { + "description": "Caller-owned JSON stored with the memory.", + "type": "object" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; null for an unattributed record or one imported from before projects." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "scope": { + "description": "The userId, agentId, and runId this memory is scoped to; each is a string or null.", + "type": "object" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "active, superseded, or invalidated." + }, + "supersededBy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the version that replaced this one." + }, + "supersedes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the version this one replaced." + }, + "tags": { + "description": "Labels stored with the memory.", + "type": "array" + }, + "temporal": { + "description": "Bi-temporal window: validFrom, validTo, recordedAt, invalidatedAt.", + "type": "object" + }, + "text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The memory content." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + }, + "verificationStatus": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Always unverified for memories." + }, + "version": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Version number within this identity, incrementing on each superseding write." + } + }, + "required": [ + "id", + "kind" + ], + "type": "object" + } + }, + "required": [ + "operation", + "memory" + ], + "type": "object" + }, + { + "properties": { + "completeness": { + "description": "Plan accounting. This is not the paginated completeness envelope.", + "properties": { + "applied": { + "description": "Results produced, one per submitted operation.", + "minimum": 0, + "type": "integer" + }, + "complete": { + "description": "Always true: a plan is applied in full or rejected in full.", + "type": "boolean" + }, + "requested": { + "description": "Operations submitted.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "complete", + "requested", + "applied" + ], + "type": "object" + }, + "results": { + "description": "One result per submitted operation, in order.", + "items": { + "properties": { + "indexUpdated": { + "description": "Present when only the embedding was refreshed.", + "type": "boolean" + }, + "memory": { + "anyOf": [ + { + "description": "A stored scoped memory version.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "embedding": { + "anyOf": [ + { + "type": "array" + }, + { + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The stored vector, or null when none was supplied and no provider was configured." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Caller-chosen name within the scope and type." + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "memoryType": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "preference, profile, goal, instruction, procedure, episode, or note." + }, + "metadata": { + "description": "Caller-owned JSON stored with the memory.", + "type": "object" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; null for an unattributed record or one imported from before projects." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "scope": { + "description": "The userId, agentId, and runId this memory is scoped to; each is a string or null.", + "type": "object" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "active, superseded, or invalidated." + }, + "supersededBy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the version that replaced this one." + }, + "supersedes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the version this one replaced." + }, + "tags": { + "description": "Labels stored with the memory.", + "type": "array" + }, + "temporal": { + "description": "Bi-temporal window: validFrom, validTo, recordedAt, invalidatedAt.", + "type": "object" + }, + "text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The memory content." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + }, + "verificationStatus": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Always unverified for memories." + }, + "version": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Version number within this identity, incrementing on each superseding write." + } + }, + "required": [ + "id", + "kind" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The resulting memory, or null for a NOOP on an identity that has no memory." + }, + "operation": { + "description": "What was actually applied, which may differ from the requested action when content already matched.", + "enum": [ + "ADD", + "UPDATE", + "DELETE", + "NOOP" + ], + "type": "string" + }, + "previous": { + "description": "A stored scoped memory version.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "embedding": { + "anyOf": [ + { + "type": "array" + }, + { + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The stored vector, or null when none was supplied and no provider was configured." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Caller-chosen name within the scope and type." + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "memoryType": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "preference, profile, goal, instruction, procedure, episode, or note." + }, + "metadata": { + "description": "Caller-owned JSON stored with the memory.", + "type": "object" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; null for an unattributed record or one imported from before projects." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "scope": { + "description": "The userId, agentId, and runId this memory is scoped to; each is a string or null.", + "type": "object" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "active, superseded, or invalidated." + }, + "supersededBy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the version that replaced this one." + }, + "supersedes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the version this one replaced." + }, + "tags": { + "description": "Labels stored with the memory.", + "type": "array" + }, + "temporal": { + "description": "Bi-temporal window: validFrom, validTo, recordedAt, invalidatedAt.", + "type": "object" + }, + "text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The memory content." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + }, + "verificationStatus": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Always unverified for memories." + }, + "version": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Version number within this identity, incrementing on each superseding write." + } + }, + "required": [ + "id", + "kind" + ], + "type": "object" + } + }, + "required": [ + "operation", + "memory" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "results", + "completeness" + ], + "type": "object" + } +]
- Removed
shadowgraph_repair_plan - Removed
shadowgraph_restore - Changed
shadowgraph_retrieve15 fields changed- added
Input schema / properties / accessIdAdded value: +{ + "description": "Grant ID, rechecked at use.", + "type": "string" +} - added
Input schema / properties / grantIdAdded value: +{ + "description": "Alias for accessId; conflicting identifiers are refused.", + "type": "string" +} - added
Input schema / properties / originIdAdded value: +{ + "description": "Capture-origin id; with no project the record belongs to it alone.", + "type": "string" +} - changed
Input schema / properties / project / descriptionPrevious value: -"Restrict to one project, including which neighbours may be pulled in."New value: +"Project or confirmed workspace binding; otherwise origin-only. No identity returns an empty scoped view." - added
Input schema / properties / readProvenanceAdded value: +{ + "description": "Original expansion bounds; cannot widen access.", + "type": "object" +} - added
Output schema / properties / completeness / properties / captureAdded value: +{ + "description": "Scoped unprocessed capture, when present.", + "properties": { + "blocked": { + "description": "Items blocked.", + "minimum": 0, + "type": "integer" + }, + "expired": { + "description": "Raw expired before extraction; a gap, not backlog.", + "minimum": 0, + "type": "integer" + }, + "extractionAvailable": { + "description": "Whether extraction runs.", + "type": "boolean" + }, + "failed": { + "description": "Items failed.", + "minimum": 0, + "type": "integer" + }, + "gaps": { + "description": "Capture refusal/unread gaps; no identities.", + "items": { + "properties": { + "from": { + "description": "Gap start time.", + "type": "string" + }, + "reason": { + "description": "Why capture has a gap.", + "enum": [ + "maxQueueDepth", + "maxStoreBytes", + "maxItemsPerSession", + "session_in_another_project", + "raw_expired", + "transcript_unrecognised", + "session_left_project", + "transcript_rewritten", + "transcript_reanchored", + "transcript_incomplete_at_end", + "transcript_line_oversized", + "tool_calls_not_captured" + ], + "type": "string" + }, + "sessions": { + "description": "Sessions covered by this gap.", + "minimum": 0, + "type": "integer" + }, + "to": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "End time, if known." + } + }, + "required": [ + "reason", + "from", + "to" + ], + "type": "object" + }, + "type": "array" + }, + "limited": { + "description": "Admission limits; accepted items kept.", + "items": { + "properties": { + "ceiling": { + "description": "The limit value.", + "minimum": 0, + "type": "integer" + }, + "limit": { + "description": "The limit reached.", + "enum": [ + "maxQueueDepth", + "maxStoreBytes" + ], + "type": "string" + }, + "since": { + "description": "When refusal began.", + "type": "string" + } + }, + "required": [ + "limit", + "ceiling", + "since" + ], + "type": "object" + }, + "type": "array" + }, + "oldestPendingAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Oldest pending capture." + }, + "pending": { + "description": "Items waiting.", + "minimum": 0, + "type": "integer" + }, + "processing": { + "description": "Items claimed.", + "minimum": 0, + "type": "integer" + }, + "workerErrors": { + "description": "Scoped worker stops; fixed codes.", + "items": { + "properties": { + "at": { + "description": "Stop timestamp.", + "type": "string" + }, + "reason": { + "description": "Worker stop code.", + "type": "string" + } + }, + "required": [ + "reason", + "at" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "pending", + "processing", + "failed", + "blocked", + "oldestPendingAt", + "extractionAvailable", + "limited", + "gaps" + ], + "type": "object" +} - changed
Output schema / properties / completeness / properties / complete / descriptionPrevious value: -"True only when every matching item is present."New value: +"Known-candidate coverage; false for unresolved scope, withheld detail or pending capture; not recall." - added
Output schema / properties / completeness / properties / limitationAdded value: +{ + "description": "Limits of this view.", + "properties": { + "code": { + "description": "Stable limitation code.", + "type": "string" + }, + "detail": { + "description": "What this view cannot establish.", + "type": "string" + } + }, + "required": [ + "code", + "detail" + ], + "type": "object" +} - changed
Output schema / properties / completeness / properties / losslessItems / descriptionPrevious value: -"Always true: each returned item is a full-fidelity record, never a summary or a truncated field."New value: +"False when returned items have withheld or transformed detail." - added
Output schema / properties / completeness / properties / quarantinedAdded value: +{ + "description": "Items withheld as possibly purged.", + "minimum": 0, + "type": "integer" +} - changed
Output schema / properties / completeness / properties / scope / descriptionPrevious value: -"The project, query, and structured filters that produced this result, so it explains its own derivation."New value: +"The resolved read boundary." - added
Output schema / properties / completeness / properties / scope / propertiesAdded value: +{ + "grant": { + "anyOf": [ + { + "type": "null" + }, + { + "properties": { + "accessId": { + "description": "The currently rechecked grant identifier.", + "type": "string" + }, + "expiresAt": { + "description": "Earliest effective expiry of this read authority.", + "type": "string" + }, + "surface": { + "description": "Actual runtime surface of this read.", + "enum": [ + "cli", + "mcp", + "http" + ], + "type": "string" + } + }, + "required": [ + "accessId", + "expiresAt", + "surface" + ], + "type": "object" + } + ], + "description": "Effective rechecked grant, or null." + }, + "originPresented": { + "description": "Usable origin presented; not project selection.", + "type": "boolean" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Resolved project, or null." + }, + "requestState": { + "description": "Whether a project was resolved.", + "enum": [ + "project_selected", + "project_unresolved" + ], + "type": "string" + } +} - added
Output schema / properties / completeness / properties / scope / requiredAdded value: +[ + "project", + "requestState", + "originPresented", + "grant" +] - changed
Output schema / properties / items / items / properties / record / properties / project / descriptionPrevious value: -"Project namespace; records imported from a schema that predates projects may carry null."New value: +"Project namespace; null for an unattributed record or one imported from before projects." - added
Output schema / properties / readProvenanceAdded value: +{ + "description": "Original read bounds; reuse intersects these with currently valid authority.", + "properties": { + "accessId": { + "description": "Original grant, revalidated on every reuse.", + "type": "string" + }, + "expiresAt": { + "description": "Original effective expiry; reuse cannot extend it.", + "type": "string" + }, + "request": { + "description": "Original request ownership, preserved during expansion.", + "properties": { + "originId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Original capture origin, or null when absent." + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Original resolved project, or null when unresolved." + } + }, + "required": [ + "project", + "originId" + ], + "type": "object" + }, + "scope": { + "description": "Finite explicit owner bounds; project names, origins and legacy attribution are disjoint.", + "properties": { + "legacyAttributions": { + "description": "Explicit legacy ownership classes; neither is a named project.", + "items": { + "enum": [ + "legacy_ambiguous", + "legacy_unattributed" + ], + "type": "string" + }, + "type": "array" + }, + "originIds": { + "description": "Exact nonempty origin identifiers for unattributed content.", + "items": { + "type": "string" + }, + "type": "array" + }, + "projects": { + "description": "Exact named projects, including a real project named default if requested.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "surfaces": { + "description": "Original permitted surfaces; reuse can only narrow them.", + "items": { + "enum": [ + "cli", + "mcp", + "http" + ], + "type": "string" + }, + "type": "array" + }, + "version": { + "const": 1, + "description": "Version of this bounded read provenance.", + "type": "integer" + } + }, + "required": [ + "version", + "request", + "accessId", + "scope", + "surfaces", + "expiresAt" + ], + "type": "object" +}
- Changed
shadowgraph_review5 fields changed- added
Input schema / properties / accessIdAdded value: +{ + "description": "Grant ID, rechecked at use.", + "type": "string" +} - added
Input schema / properties / grantIdAdded value: +{ + "description": "Alias for accessId; conflicting identifiers are refused.", + "type": "string" +} - added
Input schema / properties / originIdAdded value: +{ + "description": "Capture-origin id; with no project the record belongs to it alone.", + "type": "string" +} - changed
Input schema / properties / project / descriptionPrevious value: -"Review only this project. Omit to review every project."New value: +"Project or confirmed workspace binding; otherwise origin-only. No identity returns an empty scoped view." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "completeness": { + "description": "Declares exactly what this response left out, so a truncated result can never look complete.", + "properties": { + "capture": { + "description": "Scoped unprocessed capture, when present.", + "properties": { + "blocked": { + "description": "Items blocked.", + "minimum": 0, + "type": "integer" + }, + "expired": { + "description": "Raw expired before extraction; a gap, not backlog.", + "minimum": 0, + "type": "integer" + }, + "extractionAvailable": { + "description": "Whether extraction runs.", + "type": "boolean" + }, + "failed": { + "description": "Items failed.", + "minimum": 0, + "type": "integer" + }, + "gaps": { + "description": "Capture refusal/unread gaps; no identities.", + "items": { + "properties": { + "from": { + "description": "Gap start time.", + "type": "string" + }, + "reason": { + "description": "Why capture has a gap.", + "enum": [ + "maxQueueDepth", + "maxStoreBytes", + "maxItemsPerSession", + "session_in_another_project", + "raw_expired", + "transcript_unrecognised", + "session_left_project", + "transcript_rewritten", + "transcript_reanchored", + "transcript_incomplete_at_end", + "transcript_line_oversized", + "tool_calls_not_captured" + ], + "type": "string" + }, + "sessions": { + "description": "Sessions covered by this gap.", + "minimum": 0, + "type": "integer" + }, + "to": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "End time, if known." + } + }, + "required": [ + "reason", + "from", + "to" + ], + "type": "object" + }, + "type": "array" + }, + "limited": { + "description": "Admission limits; accepted items kept.", + "items": { + "properties": { + "ceiling": { + "description": "The limit value.", + "minimum": 0, + "type": "integer" + }, + "limit": { + "description": "The limit reached.", + "enum": [ + "maxQueueDepth", + "maxStoreBytes" + ], + "type": "string" + }, + "since": { + "description": "When refusal began.", + "type": "string" + } + }, + "required": [ + "limit", + "ceiling", + "since" + ], + "type": "object" + }, + "type": "array" + }, + "oldestPendingAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Oldest pending capture." + }, + "pending": { + "description": "Items waiting.", + "minimum": 0, + "type": "integer" + }, + "processing": { + "description": "Items claimed.", + "minimum": 0, + "type": "integer" + }, + "workerErrors": { + "description": "Scoped worker stops; fixed codes.", + "items": { + "properties": { + "at": { + "description": "Stop timestamp.", + "type": "string" + }, + "reason": { + "description": "Worker stop code.", + "type": "string" + } + }, + "required": [ + "reason", + "at" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "pending", + "processing", + "failed", + "blocked", + "oldestPendingAt", + "extractionAvailable", + "limited", + "gaps" + ], + "type": "object" + }, + "complete": { + "description": "Known-candidate coverage; false for unresolved scope, withheld detail or pending capture; not recall.", + "type": "boolean" + }, + "limitSource": { + "description": "Whose choice bounded the result.", + "enum": [ + "caller", + "default" + ], + "type": "string" + }, + "limitation": { + "description": "Limits of this view.", + "properties": { + "code": { + "description": "Stable limitation code.", + "type": "string" + }, + "detail": { + "description": "What this view cannot establish.", + "type": "string" + } + }, + "required": [ + "code", + "detail" + ], + "type": "object" + }, + "losslessItems": { + "description": "False when returned items have withheld or transformed detail.", + "type": "boolean" + }, + "omitted": { + "description": "total minus returned.", + "minimum": 0, + "type": "integer" + }, + "quarantined": { + "description": "Items withheld as possibly purged.", + "minimum": 0, + "type": "integer" + }, + "returned": { + "description": "Items in this response.", + "minimum": 0, + "type": "integer" + }, + "scope": { + "description": "The resolved read boundary.", + "properties": { + "grant": { + "anyOf": [ + { + "type": "null" + }, + { + "properties": { + "accessId": { + "description": "The currently rechecked grant identifier.", + "type": "string" + }, + "expiresAt": { + "description": "Earliest effective expiry of this read authority.", + "type": "string" + }, + "surface": { + "description": "Actual runtime surface of this read.", + "enum": [ + "cli", + "mcp", + "http" + ], + "type": "string" + } + }, + "required": [ + "accessId", + "expiresAt", + "surface" + ], + "type": "object" + } + ], + "description": "Effective rechecked grant, or null." + }, + "originPresented": { + "description": "Usable origin presented; not project selection.", + "type": "boolean" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Resolved project, or null." + }, + "requestState": { + "description": "Whether a project was resolved.", + "enum": [ + "project_selected", + "project_unresolved" + ], + "type": "string" + } + }, + "required": [ + "project", + "requestState", + "originPresented", + "grant" + ], + "type": "object" + }, + "total": { + "description": "Items that matched in total.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "scope", + "returned", + "total", + "complete", + "omitted", + "losslessItems" + ], + "type": "object" + }, + "items": { + "description": "All known matching items inside this boundary.", + "items": { + "description": "One decision whose rejected alternatives are due for reconsideration.", + "properties": { + "alternativesToReconsider": { + "description": "Labels of the alternatives to look at again; all of them when the trigger was not alternative-specific.", + "items": { + "type": "string" + }, + "type": "array" + }, + "decisionId": { + "description": "The decision to reconsider.", + "type": "string" + }, + "reason": { + "description": "Comma-separated causes: the fact keys whose reopenWhen rules matched, \"review date reached\", or \"decision outcome failed\".", + "type": "string" + }, + "reviewSignalId": { + "description": "Pass this to shadowgraph_ack_review to acknowledge this review.", + "type": "string" + }, + "reviewSignalStatus": { + "description": "Whether this review is open or acknowledged, or unpersisted: no stored signal, because context is a read or the evaluation was wider. Entries are recomputed from current evidence; an acknowledged one still appears.", + "enum": [ + "open", + "acknowledged", + "unpersisted" + ], + "type": "string" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Decision title, when the stored decision has one." + }, + "violatedConditions": { + "description": "The conditions that actually fired, each naming its operator, expected and observed value, and the fact it was computed from.", + "items": { + "description": "One evaluated reopen condition. Verdict \"unknown\" means it could not be evaluated from available evidence, which is not a pass.", + "properties": { + "alternativeId": { + "description": "Alternative carrying it.", + "type": "string" + }, + "alternativeLabel": { + "description": "Label of that alternative.", + "type": "string" + }, + "attemptId": { + "description": "Attempt the condition belongs to, for a reusableWhen rule.", + "type": "string" + }, + "conflictingEvidence": { + "description": "Equally applicable facts that disagree. The verdict rests on the deterministic winner.", + "items": { + "description": "A fact a verdict came from. Unrecorded fields are omitted, never filled in.", + "properties": { + "factId": { + "description": "The observed fact.", + "type": "string" + }, + "observedAt": { + "description": "When observed, if recorded.", + "type": "string" + }, + "sourceClass": { + "description": "Provenance class, if recorded.", + "type": "string" + }, + "validFrom": { + "description": "Validity start, if recorded.", + "type": "string" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "A stored value, any lossless JSON value." + }, + "verificationStatus": { + "description": "Verification status, if recorded.", + "type": "string" + } + }, + "required": [ + "factId", + "value" + ], + "type": "object" + }, + "type": "array" + }, + "decisionId": { + "description": "Decision the condition belongs to, for a reopenWhen rule.", + "type": "string" + }, + "evidence": { + "description": "Provenance of the value used.", + "type": "object" + }, + "expected": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "A stored value, any lossless JSON value." + }, + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Fact key read." + }, + "observed": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "A stored value, any lossless JSON value." + }, + "operator": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Operator the rule declared." + }, + "reason": { + "description": "Why this verdict.", + "type": "string" + }, + "unit": { + "description": "Unit the rule declared, if any.", + "type": "string" + }, + "verdict": { + "description": "Evaluation result.", + "enum": [ + "true", + "false", + "unknown" + ], + "type": "string" + } + }, + "required": [ + "key", + "operator", + "verdict", + "reason" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "decisionId", + "reason", + "alternativesToReconsider" + ], + "type": "object" + }, + "type": "array" + }, + "readProvenance": { + "description": "Original read bounds; reuse intersects these with currently valid authority.", + "properties": { + "accessId": { + "description": "Original grant, revalidated on every reuse.", + "type": "string" + }, + "expiresAt": { + "description": "Original effective expiry; reuse cannot extend it.", + "type": "string" + }, + "request": { + "description": "Original request ownership, preserved during expansion.", + "properties": { + "originId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Original capture origin, or null when absent." + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Original resolved project, or null when unresolved." + } + }, + "required": [ + "project", + "originId" + ], + "type": "object" + }, + "scope": { + "description": "Finite explicit owner bounds; project names, origins and legacy attribution are disjoint.", + "properties": { + "legacyAttributions": { + "description": "Explicit legacy ownership classes; neither is a named project.", + "items": { + "enum": [ + "legacy_ambiguous", + "legacy_unattributed" + ], + "type": "string" + }, + "type": "array" + }, + "originIds": { + "description": "Exact nonempty origin identifiers for unattributed content.", + "items": { + "type": "string" + }, + "type": "array" + }, + "projects": { + "description": "Exact named projects, including a real project named default if requested.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "surfaces": { + "description": "Original permitted surfaces; reuse can only narrow them.", + "items": { + "enum": [ + "cli", + "mcp", + "http" + ], + "type": "string" + }, + "type": "array" + }, + "version": { + "const": 1, + "description": "Version of this bounded read provenance.", + "type": "integer" + } + }, + "required": [ + "version", + "request", + "accessId", + "scope", + "surfaces", + "expiresAt" + ], + "type": "object" + } + }, + "required": [ + "items", + "completeness" + ], + "type": "object" +}
- Added
shadowgraph_review_context - Removed
shadowgraph_review_signals - Changed
shadowgraph_search14 fields changed- added
Input schema / properties / accessIdAdded value: +{ + "description": "Grant ID, rechecked at use.", + "type": "string" +} - added
Input schema / properties / grantIdAdded value: +{ + "description": "Alias for accessId; conflicting identifiers are refused.", + "type": "string" +} - added
Input schema / properties / originIdAdded value: +{ + "description": "Capture-origin id; with no project the record belongs to it alone.", + "type": "string" +} - changed
Input schema / properties / project / descriptionPrevious value: -"Restrict to one project. Omitted, decisions and facts are searched across projects, while memories stay in the default project and all-null scope."New value: +"Project or confirmed workspace binding; otherwise origin-only. No identity returns an empty scoped view." - added
Output schema / properties / completeness / properties / captureAdded value: +{ + "description": "Scoped unprocessed capture, when present.", + "properties": { + "blocked": { + "description": "Items blocked.", + "minimum": 0, + "type": "integer" + }, + "expired": { + "description": "Raw expired before extraction; a gap, not backlog.", + "minimum": 0, + "type": "integer" + }, + "extractionAvailable": { + "description": "Whether extraction runs.", + "type": "boolean" + }, + "failed": { + "description": "Items failed.", + "minimum": 0, + "type": "integer" + }, + "gaps": { + "description": "Capture refusal/unread gaps; no identities.", + "items": { + "properties": { + "from": { + "description": "Gap start time.", + "type": "string" + }, + "reason": { + "description": "Why capture has a gap.", + "enum": [ + "maxQueueDepth", + "maxStoreBytes", + "maxItemsPerSession", + "session_in_another_project", + "raw_expired", + "transcript_unrecognised", + "session_left_project", + "transcript_rewritten", + "transcript_reanchored", + "transcript_incomplete_at_end", + "transcript_line_oversized", + "tool_calls_not_captured" + ], + "type": "string" + }, + "sessions": { + "description": "Sessions covered by this gap.", + "minimum": 0, + "type": "integer" + }, + "to": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "End time, if known." + } + }, + "required": [ + "reason", + "from", + "to" + ], + "type": "object" + }, + "type": "array" + }, + "limited": { + "description": "Admission limits; accepted items kept.", + "items": { + "properties": { + "ceiling": { + "description": "The limit value.", + "minimum": 0, + "type": "integer" + }, + "limit": { + "description": "The limit reached.", + "enum": [ + "maxQueueDepth", + "maxStoreBytes" + ], + "type": "string" + }, + "since": { + "description": "When refusal began.", + "type": "string" + } + }, + "required": [ + "limit", + "ceiling", + "since" + ], + "type": "object" + }, + "type": "array" + }, + "oldestPendingAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Oldest pending capture." + }, + "pending": { + "description": "Items waiting.", + "minimum": 0, + "type": "integer" + }, + "processing": { + "description": "Items claimed.", + "minimum": 0, + "type": "integer" + }, + "workerErrors": { + "description": "Scoped worker stops; fixed codes.", + "items": { + "properties": { + "at": { + "description": "Stop timestamp.", + "type": "string" + }, + "reason": { + "description": "Worker stop code.", + "type": "string" + } + }, + "required": [ + "reason", + "at" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "pending", + "processing", + "failed", + "blocked", + "oldestPendingAt", + "extractionAvailable", + "limited", + "gaps" + ], + "type": "object" +} - changed
Output schema / properties / completeness / properties / complete / descriptionPrevious value: -"True only when every matching item is present."New value: +"Known-candidate coverage; false for unresolved scope, withheld detail or pending capture; not recall." - added
Output schema / properties / completeness / properties / limitationAdded value: +{ + "description": "Limits of this view.", + "properties": { + "code": { + "description": "Stable limitation code.", + "type": "string" + }, + "detail": { + "description": "What this view cannot establish.", + "type": "string" + } + }, + "required": [ + "code", + "detail" + ], + "type": "object" +} - changed
Output schema / properties / completeness / properties / losslessItems / descriptionPrevious value: -"Always true: each returned item is a full-fidelity record, never a summary or a truncated field."New value: +"False when returned items have withheld or transformed detail." - added
Output schema / properties / completeness / properties / quarantinedAdded value: +{ + "description": "Items withheld as possibly purged.", + "minimum": 0, + "type": "integer" +} - changed
Output schema / properties / completeness / properties / scope / descriptionPrevious value: -"The project, query, and structured filters that produced this result, so it explains its own derivation."New value: +"The resolved read boundary." - added
Output schema / properties / completeness / properties / scope / propertiesAdded value: +{ + "grant": { + "anyOf": [ + { + "type": "null" + }, + { + "properties": { + "accessId": { + "description": "The currently rechecked grant identifier.", + "type": "string" + }, + "expiresAt": { + "description": "Earliest effective expiry of this read authority.", + "type": "string" + }, + "surface": { + "description": "Actual runtime surface of this read.", + "enum": [ + "cli", + "mcp", + "http" + ], + "type": "string" + } + }, + "required": [ + "accessId", + "expiresAt", + "surface" + ], + "type": "object" + } + ], + "description": "Effective rechecked grant, or null." + }, + "originPresented": { + "description": "Usable origin presented; not project selection.", + "type": "boolean" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Resolved project, or null." + }, + "requestState": { + "description": "Whether a project was resolved.", + "enum": [ + "project_selected", + "project_unresolved" + ], + "type": "string" + } +} - added
Output schema / properties / completeness / properties / scope / requiredAdded value: +[ + "project", + "requestState", + "originPresented", + "grant" +] - changed
Output schema / properties / items / items / properties / record / properties / project / descriptionPrevious value: -"Project namespace; records imported from a schema that predates projects may carry null."New value: +"Project namespace; null for an unattributed record or one imported from before projects." - added
Output schema / properties / readProvenanceAdded value: +{ + "description": "Original read bounds; reuse intersects these with currently valid authority.", + "properties": { + "accessId": { + "description": "Original grant, revalidated on every reuse.", + "type": "string" + }, + "expiresAt": { + "description": "Original effective expiry; reuse cannot extend it.", + "type": "string" + }, + "request": { + "description": "Original request ownership, preserved during expansion.", + "properties": { + "originId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Original capture origin, or null when absent." + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Original resolved project, or null when unresolved." + } + }, + "required": [ + "project", + "originId" + ], + "type": "object" + }, + "scope": { + "description": "Finite explicit owner bounds; project names, origins and legacy attribution are disjoint.", + "properties": { + "legacyAttributions": { + "description": "Explicit legacy ownership classes; neither is a named project.", + "items": { + "enum": [ + "legacy_ambiguous", + "legacy_unattributed" + ], + "type": "string" + }, + "type": "array" + }, + "originIds": { + "description": "Exact nonempty origin identifiers for unattributed content.", + "items": { + "type": "string" + }, + "type": "array" + }, + "projects": { + "description": "Exact named projects, including a real project named default if requested.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "surfaces": { + "description": "Original permitted surfaces; reuse can only narrow them.", + "items": { + "enum": [ + "cli", + "mcp", + "http" + ], + "type": "string" + }, + "type": "array" + }, + "version": { + "const": 1, + "description": "Version of this bounded read provenance.", + "type": "integer" + } + }, + "required": [ + "version", + "request", + "accessId", + "scope", + "surfaces", + "expiresAt" + ], + "type": "object" +}
- Removed
shadowgraph_supersede - Removed
shadowgraph_traverse - Removed
shadowgraph_update_status - Changed
shadowgraph_validate2 fields changed- added
Input schema / propertiesAdded value: +{ + "accessId": { + "description": "Grant ID, rechecked at use.", + "type": "string" + }, + "grantId": { + "description": "Alias for accessId; conflicting identifiers are refused.", + "type": "string" + }, + "originId": { + "description": "Capture-origin id; with no project the record belongs to it alone.", + "type": "string" + }, + "project": { + "description": "Project or confirmed workspace binding; otherwise origin-only. No identity returns an empty scoped view.", + "type": "string" + } +} - added
Output schema / properties / readProvenanceAdded value: +{ + "description": "Original read bounds; reuse intersects these with currently valid authority.", + "properties": { + "accessId": { + "description": "Original grant, revalidated on every reuse.", + "type": "string" + }, + "expiresAt": { + "description": "Original effective expiry; reuse cannot extend it.", + "type": "string" + }, + "request": { + "description": "Original request ownership, preserved during expansion.", + "properties": { + "originId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Original capture origin, or null when absent." + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Original resolved project, or null when unresolved." + } + }, + "required": [ + "project", + "originId" + ], + "type": "object" + }, + "scope": { + "description": "Finite explicit owner bounds; project names, origins and legacy attribution are disjoint.", + "properties": { + "legacyAttributions": { + "description": "Explicit legacy ownership classes; neither is a named project.", + "items": { + "enum": [ + "legacy_ambiguous", + "legacy_unattributed" + ], + "type": "string" + }, + "type": "array" + }, + "originIds": { + "description": "Exact nonempty origin identifiers for unattributed content.", + "items": { + "type": "string" + }, + "type": "array" + }, + "projects": { + "description": "Exact named projects, including a real project named default if requested.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "surfaces": { + "description": "Original permitted surfaces; reuse can only narrow them.", + "items": { + "enum": [ + "cli", + "mcp", + "http" + ], + "type": "string" + }, + "type": "array" + }, + "version": { + "const": 1, + "description": "Version of this bounded read provenance.", + "type": "integer" + } + }, + "required": [ + "version", + "request", + "accessId", + "scope", + "surfaces", + "expiresAt" + ], + "type": "object" +}
27 tool updates
v0.40.1- Changed
shadowgraph_ack_review2 fields changed- added
Input schema / properties / id / descriptionAdded value: +"Review signal id, as returned in the id field by shadowgraph_review_signals or in reviewSignals by shadowgraph_maintain. This is the signal id, not the decisionId it refers to." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "The acknowledged review signal, retained rather than deleted.", + "properties": { + "acknowledgedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the most recent acknowledgement." + }, + "alternativesToReconsider": { + "description": "Alternative labels to look at again.", + "items": { + "type": "string" + }, + "type": "array" + }, + "createdAt": { + "description": "ISO 8601 time the signal was raised.", + "type": "string" + }, + "decisionId": { + "description": "The decision this signal is about.", + "type": "string" + }, + "id": { + "description": "Signal identifier, used by shadowgraph_ack_review.", + "type": "string" + }, + "kind": { + "const": "review", + "description": "Always \"review\".", + "type": "string" + }, + "reason": { + "description": "Why the signal was raised. Together with decisionId this is the dedupe identity, so the same cause never raises a second signal.", + "type": "string" + }, + "status": { + "description": "open until acknowledged.", + "enum": [ + "open", + "acknowledged" + ], + "type": "string" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Decision title, when the stored decision has one." + } + }, + "required": [ + "id", + "kind", + "decisionId", + "reason", + "alternativesToReconsider", + "status", + "createdAt", + "acknowledgedAt" + ], + "type": "object" +}
- Changed
shadowgraph_backup2 fields changed- added
Input schema / properties / destination / descriptionAdded value: +"Server-side path to write the snapshot to. Required. An existing file there is overwritten; parent directories are created. Use the storage backend’s own extension, .json for JSON stores and .db for SQLite." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Where the snapshot was taken from and written to.", + "properties": { + "destination": { + "description": "Path the snapshot was written to.", + "type": "string" + }, + "source": { + "description": "Path of the live store the snapshot was taken from.", + "type": "string" + } + }, + "required": [ + "source", + "destination" + ], + "type": "object" +}
- Changed
shadowgraph_confidence_evidence10 fields changed- changed
Input schema / properties / actor / descriptionPrevious value: -"Who performed this write, e.g. an agent name."New value: +"Who performed this write, such as an agent or person name. Stored for audit; never used to grant trust." - changed
Input schema / properties / client / descriptionPrevious value: -"Which client performed this write."New value: +"Which client software performed this write, such as the host application name." - added
Input schema / properties / decisionId / descriptionAdded value: +"Identifier of an existing decision, as returned by shadowgraph_record_decision, shadowgraph_search, or shadowgraph_retrieve." - changed
Input schema / properties / key / descriptionPrevious value: -"REQUIRED stable dedupe key. Reuse the same key for the same observation so retries do not double-count; use a NEW key for a genuinely new observation."New value: +"REQUIRED stable dedupe key. Reuse the same key for the same observation so retries cannot double-count; use a NEW key for a genuinely new observation. There is no default, because a generated one would only be stable within a millisecond." - added
Input schema / properties / observedAt / descriptionAdded value: +"ISO 8601 time the evidence was observed. Defaults to now." - added
Input schema / properties / reason / descriptionAdded value: +"Why this evidence matters. Required, non-empty, and kept in the audit history." - changed
Input schema / properties / sessionId / descriptionPrevious value: -"Session identifier for this write."New value: +"Caller-owned identifier that groups related writes in the audit trail." - changed
Input schema / properties / sourceClass / descriptionPrevious value: -"Claimed origin class. A claim, not proof: no value here can make a fact verified."New value: +"Claimed origin, never proof: agent_claimed (the default), tool_observed, human_confirmed, or production_verified. It weights confidence only. An unrecognised label downgrades to agent_claimed, kept verbatim in sourceRaw." - changed
Input schema / properties / supports / descriptionPrevious value: -"Defaults to true. false records contradicting evidence."New value: +"Defaults to true. false records contradicting evidence, moving confidence down instead of up." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "A stored decision, including its alternatives and auditable confidence basis.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "alternatives": { + "description": "Rejected alternatives, each with id, label, reasonRejected, status, and the reopenWhen rules that make it reconsiderable.", + "type": "array" + }, + "assumptions": { + "description": "Assumptions the decision rests on. Searchable content.", + "items": { + "type": "string" + }, + "type": "array" + }, + "chosen": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The option that was chosen." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "confidence": { + "description": "Auditable confidence: initial, current (0-1), policy, a history entry per move, and a basis summarising the contributions it was folded from. Legacy records may lack basis.", + "type": "object" + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "evidence": { + "description": "Normalised evidence entries: source, type, sourceClass, confidence, observedAt, detail.", + "type": "array" + }, + "failedAttempts": { + "description": "Attempt identifiers or notes attached to this decision.", + "type": "array" + }, + "goal": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "What the decision was trying to achieve." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "migration": { + "description": "Present only on migrated records; records the legacy value a field was mapped from.", + "type": "object" + }, + "outcome": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The recorded outcome, or null until one is recorded." + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "reviewAfter": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 instant after which shadowgraph_maintain marks this decision stale." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Lifecycle state. Legacy records may carry a value this build does not recognise; shadowgraph_validate reports those." + }, + "supersededBy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the decision that replaced this one." + }, + "supersedes": { + "description": "Identifiers of decisions this one replaced.", + "type": "array" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Short name of the decision." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + } + }, + "required": [ + "id", + "kind" + ], + "type": "object" +}
- Changed
shadowgraph_context5 fields changed- added
Input schema / properties / changedFacts / descriptionAdded value: +"Fact keys that just changed. Only string-form reopenWhen rules match this list; it is an ephemeral signal, not durable state." - added
Input schema / properties / facts / descriptionAdded value: +"Fact key/value overrides evaluated instead of the stored facts of the same key. Stored facts are used for every key not listed here, so reopen rules still work after a restart." - added
Input schema / properties / limit / descriptionAdded value: +"Maximum items per collection, 1-1000, applied to each collection independently. Omit for the default of 50." - added
Input schema / properties / project / descriptionAdded value: +"Project namespace. Defaults to \"default\"; an empty string is rejected." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "The working set for one project.", + "properties": { + "activeDecisions": { + "description": "Decisions in a current, actionable state: proposed, planned, in_progress, executed, validated, or reconsidered.", + "items": { + "description": "A stored decision, including its alternatives and auditable confidence basis.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "alternatives": { + "description": "Rejected alternatives, each with id, label, reasonRejected, status, and the reopenWhen rules that make it reconsiderable.", + "type": "array" + }, + "assumptions": { + "description": "Assumptions the decision rests on. Searchable content.", + "items": { + "type": "string" + }, + "type": "array" + }, + "chosen": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The option that was chosen." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "confidence": { + "description": "Auditable confidence: initial, current (0-1), policy, a history entry per move, and a basis summarising the contributions it was folded from. Legacy records may lack basis.", + "type": "object" + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "evidence": { + "description": "Normalised evidence entries: source, type, sourceClass, confidence, observedAt, detail.", + "type": "array" + }, + "failedAttempts": { + "description": "Attempt identifiers or notes attached to this decision.", + "type": "array" + }, + "goal": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "What the decision was trying to achieve." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "migration": { + "description": "Present only on migrated records; records the legacy value a field was mapped from.", + "type": "object" + }, + "outcome": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The recorded outcome, or null until one is recorded." + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "reviewAfter": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 instant after which shadowgraph_maintain marks this decision stale." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Lifecycle state. Legacy records may carry a value this build does not recognise; shadowgraph_validate reports those." + }, + "supersededBy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the decision that replaced this one." + }, + "supersedes": { + "description": "Identifiers of decisions this one replaced.", + "type": "array" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Short name of the decision." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + } + }, + "required": [ + "id", + "kind" + ], + "type": "object" + }, + "type": "array" + }, + "completeness": { + "description": "Per-collection completeness. context returns five named collections, so one page object cannot describe it.", + "properties": { + "collections": { + "description": "One entry per returned collection.", + "properties": { + "activeDecisions": { + "description": "Counts for activeDecisions.", + "properties": { + "hasMore": { + "description": "True when this collection was truncated.", + "type": "boolean" + }, + "omitted": { + "description": "total minus returned for this collection.", + "minimum": 0, + "type": "integer" + }, + "returned": { + "description": "Items returned for this collection.", + "minimum": 0, + "type": "integer" + }, + "total": { + "description": "Items that matched for this collection.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "returned", + "total", + "hasMore", + "omitted" + ], + "type": "object" + }, + "failedAttemptsToAvoid": { + "description": "Counts for failedAttemptsToAvoid.", + "properties": { + "hasMore": { + "description": "True when this collection was truncated.", + "type": "boolean" + }, + "omitted": { + "description": "total minus returned for this collection.", + "minimum": 0, + "type": "integer" + }, + "returned": { + "description": "Items returned for this collection.", + "minimum": 0, + "type": "integer" + }, + "total": { + "description": "Items that matched for this collection.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "returned", + "total", + "hasMore", + "omitted" + ], + "type": "object" + }, + "openReviews": { + "description": "Counts for openReviews.", + "properties": { + "hasMore": { + "description": "True when this collection was truncated.", + "type": "boolean" + }, + "omitted": { + "description": "total minus returned for this collection.", + "minimum": 0, + "type": "integer" + }, + "returned": { + "description": "Items returned for this collection.", + "minimum": 0, + "type": "integer" + }, + "total": { + "description": "Items that matched for this collection.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "returned", + "total", + "hasMore", + "omitted" + ], + "type": "object" + }, + "staleAssumptions": { + "description": "Counts for staleAssumptions.", + "properties": { + "hasMore": { + "description": "True when this collection was truncated.", + "type": "boolean" + }, + "omitted": { + "description": "total minus returned for this collection.", + "minimum": 0, + "type": "integer" + }, + "returned": { + "description": "Items returned for this collection.", + "minimum": 0, + "type": "integer" + }, + "total": { + "description": "Items that matched for this collection.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "returned", + "total", + "hasMore", + "omitted" + ], + "type": "object" + }, + "suggestedQuestions": { + "description": "Counts for suggestedQuestions.", + "properties": { + "hasMore": { + "description": "True when this collection was truncated.", + "type": "boolean" + }, + "omitted": { + "description": "total minus returned for this collection.", + "minimum": 0, + "type": "integer" + }, + "returned": { + "description": "Items returned for this collection.", + "minimum": 0, + "type": "integer" + }, + "total": { + "description": "Items that matched for this collection.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "returned", + "total", + "hasMore", + "omitted" + ], + "type": "object" + } + }, + "required": [ + "activeDecisions", + "staleAssumptions", + "failedAttemptsToAvoid", + "openReviews", + "suggestedQuestions" + ], + "type": "object" + }, + "complete": { + "description": "True only when no collection was truncated.", + "type": "boolean" + }, + "limitSource": { + "description": "Whose choice bounded the collections.", + "enum": [ + "caller", + "default" + ], + "type": "string" + }, + "losslessItems": { + "description": "Always true: items are full records, never summaries.", + "type": "boolean" + }, + "scope": { + "description": "The project this result covers.", + "type": "object" + } + }, + "required": [ + "scope", + "complete", + "limitSource", + "losslessItems", + "collections" + ], + "type": "object" + }, + "failedAttemptsToAvoid": { + "description": "Attempts whose result mentions failure, regression, or error.", + "items": { + "description": "A stored attempt and its result.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "environment": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Where it was tried." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why it turned out that way." + }, + "relatedTo": { + "description": "Identifiers of related entities.", + "type": "array" + }, + "result": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "What happened." + }, + "reusableWhen": { + "description": "Conditions under which the attempt is worth repeating.", + "type": "array" + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "solution": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "What was tried." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + } + }, + "required": [ + "id", + "kind" + ], + "type": "object" + }, + "type": "array" + }, + "openReviews": { + "description": "Decisions currently due for reconsideration.", + "items": { + "description": "One decision whose rejected alternatives are due for reconsideration.", + "properties": { + "alternativesToReconsider": { + "description": "Labels of the alternatives to look at again; all of them when the trigger was not alternative-specific.", + "items": { + "type": "string" + }, + "type": "array" + }, + "decisionId": { + "description": "The decision to reconsider.", + "type": "string" + }, + "reason": { + "description": "Comma-separated causes: the fact keys whose reopenWhen rules matched, \"review date reached\", or \"decision outcome failed\".", + "type": "string" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Decision title, when the stored decision has one." + } + }, + "required": [ + "decisionId", + "reason", + "alternativesToReconsider" + ], + "type": "object" + }, + "type": "array" + }, + "project": { + "description": "The project this context describes.", + "type": "string" + }, + "staleAssumptions": { + "description": "Facts that are no longer active, such as superseded or expired ones, which earlier decisions may still rest on.", + "items": { + "description": "A stored fact with its provenance claim and validity window.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "confidence": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Caller-declared confidence in the observation, 0-1." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "expiresAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Caller-declared expiry instant, or null." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Fact name, unique per project among active facts." + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "observedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time the fact was observed." + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Legacy alias of sourceClass, retained for compatibility." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "active, superseded, or expired." + }, + "temporal": { + "description": "Bi-temporal window: validFrom, validTo, recordedAt, invalidatedAt.", + "type": "object" + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + }, + "validityPolicy": { + "description": "Declared expiry inputs and the effective expiration boundary derived from them.", + "type": "object" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "The observed value, any lossless JSON value." + }, + "verification": { + "description": "Present only on a signed verification: the attestation this build checked.", + "type": "object" + }, + "verificationStatus": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "unverified, contradicted, expired, or verified. Only the separately configured signed-evidence verifier can produce verified." + } + }, + "required": [ + "key" + ], + "type": "object" + }, + "type": "array" + }, + "suggestedQuestions": { + "description": "Questions for the low-confidence decisions in this project.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "project", + "activeDecisions", + "staleAssumptions", + "failedAttemptsToAvoid", + "openReviews", + "suggestedQuestions", + "completeness" + ], + "type": "object" +}
- Changed
shadowgraph_journal4 fields changed- changed
Input schema / properties / limit / descriptionPrevious value: -"Page size. Omitted means a declared default, never silent truncation."New value: +"Maximum items to return, 1-1000; the default is 50 and completeness.limitSource reports which applied. Out of range is rejected, never silently clamped." - changed
Input schema / properties / offset / descriptionPrevious value: -"Page offset."New value: +"Items to skip before this window. Ordering is total and deterministic, so paging cannot drop or duplicate an item." - added
Input schema / properties / project / descriptionAdded value: +"Return only entries recorded for this project. Omit for every project, including entries with no project." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Journal entries with pagination, replay boundary, and declared gaps.", + "properties": { + "completeness": { + "description": "Declares exactly what this response left out, so a truncated result can never look complete.", + "properties": { + "complete": { + "description": "True only when every matching item is present.", + "type": "boolean" + }, + "gaps": { + "description": "Sequence ranges missing from the journal, each { from, to }. A hard purge legitimately creates one; it is declared, not hidden.", + "items": { + "properties": { + "from": { + "description": "First missing sequence.", + "type": "integer" + }, + "to": { + "description": "Last missing sequence.", + "type": "integer" + } + }, + "type": "object" + }, + "type": "array" + }, + "journalEpoch": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "First replayable sequence, or null when nothing is replayable." + }, + "journalSeq": { + "description": "Highest sequence issued so far.", + "type": "integer" + }, + "limitSource": { + "description": "Whose choice bounded the result.", + "enum": [ + "caller", + "default" + ], + "type": "string" + }, + "losslessItems": { + "description": "Always true: each returned item is a full-fidelity record, never a summary or a truncated field.", + "type": "boolean" + }, + "omitted": { + "description": "total minus returned.", + "minimum": 0, + "type": "integer" + }, + "returned": { + "description": "Items in this response.", + "minimum": 0, + "type": "integer" + }, + "scope": { + "description": "The project, query, and structured filters that produced this result, so it explains its own derivation.", + "type": "object" + }, + "total": { + "description": "Items that matched in total.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "scope", + "returned", + "total", + "complete", + "omitted", + "losslessItems", + "limitSource", + "journalEpoch", + "journalSeq", + "gaps" + ], + "type": "object" + }, + "items": { + "description": "The items in this window, in deterministic order.", + "items": { + "description": "One journal entry: a complete post-operation snapshot. Entries imported from older schemas may lack seq or payload.", + "properties": { + "at": { + "description": "ISO 8601 time the entry was appended.", + "type": "string" + }, + "causationId": { + "description": "Present only when this entry was caused by another; carries that entry id.", + "type": "string" + }, + "entityId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of that entity; null on a redacted skeleton." + }, + "entityKind": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Kind of the entity the entry is about." + }, + "id": { + "description": "Entry identifier.", + "type": "string" + }, + "idempotencyKey": { + "description": "Present only when the write carried a retry key.", + "type": "string" + }, + "payload": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The complete post-operation snapshot, or null once a logical purge reduced the entry to an audit skeleton." + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project the entry belongs to." + }, + "provenance": { + "description": "actor, client, and sessionId recorded with the write; all null on purged skeletons.", + "type": "object" + }, + "redacted": { + "description": "Present only on entries reduced by a logical purge.", + "type": "boolean" + }, + "redactedReason": { + "description": "Why the entry was reduced.", + "type": "string" + }, + "schemaVersion": { + "description": "Schema version the entry was written under.", + "type": "integer" + }, + "seq": { + "description": "Monotonic sequence number. Absent on pre-journal metadata entries.", + "type": "integer" + }, + "transition": { + "description": "Present only on lifecycle changes; carries from, to, and the actor that made them.", + "type": "object" + }, + "type": { + "description": "Entry type, such as decision.recorded, fact.observed, memory.superseded, or project.purged.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "page": { + "description": "The window actually applied to the matching items.", + "properties": { + "hasMore": { + "description": "True when matching items exist beyond this window.", + "type": "boolean" + }, + "limit": { + "description": "Window size applied, whether the caller set it or the default did.", + "minimum": 1, + "type": "integer" + }, + "offset": { + "description": "Index of the first item returned.", + "minimum": 0, + "type": "integer" + }, + "total": { + "description": "Matching items before the window was applied.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "offset", + "limit", + "total", + "hasMore" + ], + "type": "object" + } + }, + "required": [ + "items", + "page", + "completeness" + ], + "type": "object" +}
- Changed
shadowgraph_link4 fields changed- added
Input schema / properties / from / descriptionAdded value: +"Source entity id. Must already exist: a decision, attempt, memory, fact, or alternative." - added
Input schema / properties / relation / descriptionAdded value: +"Relationship name, chosen by the caller and stored verbatim, such as depends_on, contradicts, or informs. It is what shadowgraph_traverse filters and explains hits by, so keep names consistent." - added
Input schema / properties / to / descriptionAdded value: +"Target entity id. Must already exist." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "The relationship that was created.", + "properties": { + "createdAt": { + "description": "ISO 8601 creation time.", + "type": "string" + }, + "from": { + "description": "Source entity identifier.", + "type": "string" + }, + "id": { + "description": "Identifier minted for this relationship. A new one on every call.", + "type": "string" + }, + "kind": { + "const": "relation", + "description": "Always \"relation\".", + "type": "string" + }, + "relation": { + "description": "Relationship name as supplied.", + "type": "string" + }, + "schemaVersion": { + "description": "Storage schema version.", + "type": "integer" + }, + "temporal": { + "description": "Bi-temporal window: validFrom, validTo, recordedAt, invalidatedAt.", + "type": "object" + }, + "to": { + "description": "Target entity identifier.", + "type": "string" + } + }, + "required": [ + "id", + "kind", + "schemaVersion", + "from", + "to", + "relation", + "createdAt", + "temporal" + ], + "type": "object" +}
- Changed
shadowgraph_maintain5 fields changed- added
Input schema / properties / changedFacts / descriptionAdded value: +"Fact keys that just changed. Only string-form reopenWhen rules match this list; it is an ephemeral signal, not durable state." - added
Input schema / properties / changedFacts / itemsAdded value: +{ + "type": "string" +} - added
Input schema / properties / facts / descriptionAdded value: +"Fact key/value overrides evaluated instead of the stored facts of the same key. Stored facts are used for every key not listed here, so reopen rules still work after a restart." - added
Input schema / properties / now / descriptionAdded value: +"ISO 8601 instant to treat as the current time. Defaults to the real clock; supplying it makes the run deterministic." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "What maintenance changed and what is now due.", + "properties": { + "agedDecisionIds": { + "description": "Compatibility alias of staleDecisionIds for older callers.", + "items": { + "type": "string" + }, + "type": "array" + }, + "at": { + "description": "The instant maintenance ran against.", + "type": "string" + }, + "due": { + "description": "Decisions due for reconsideration after the run.", + "items": { + "description": "One decision whose rejected alternatives are due for reconsideration.", + "properties": { + "alternativesToReconsider": { + "description": "Labels of the alternatives to look at again; all of them when the trigger was not alternative-specific.", + "items": { + "type": "string" + }, + "type": "array" + }, + "decisionId": { + "description": "The decision to reconsider.", + "type": "string" + }, + "reason": { + "description": "Comma-separated causes: the fact keys whose reopenWhen rules matched, \"review date reached\", or \"decision outcome failed\".", + "type": "string" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Decision title, when the stored decision has one." + } + }, + "required": [ + "decisionId", + "reason", + "alternativesToReconsider" + ], + "type": "object" + }, + "type": "array" + }, + "reviewSignals": { + "description": "Every persisted review signal after the run, open and acknowledged alike.", + "items": { + "description": "A persisted review signal.", + "properties": { + "acknowledgedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the most recent acknowledgement." + }, + "alternativesToReconsider": { + "description": "Alternative labels to look at again.", + "items": { + "type": "string" + }, + "type": "array" + }, + "createdAt": { + "description": "ISO 8601 time the signal was raised.", + "type": "string" + }, + "decisionId": { + "description": "The decision this signal is about.", + "type": "string" + }, + "id": { + "description": "Signal identifier, used by shadowgraph_ack_review.", + "type": "string" + }, + "kind": { + "const": "review", + "description": "Always \"review\".", + "type": "string" + }, + "reason": { + "description": "Why the signal was raised. Together with decisionId this is the dedupe identity, so the same cause never raises a second signal.", + "type": "string" + }, + "status": { + "description": "open until acknowledged.", + "enum": [ + "open", + "acknowledged" + ], + "type": "string" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Decision title, when the stored decision has one." + } + }, + "required": [ + "id", + "kind", + "decisionId", + "reason", + "alternativesToReconsider", + "status", + "createdAt" + ], + "type": "object" + }, + "type": "array" + }, + "staleDecisionIds": { + "description": "Decisions moved to stale because they passed reviewAfter.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "at", + "staleDecisionIds", + "agedDecisionIds", + "reviewSignals", + "due" + ], + "type": "object" +}
- Changed
shadowgraph_purge3 fields changed- changed
Input schema / properties / mode / descriptionPrevious value: -"Defaults to logical. `hard` is irreversible and removes audit history."New value: +"Defaults to logical, which keeps an auditable payload-free journal skeleton. \"hard\" is irreversible, physically removes journal entries, and leaves a sequence gap that validate() reports." - added
Input schema / properties / project / descriptionAdded value: +"Project to delete. Required and non-empty; there is no wildcard." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "What the purge removed.", + "properties": { + "events": { + "description": "Compatibility events that were present.", + "minimum": 0, + "type": "integer" + }, + "facts": { + "description": "Facts that were present.", + "minimum": 0, + "type": "integer" + }, + "idempotencyRemoved": { + "description": "Retry keys removed with the project.", + "minimum": 0, + "type": "integer" + }, + "journal": { + "description": "Journal entries that were present for the project.", + "minimum": 0, + "type": "integer" + }, + "journalEntriesRedacted": { + "description": "Entries reduced to an audit skeleton by a logical purge.", + "minimum": 0, + "type": "integer" + }, + "journalEntriesRemoved": { + "description": "Entries physically deleted by a hard purge.", + "minimum": 0, + "type": "integer" + }, + "journalEntryId": { + "description": "Id of the project.purged entry that records this purge.", + "type": "string" + }, + "mode": { + "description": "The mode that was applied.", + "enum": [ + "logical", + "hard" + ], + "type": "string" + }, + "project": { + "description": "The project that was purged.", + "type": "string" + }, + "records": { + "description": "Decisions, attempts, and memories that were present.", + "minimum": 0, + "type": "integer" + }, + "relations": { + "description": "Relationships that were present.", + "minimum": 0, + "type": "integer" + }, + "removed": { + "description": "Entities removed from live state, including alternatives.", + "minimum": 0, + "type": "integer" + }, + "removedJournalSequences": { + "description": "Sequence numbers a hard purge removed, declared so the resulting gap is explained rather than hidden.", + "items": { + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "project", + "records", + "facts", + "relations", + "events", + "journal", + "removed", + "mode", + "journalEntriesRedacted", + "journalEntriesRemoved", + "removedJournalSequences", + "idempotencyRemoved", + "journalEntryId" + ], + "type": "object" +}
- Changed
shadowgraph_purge_preview2 fields changed- added
Input schema / properties / project / descriptionAdded value: +"Project name to preview, matched exactly. Required and non-empty." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "What a purge of this project would remove.", + "properties": { + "events": { + "description": "Compatibility events for the project.", + "minimum": 0, + "type": "integer" + }, + "facts": { + "description": "Facts in the project.", + "minimum": 0, + "type": "integer" + }, + "journal": { + "description": "Journal entries recorded for the project.", + "minimum": 0, + "type": "integer" + }, + "project": { + "description": "The project that was previewed.", + "type": "string" + }, + "records": { + "description": "Decisions, attempts, and memories in the project.", + "minimum": 0, + "type": "integer" + }, + "relations": { + "description": "Relationships touching the project.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "project", + "records", + "facts", + "relations", + "events", + "journal" + ], + "type": "object" +}
- Changed
shadowgraph_rebuild2 fields changed- changed
Input schema / properties / requireFullHistory / descriptionPrevious value: -"When true, refuse to rebuild if pre-journal metadata-only entries exist."New value: +"When true, refuse to rebuild if pre-journal metadata-only entries exist, returning rebuildable:false instead of a fold that silently starts later. Defaults to false." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "The rebuild report and the projection it produced.", + "properties": { + "applied": { + "description": "Entries folded into the projection.", + "minimum": 0, + "type": "integer" + }, + "duplicates": { + "description": "Sequence numbers appearing more than once, each { seq, count }. A repeated sequence cannot be totally ordered, so it makes the fold untrustworthy.", + "type": "array" + }, + "journalEpoch": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "First replayable sequence." + }, + "legacy": { + "description": "Entries recognised as pre-journal or non-replayable, each with a why.", + "type": "array" + }, + "ok": { + "description": "True when the fold ran; it does not by itself mean the projection is complete.", + "type": "boolean" + }, + "projection": { + "description": "The projection folded from the journal.", + "properties": { + "facts": { + "description": "Facts reconstructed by the fold.", + "items": { + "description": "A stored fact with its provenance claim and validity window.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "confidence": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Caller-declared confidence in the observation, 0-1." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "expiresAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Caller-declared expiry instant, or null." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Fact name, unique per project among active facts." + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "observedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time the fact was observed." + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Legacy alias of sourceClass, retained for compatibility." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "active, superseded, or expired." + }, + "temporal": { + "description": "Bi-temporal window: validFrom, validTo, recordedAt, invalidatedAt.", + "type": "object" + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + }, + "validityPolicy": { + "description": "Declared expiry inputs and the effective expiration boundary derived from them.", + "type": "object" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "The observed value, any lossless JSON value." + }, + "verification": { + "description": "Present only on a signed verification: the attestation this build checked.", + "type": "object" + }, + "verificationStatus": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "unverified, contradicted, expired, or verified. Only the separately configured signed-evidence verifier can produce verified." + } + }, + "required": [ + "key" + ], + "type": "object" + }, + "type": "array" + }, + "idempotency": { + "description": "Retry-key entries reconstructed by the fold.", + "type": "array" + }, + "records": { + "description": "Decisions, attempts, and memories reconstructed by the fold.", + "items": { + "description": "One stored entity: a decision, attempt, memory, fact, or alternative. Fields vary by kind, and an entity imported from an older schema may carry fewer of them.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + } + }, + "type": "object" + }, + "type": "array" + }, + "relations": { + "description": "Relationships reconstructed by the fold.", + "items": { + "description": "A stored relationship between two entities.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "from": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Source entity identifier." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "relation": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Relationship name, such as depends_on or supersedes." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "temporal": { + "description": "Bi-temporal window for the relationship.", + "type": "object" + }, + "to": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Target entity identifier." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + } + }, + "required": [ + "id", + "from", + "to", + "relation" + ], + "type": "object" + }, + "type": "array" + }, + "schemaVersion": { + "description": "Schema version of the rebuilt projection.", + "type": "integer" + } + }, + "required": [ + "schemaVersion", + "records", + "facts", + "relations", + "idempotency" + ], + "type": "object" + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why the projection is not rebuildable, or null when it is." + }, + "rebuildable": { + "description": "True only when every entry in the replay range was folded and the result is trustworthy.", + "type": "boolean" + }, + "replayedFrom": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Lowest sequence folded." + }, + "replayedTo": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Highest sequence folded." + }, + "skipped": { + "description": "Entries not folded, each carrying seq, type, and a stable why such as unknown_entry_type or unsupported_schema_version.", + "type": "array" + } + }, + "required": [ + "ok", + "rebuildable", + "reason", + "projection", + "journalEpoch", + "replayedFrom", + "replayedTo", + "applied", + "skipped", + "legacy", + "duplicates" + ], + "type": "object" +}
- Changed
shadowgraph_recall14 fields changed- added
Input schema / properties / asOf / descriptionAdded value: +"ISO 8601 instant to select by valid time, returning what was true then rather than now. Also enables temporal ranking." - added
Input schema / properties / focalId / descriptionAdded value: +"Entity id to measure graph distance from. Without it the graph signal reports available:false." - changed
Input schema / properties / limit / descriptionPrevious value: -"Page size. Omitted means a declared default, never silent truncation."New value: +"Maximum items to return, 1-1000; the default is 50 and completeness.limitSource reports which applied. Out of range is rejected, never silently clamped." - added
Input schema / properties / memoryType / descriptionAdded value: +"Restrict memory candidates to this type." - changed
Input schema / properties / offset / descriptionPrevious value: -"Page offset."New value: +"Items to skip before this window. Ordering is total and deterministic, so paging cannot drop or duplicate an item." - added
Input schema / properties / preferRecent / descriptionAdded value: +"Enable temporal ranking against now. Ignored when asOf is supplied, which already selects a point in time." - added
Input schema / properties / project / descriptionAdded value: +"Project to recall from. Defaults to \"default\" for memory records rather than meaning all projects." - added
Input schema / properties / query / descriptionAdded value: +"Free text to rank against. An empty query still returns scope-matching records ranked by the remaining signals." - changed
Input schema / properties / queryEmbedding / descriptionPrevious value: -"Optional caller-supplied vector. When omitted, the configured embedding provider is used."New value: +"Caller-supplied query vector. Omit to use the configured provider; with neither, the semantic signal reports available:false and a reason." - added
Input schema / properties / scope / descriptionAdded value: +"Scope selector. Omitted or partial fields mean explicit nulls, not \"any\": identity is the exact (project, userId, agentId, runId, memoryType, key) tuple, so a run-scoped memory never leaks into a user-only read." - added
Input schema / properties / scope / properties / agentId / descriptionAdded value: +"Agent this memory belongs to, or null for none." - added
Input schema / properties / scope / properties / runId / descriptionAdded value: +"Single run or task this memory belongs to, or null for none." - added
Input schema / properties / scope / properties / userId / descriptionAdded value: +"Person this memory belongs to, or null for none." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Fused results with a per-signal explanation of how they were ranked.", + "properties": { + "completeness": { + "description": "Declares exactly what this response left out, so a truncated result can never look complete.", + "properties": { + "complete": { + "description": "True only when every matching item is present.", + "type": "boolean" + }, + "limitSource": { + "description": "Whose choice bounded the result.", + "enum": [ + "caller", + "default" + ], + "type": "string" + }, + "losslessItems": { + "description": "Always true: each returned item is a full-fidelity record, never a summary or a truncated field.", + "type": "boolean" + }, + "omitted": { + "description": "total minus returned.", + "minimum": 0, + "type": "integer" + }, + "ranking": { + "description": "How the per-signal lists were fused.", + "properties": { + "k": { + "description": "Reciprocal rank fusion constant.", + "type": "number" + }, + "strategy": { + "description": "Fusion strategy identifier, currently weighted_rrf.", + "type": "string" + }, + "weights": { + "description": "Per-signal weights applied during fusion.", + "type": "object" + } + }, + "required": [ + "strategy", + "k", + "weights" + ], + "type": "object" + }, + "returned": { + "description": "Items in this response.", + "minimum": 0, + "type": "integer" + }, + "scope": { + "description": "The project, query, and structured filters that produced this result, so it explains its own derivation.", + "type": "object" + }, + "signals": { + "description": "Authoritative per-signal availability. A signal that could not run says so instead of being silently dropped or renamed.", + "properties": { + "graph": { + "description": "Graph-distance ranking from focalId.", + "properties": { + "available": { + "description": "Whether this signal could contribute at all.", + "type": "boolean" + }, + "matched": { + "description": "Candidates this signal contributed.", + "minimum": 0, + "type": "integer" + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why the signal was unavailable, when it was." + } + }, + "required": [ + "available", + "matched", + "reason" + ], + "type": "object" + }, + "lexical": { + "description": "BM25-style lexical matching over declared content.", + "properties": { + "available": { + "description": "True when the query contained terms.", + "type": "boolean" + }, + "matched": { + "description": "Candidates the lexical list contributed.", + "minimum": 0, + "type": "integer" + }, + "terms": { + "description": "The query terms that were used.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "available", + "matched", + "terms" + ], + "type": "object" + }, + "semantic": { + "description": "Cosine vector matching. available is false when no compatible query vector or provider existed; the result is then lexical, graph, and temporal only.", + "properties": { + "available": { + "description": "Whether this signal could contribute at all.", + "type": "boolean" + }, + "matched": { + "description": "Candidates this signal contributed.", + "minimum": 0, + "type": "integer" + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why the signal was unavailable, when it was." + } + }, + "required": [ + "available", + "matched", + "reason" + ], + "type": "object" + }, + "temporal": { + "description": "Recency ranking from asOf or preferRecent.", + "properties": { + "asOf": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The point in time selection was made against, or null for now." + }, + "available": { + "description": "Whether recency ranking ran.", + "type": "boolean" + }, + "matched": { + "description": "Candidates the temporal list contributed.", + "minimum": 0, + "type": "integer" + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why recency ranking did not run, when it did not." + } + }, + "required": [ + "available", + "matched", + "reason", + "asOf" + ], + "type": "object" + } + }, + "required": [ + "lexical", + "semantic", + "graph", + "temporal" + ], + "type": "object" + }, + "total": { + "description": "Items that matched in total.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "scope", + "returned", + "total", + "complete", + "omitted", + "losslessItems", + "limitSource", + "signals", + "ranking" + ], + "type": "object" + }, + "items": { + "description": "The items in this window, in deterministic order.", + "items": { + "description": "One recalled record with its per-signal explanation.", + "properties": { + "ranks": { + "description": "Position this item held in each signal list, counting from 1, or null where that signal did not rank it.", + "properties": { + "graph": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Position in the graph-distance list; null when no focalId was supplied." + }, + "lexical": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Position in the BM25-style lexical list." + }, + "semantic": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Position in the vector list; null when no compatible query vector or provider existed." + }, + "temporal": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Position in the recency list; null when neither asOf nor preferRecent was supplied." + } + }, + "required": [ + "lexical", + "semantic", + "graph", + "temporal" + ], + "type": "object" + }, + "reasons": { + "description": "One entry per contributing signal, naming the rank it contributed.", + "items": { + "type": "string" + }, + "type": "array" + }, + "record": { + "description": "One stored entity: a decision, attempt, memory, fact, or alternative. Fields vary by kind, and an entity imported from an older schema may carry fewer of them.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + } + }, + "type": "object" + }, + "score": { + "description": "Fused score.", + "type": "number" + }, + "scores": { + "description": "The raw value behind each rank, or null where that signal did not rank this item.", + "properties": { + "graph": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Hop distance from focalId." + }, + "lexical": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "BM25-style lexical score." + }, + "semantic": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Cosine similarity between the query vector and the stored vector." + }, + "temporal": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The ISO 8601 validFrom or recordedAt instant recency ordering used, not a number." + } + }, + "required": [ + "lexical", + "semantic", + "graph", + "temporal" + ], + "type": "object" + } + }, + "required": [ + "record", + "score", + "ranks", + "scores", + "reasons" + ], + "type": "object" + }, + "type": "array" + }, + "page": { + "description": "The window actually applied to the matching items.", + "properties": { + "hasMore": { + "description": "True when matching items exist beyond this window.", + "type": "boolean" + }, + "limit": { + "description": "Window size applied, whether the caller set it or the default did.", + "minimum": 1, + "type": "integer" + }, + "offset": { + "description": "Index of the first item returned.", + "minimum": 0, + "type": "integer" + }, + "total": { + "description": "Matching items before the window was applied.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "offset", + "limit", + "total", + "hasMore" + ], + "type": "object" + } + }, + "required": [ + "items", + "page", + "completeness" + ], + "type": "object" +}
- Changed
shadowgraph_record_attempt11 fields changed- changed
Input schema / properties / actor / descriptionPrevious value: -"Who performed this write, e.g. an agent name."New value: +"Who performed this write, such as an agent or person name. Stored for audit; never used to grant trust." - changed
Input schema / properties / client / descriptionPrevious value: -"Which client performed this write."New value: +"Which client software performed this write, such as the host application name." - added
Input schema / properties / environment / descriptionAdded value: +"Where it was tried, such as a runtime, OS, or version. Searchable content, so a later attempt can be matched to the same environment." - changed
Input schema / properties / idempotencyKey / descriptionPrevious value: -"Retry key scoped by project and operation; reuse only for the same logical write."New value: +"Retry key scoped by project and operation: reuse it so a retry returns the first result instead of writing a duplicate. Without it every call creates a new entity." - added
Input schema / properties / project / descriptionAdded value: +"Project namespace. Defaults to \"default\"; an empty string is rejected." - added
Input schema / properties / reason / descriptionAdded value: +"Why it turned out that way. Searchable content." - added
Input schema / properties / result / descriptionAdded value: +"What happened. Required, non-empty, and searchable content. Wording such as failed, error, or regression is what makes the attempt surface in shadowgraph_context as one to avoid." - changed
Input schema / properties / sessionId / descriptionPrevious value: -"Session identifier for this write."New value: +"Caller-owned identifier that groups related writes in the audit trail." - added
Input schema / properties / solution / descriptionAdded value: +"What was tried. Required, non-empty, and searchable content." - changed
Input schema / properties / sourceClass / descriptionPrevious value: -"Claimed origin class. A claim, not proof: no value here can make a fact verified."New value: +"Claimed origin, never proof: agent_claimed (the default), tool_observed, human_confirmed, or production_verified. It weights confidence only. An unrecognised label downgrades to agent_claimed, kept verbatim in sourceRaw." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "A stored attempt and its result.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "environment": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Where it was tried." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why it turned out that way." + }, + "relatedTo": { + "description": "Identifiers of related entities.", + "type": "array" + }, + "result": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "What happened." + }, + "reusableWhen": { + "description": "Conditions under which the attempt is worth repeating.", + "type": "array" + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "solution": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "What was tried." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + } + }, + "required": [ + "id", + "kind" + ], + "type": "object" +}
- Changed
shadowgraph_record_decision20 fields changed- changed
Input schema / properties / actor / descriptionPrevious value: -"Who performed this write, e.g. an agent name."New value: +"Who performed this write, such as an agent or person name. Stored for audit; never used to grant trust." - added
Input schema / properties / alternatives / descriptionAdded value: +"Options considered and rejected. Alternatives belong to the decision and have no separate write API; they are what shadowgraph_review reconsiders." - added
Input schema / properties / alternatives / items / properties / label / descriptionAdded value: +"Name of the rejected option. Required in practice: an alternative without a non-empty label is rejected." - added
Input schema / properties / alternatives / items / properties / reason / descriptionAdded value: +"Accepted as an alias of reasonRejected for older callers." - added
Input schema / properties / alternatives / items / properties / reasonRejected / descriptionAdded value: +"Why it was rejected. Searchable content." - added
Input schema / properties / alternatives / items / properties / reopenWhen / descriptionAdded value: +"Rules that make this alternative worth reconsidering. Each is either a fact key as a plain string, matched only against changedFacts, or an object { key, operator, value } evaluated against stored facts so it still fires after a restart. operator defaults to equals." - added
Input schema / properties / assumptions / descriptionAdded value: +"What the decision takes for granted. Record each as a fact too if it should be able to reopen the decision." - added
Input schema / properties / chosen / descriptionAdded value: +"The option actually chosen. Required, non-empty, and searchable content." - changed
Input schema / properties / client / descriptionPrevious value: -"Which client performed this write."New value: +"Which client software performed this write, such as the host application name." - added
Input schema / properties / confidence / descriptionAdded value: +"Starting confidence, 0-1. Defaults to 0.5. Later outcomes and evidence move it from this baseline; it is a degree of belief, never a verification status." - added
Input schema / properties / evidence / descriptionAdded value: +"Supporting evidence. Counted as declared evidence in the confidence basis, but never re-checked." - changed
Input schema / properties / evidence / items / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "additionalProperties": true, - "properties": { - "confidence": { - "maximum": 1, - "minimum": 0, - "type": "number" - }, - "detail": { - "type": "string" - }, - "observedAt": { - "type": "string" - }, - "source": { - "type": "string" - }, - "sourceClass": { - "enum": [ - "agent_claimed", - "tool_observed", - "human_confirmed", - "production_verified" - ], - "type": "string" - }, - "type": { - "type": "string" - } - }, - "type": "object" - } -]New value: +[ + { + "type": "string" + }, + { + "additionalProperties": true, + "properties": { + "confidence": { + "description": "How much weight the caller places on this item, 0-1. Defaults to 0.5.", + "maximum": 1, + "minimum": 0, + "type": "number" + }, + "detail": { + "description": "Free-text detail. Searchable content.", + "type": "string" + }, + "observedAt": { + "description": "ISO 8601 timestamp of the observation. Defaults to the time of the write.", + "type": "string" + }, + "source": { + "description": "Where the evidence came from, such as a document, ticket, or command. Searchable content.", + "type": "string" + }, + "sourceClass": { + "description": "Claimed origin class for this item; an unrecognised value downgrades to agent_claimed.", + "enum": [ + "agent_claimed", + "tool_observed", + "human_confirmed", + "production_verified" + ], + "type": "string" + }, + "type": { + "description": "Free-form evidence kind, such as benchmark, incident, or review.", + "type": "string" + } + }, + "type": "object" + } +] - added
Input schema / properties / evidence / items / descriptionAdded value: +"One piece of supporting evidence. A plain string is stored as its source; an object carries structured provenance. Nothing here is checked or re-verified: it records what the caller claimed." - added
Input schema / properties / goal / descriptionAdded value: +"What the decision is meant to achieve. Searchable content." - changed
Input schema / properties / idempotencyKey / descriptionPrevious value: -"Retry key scoped by project and operation; reuse only for the same logical write."New value: +"Retry key scoped by project and operation: reuse it so a retry returns the first result instead of writing a duplicate. Without it every call creates a new entity." - added
Input schema / properties / project / descriptionAdded value: +"Project namespace. Defaults to \"default\"; an empty string is rejected." - changed
Input schema / properties / sessionId / descriptionPrevious value: -"Session identifier for this write."New value: +"Caller-owned identifier that groups related writes in the audit trail." - changed
Input schema / properties / sourceClass / descriptionPrevious value: -"Claimed origin class. A claim, not proof: no value here can make a fact verified."New value: +"Claimed origin, never proof: agent_claimed (the default), tool_observed, human_confirmed, or production_verified. It weights confidence only. An unrecognised label downgrades to agent_claimed, kept verbatim in sourceRaw." - added
Input schema / properties / title / descriptionAdded value: +"Short name of the decision. Required, non-empty, and searchable content." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "A stored decision, including its alternatives and auditable confidence basis.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "alternatives": { + "description": "Rejected alternatives, each with id, label, reasonRejected, status, and the reopenWhen rules that make it reconsiderable.", + "type": "array" + }, + "assumptions": { + "description": "Assumptions the decision rests on. Searchable content.", + "items": { + "type": "string" + }, + "type": "array" + }, + "chosen": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The option that was chosen." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "confidence": { + "description": "Auditable confidence: initial, current (0-1), policy, a history entry per move, and a basis summarising the contributions it was folded from. Legacy records may lack basis.", + "type": "object" + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "evidence": { + "description": "Normalised evidence entries: source, type, sourceClass, confidence, observedAt, detail.", + "type": "array" + }, + "failedAttempts": { + "description": "Attempt identifiers or notes attached to this decision.", + "type": "array" + }, + "goal": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "What the decision was trying to achieve." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "migration": { + "description": "Present only on migrated records; records the legacy value a field was mapped from.", + "type": "object" + }, + "outcome": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The recorded outcome, or null until one is recorded." + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "reviewAfter": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 instant after which shadowgraph_maintain marks this decision stale." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Lifecycle state. Legacy records may carry a value this build does not recognise; shadowgraph_validate reports those." + }, + "supersededBy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the decision that replaced this one." + }, + "supersedes": { + "description": "Identifiers of decisions this one replaced.", + "type": "array" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Short name of the decision." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + } + }, + "required": [ + "id", + "kind" + ], + "type": "object" +}
- Changed
shadowgraph_record_fact12 fields changed- changed
Input schema / properties / actor / descriptionPrevious value: -"Who performed this write, e.g. an agent name."New value: +"Who performed this write, such as an agent or person name. Stored for audit; never used to grant trust." - changed
Input schema / properties / client / descriptionPrevious value: -"Which client performed this write."New value: +"Which client software performed this write, such as the host application name." - added
Input schema / properties / confidence / descriptionAdded value: +"How much the caller trusts this observation, 0-1. Defaults to 0.5. It does not verify anything." - added
Input schema / properties / expiresAt / descriptionAdded value: +"ISO 8601 instant after which shadowgraph_maintain expires this fact. Combined with validTo, the earlier boundary wins." - changed
Input schema / properties / idempotencyKey / descriptionPrevious value: -"Retry key scoped by project and operation; reuse only for the same logical write."New value: +"Retry key scoped by project and operation: reuse it so a retry returns the first result instead of writing a duplicate. Without it every call creates a new entity." - added
Input schema / properties / key / descriptionAdded value: +"Fact name, unique per project among active facts. Required and non-empty. Use the same key that a decision’s reopenWhen rules refer to." - added
Input schema / properties / project / descriptionAdded value: +"Project namespace. Defaults to \"default\"; an empty string is rejected." - changed
Input schema / properties / sessionId / descriptionPrevious value: -"Session identifier for this write."New value: +"Caller-owned identifier that groups related writes in the audit trail." - changed
Input schema / properties / source / descriptionPrevious value: -"Legacy alias for sourceClass. Unknown labels downgrade to agent_claimed with the raw label kept in sourceRaw."New value: +"Legacy alias for sourceClass. An unknown label downgrades to agent_claimed with the raw label kept in sourceRaw." - changed
Input schema / properties / sourceClass / descriptionPrevious value: -"Claimed origin class. A claim, not proof: no value here can make a fact verified."New value: +"Claimed origin, never proof: agent_claimed (the default), tool_observed, human_confirmed, or production_verified. It weights confidence only. An unrecognised label downgrades to agent_claimed, kept verbatim in sourceRaw." - changed
Input schema / properties / verificationStatus / descriptionPrevious value: -"Only `contradicted` may be set by a caller; `verified` and `expired` are rejected."New value: +"Only \"contradicted\" may be set by a caller, because it lowers trust. \"verified\" and \"expired\" are rejected: verification is not self-assertable and expiry is owned by shadowgraph_maintain." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "A stored fact with its provenance claim and validity window.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "confidence": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Caller-declared confidence in the observation, 0-1." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "expiresAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Caller-declared expiry instant, or null." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Fact name, unique per project among active facts." + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "observedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time the fact was observed." + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Legacy alias of sourceClass, retained for compatibility." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "active, superseded, or expired." + }, + "temporal": { + "description": "Bi-temporal window: validFrom, validTo, recordedAt, invalidatedAt.", + "type": "object" + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + }, + "validityPolicy": { + "description": "Declared expiry inputs and the effective expiration boundary derived from them.", + "type": "object" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "The observed value, any lossless JSON value." + }, + "verification": { + "description": "Present only on a signed verification: the attestation this build checked.", + "type": "object" + }, + "verificationStatus": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "unverified, contradicted, expired, or verified. Only the separately configured signed-evidence verifier can produce verified." + } + }, + "required": [ + "key" + ], + "type": "object" +}
- Changed
shadowgraph_record_outcome7 fields changed- added
Input schema / properties / decisionId / descriptionAdded value: +"Identifier of an existing decision, as returned by shadowgraph_record_decision, shadowgraph_search, or shadowgraph_retrieve." - added
Input schema / properties / outcome / descriptionAdded value: +"The outcome to record." - added
Input schema / properties / outcome / properties / lessons / descriptionAdded value: +"What was learned, stored with the outcome." - added
Input schema / properties / outcome / properties / observedAt / descriptionAdded value: +"ISO 8601 time the outcome was observed. Defaults to now." - added
Input schema / properties / outcome / properties / sourceClass / descriptionAdded value: +"Claimed origin of this outcome observation. It weights how far confidence moves; it never verifies anything." - added
Input schema / properties / outcome / properties / status / descriptionAdded value: +"successful raises confidence, failed lowers it and makes the decision due for review, mixed lowers it by half, and unknown moves nothing because \"we do not know\" is not evidence." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "A stored decision, including its alternatives and auditable confidence basis.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "alternatives": { + "description": "Rejected alternatives, each with id, label, reasonRejected, status, and the reopenWhen rules that make it reconsiderable.", + "type": "array" + }, + "assumptions": { + "description": "Assumptions the decision rests on. Searchable content.", + "items": { + "type": "string" + }, + "type": "array" + }, + "chosen": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The option that was chosen." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "confidence": { + "description": "Auditable confidence: initial, current (0-1), policy, a history entry per move, and a basis summarising the contributions it was folded from. Legacy records may lack basis.", + "type": "object" + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "evidence": { + "description": "Normalised evidence entries: source, type, sourceClass, confidence, observedAt, detail.", + "type": "array" + }, + "failedAttempts": { + "description": "Attempt identifiers or notes attached to this decision.", + "type": "array" + }, + "goal": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "What the decision was trying to achieve." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "migration": { + "description": "Present only on migrated records; records the legacy value a field was mapped from.", + "type": "object" + }, + "outcome": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The recorded outcome, or null until one is recorded." + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "reviewAfter": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 instant after which shadowgraph_maintain marks this decision stale." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Lifecycle state. Legacy records may carry a value this build does not recognise; shadowgraph_validate reports those." + }, + "supersededBy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the decision that replaced this one." + }, + "supersedes": { + "description": "Identifiers of decisions this one replaced.", + "type": "array" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Short name of the decision." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + } + }, + "required": [ + "id", + "kind" + ], + "type": "object" +}
- Changed
shadowgraph_redact3 fields changed- added
Input schema / properties / patterns / descriptionAdded value: +"Case-insensitive regular expressions matched against key names, replacing the default set (password, secret, token, api[-_]?key, authorization, private[-_]?key). Supplying this replaces the defaults rather than adding to them; idempotency keys, evidence references, and signatures are always redacted." - added
Input schema / properties / project / descriptionAdded value: +"Limit the export to one project. Omit to redact everything." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "A complete store export.", + "properties": { + "events": { + "description": "Compatibility event log.", + "type": "array" + }, + "facts": { + "description": "Observed facts with their provenance claims.", + "items": { + "description": "A stored fact with its provenance claim and validity window.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "confidence": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Caller-declared confidence in the observation, 0-1." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "expiresAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Caller-declared expiry instant, or null." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Fact name, unique per project among active facts." + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "observedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time the fact was observed." + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Legacy alias of sourceClass, retained for compatibility." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "active, superseded, or expired." + }, + "temporal": { + "description": "Bi-temporal window: validFrom, validTo, recordedAt, invalidatedAt.", + "type": "object" + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + }, + "validityPolicy": { + "description": "Declared expiry inputs and the effective expiration boundary derived from them.", + "type": "object" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "The observed value, any lossless JSON value." + }, + "verification": { + "description": "Present only on a signed verification: the attestation this build checked.", + "type": "object" + }, + "verificationStatus": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "unverified, contradicted, expired, or verified. Only the separately configured signed-evidence verifier can produce verified." + } + }, + "required": [ + "key" + ], + "type": "object" + }, + "type": "array" + }, + "idempotency": { + "description": "Retry-key entries, each { key, value }.", + "type": "array" + }, + "journal": { + "description": "The append-oriented journal.", + "items": { + "description": "One journal entry: a complete post-operation snapshot. Entries imported from older schemas may lack seq or payload.", + "properties": { + "at": { + "description": "ISO 8601 time the entry was appended.", + "type": "string" + }, + "causationId": { + "description": "Present only when this entry was caused by another; carries that entry id.", + "type": "string" + }, + "entityId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of that entity; null on a redacted skeleton." + }, + "entityKind": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Kind of the entity the entry is about." + }, + "id": { + "description": "Entry identifier.", + "type": "string" + }, + "idempotencyKey": { + "description": "Present only when the write carried a retry key.", + "type": "string" + }, + "payload": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The complete post-operation snapshot, or null once a logical purge reduced the entry to an audit skeleton." + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project the entry belongs to." + }, + "provenance": { + "description": "actor, client, and sessionId recorded with the write; all null on purged skeletons.", + "type": "object" + }, + "redacted": { + "description": "Present only on entries reduced by a logical purge.", + "type": "boolean" + }, + "redactedReason": { + "description": "Why the entry was reduced.", + "type": "string" + }, + "schemaVersion": { + "description": "Schema version the entry was written under.", + "type": "integer" + }, + "seq": { + "description": "Monotonic sequence number. Absent on pre-journal metadata entries.", + "type": "integer" + }, + "transition": { + "description": "Present only on lifecycle changes; carries from, to, and the actor that made them.", + "type": "object" + }, + "type": { + "description": "Entry type, such as decision.recorded, fact.observed, memory.superseded, or project.purged.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "journalEpoch": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "First replayable sequence, or null when nothing is replayable." + }, + "journalSeq": { + "description": "Highest journal sequence issued.", + "type": "integer" + }, + "records": { + "description": "Decisions, attempts, and memories.", + "items": { + "description": "One stored entity: a decision, attempt, memory, fact, or alternative. Fields vary by kind, and an entity imported from an older schema may carry fewer of them.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + } + }, + "type": "object" + }, + "type": "array" + }, + "relations": { + "description": "Relationships.", + "items": { + "description": "A stored relationship between two entities.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "from": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Source entity identifier." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "relation": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Relationship name, such as depends_on or supersedes." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "temporal": { + "description": "Bi-temporal window for the relationship.", + "type": "object" + }, + "to": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Target entity identifier." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + } + }, + "required": [ + "id", + "from", + "to", + "relation" + ], + "type": "object" + }, + "type": "array" + }, + "reviewSignals": { + "description": "Persisted review signals.", + "items": { + "description": "A persisted review signal.", + "properties": { + "acknowledgedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the most recent acknowledgement." + }, + "alternativesToReconsider": { + "description": "Alternative labels to look at again.", + "items": { + "type": "string" + }, + "type": "array" + }, + "createdAt": { + "description": "ISO 8601 time the signal was raised.", + "type": "string" + }, + "decisionId": { + "description": "The decision this signal is about.", + "type": "string" + }, + "id": { + "description": "Signal identifier, used by shadowgraph_ack_review.", + "type": "string" + }, + "kind": { + "const": "review", + "description": "Always \"review\".", + "type": "string" + }, + "reason": { + "description": "Why the signal was raised. Together with decisionId this is the dedupe identity, so the same cause never raises a second signal.", + "type": "string" + }, + "status": { + "description": "open until acknowledged.", + "enum": [ + "open", + "acknowledged" + ], + "type": "string" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Decision title, when the stored decision has one." + } + }, + "required": [ + "id", + "kind", + "decisionId", + "reason", + "alternativesToReconsider", + "status", + "createdAt" + ], + "type": "object" + }, + "type": "array" + }, + "revision": { + "description": "Concurrency token of the state this export was taken from.", + "type": "integer" + }, + "schemaVersion": { + "description": "Storage schema version of this export.", + "type": "integer" + } + }, + "required": [ + "schemaVersion", + "revision", + "records", + "facts", + "relations", + "reviewSignals", + "idempotency", + "events", + "journal", + "journalSeq", + "journalEpoch" + ], + "type": "object" +}
- Changed
shadowgraph_remember32 fields changed- changed
Input schema / properties / actor / descriptionPrevious value: -"Who performed this write, e.g. an agent name."New value: +"Who performed this write, such as an agent or person name. Stored for audit; never used to grant trust." - changed
Input schema / properties / client / descriptionPrevious value: -"Which client performed this write."New value: +"Which client software performed this write, such as the host application name." - changed
Input schema / properties / embedding / descriptionPrevious value: -"Optional caller-supplied vector. When omitted, the configured embedding provider is used."New value: +"Caller-supplied vector for this text. Omit to use the configured embedding provider; with no provider the record is still stored and recall reports semantic.available=false instead of renaming lexical overlap as semantic." - added
Input schema / properties / key / descriptionAdded value: +"Stable caller-chosen name within this scope and type, such as hotel-style. Reusing it reconciles that memory rather than adding a second one." - added
Input schema / properties / memoryType / descriptionAdded value: +"Which kind of memory this is, and part of its identity. preference and profile are durable user facts, goal a desired state, instruction an operating constraint, procedure reusable steps, episode a recallable event, note general knowledge." - added
Input schema / properties / metadata / descriptionAdded value: +"Caller-owned JSON object kept with the memory. Part of the compared content, so changing it produces a new version." - added
Input schema / properties / operations / descriptionAdded value: +"A batch plan. Supply this instead of a single memory, typically from an extraction step. Every operation is validated before the first one is applied, so a malformed late operation cannot leave a half-applied batch." - added
Input schema / properties / operations / items / properties / action / descriptionAdded value: +"ADD and UPDATE both reconcile against the current memory and require text; DELETE invalidates the current one, keeping history; NOOP records that nothing should change." - changed
Input schema / properties / operations / items / properties / embedding / descriptionPrevious value: -"Optional caller-supplied vector. When omitted, the configured embedding provider is used."New value: +"Caller-supplied vector for this text. Omit to use the configured embedding provider; with no provider the record is still stored and recall reports semantic.available=false instead of renaming lexical overlap as semantic." - added
Input schema / properties / operations / items / properties / key / descriptionAdded value: +"Stable caller-chosen name within this scope and type, such as hotel-style. Reusing it reconciles that memory rather than adding a second one." - added
Input schema / properties / operations / items / properties / memoryType / descriptionAdded value: +"Which kind of memory this is, and part of its identity. preference and profile are durable user facts, goal a desired state, instruction an operating constraint, procedure reusable steps, episode a recallable event, note general knowledge." - added
Input schema / properties / operations / items / properties / metadata / descriptionAdded value: +"Caller-owned JSON object kept with the memory. Part of the compared content, so changing it produces a new version." - added
Input schema / properties / operations / items / properties / scope / descriptionAdded value: +"Scope selector. Omitted or partial fields mean explicit nulls, not \"any\": identity is the exact (project, userId, agentId, runId, memoryType, key) tuple, so a run-scoped memory never leaks into a user-only read." - added
Input schema / properties / operations / items / properties / scope / properties / agentId / descriptionAdded value: +"Agent this memory belongs to, or null for none." - added
Input schema / properties / operations / items / properties / scope / properties / runId / descriptionAdded value: +"Single run or task this memory belongs to, or null for none." - added
Input schema / properties / operations / items / properties / scope / properties / userId / descriptionAdded value: +"Person this memory belongs to, or null for none." - added
Input schema / properties / operations / items / properties / tags / descriptionAdded value: +"Free-form labels stored with the memory. Part of the compared content, so changing them produces a new version." - added
Input schema / properties / operations / items / properties / text / descriptionAdded value: +"The memory content itself. Stored verbatim, searched as content, and compared to decide ADD, UPDATE, or NOOP." - added
Input schema / properties / operations / items / properties / validFrom / descriptionAdded value: +"ISO 8601 instant from which this memory is true in the modeled world. Defaults to the write time. Writes for one identity must arrive in non-decreasing validFrom order." - added
Input schema / properties / operations / items / properties / validTo / descriptionAdded value: +"ISO 8601 instant after which it stops being true, or null for open-ended. Must be later than validFrom." - added
Input schema / properties / project / descriptionAdded value: +"Project namespace. Defaults to \"default\"; an empty string is rejected." - added
Input schema / properties / scope / descriptionAdded value: +"Scope selector. Omitted or partial fields mean explicit nulls, not \"any\": identity is the exact (project, userId, agentId, runId, memoryType, key) tuple, so a run-scoped memory never leaks into a user-only read." - added
Input schema / properties / scope / properties / agentId / descriptionAdded value: +"Agent this memory belongs to, or null for none." - added
Input schema / properties / scope / properties / runId / descriptionAdded value: +"Single run or task this memory belongs to, or null for none." - added
Input schema / properties / scope / properties / userId / descriptionAdded value: +"Person this memory belongs to, or null for none." - changed
Input schema / properties / sessionId / descriptionPrevious value: -"Session identifier for this write."New value: +"Caller-owned identifier that groups related writes in the audit trail." - changed
Input schema / properties / sourceClass / descriptionPrevious value: -"Claimed origin class. A claim, not proof: no value here can make a fact verified."New value: +"Claimed origin, never proof: agent_claimed (the default), tool_observed, human_confirmed, or production_verified. It weights confidence only. An unrecognised label downgrades to agent_claimed, kept verbatim in sourceRaw." - added
Input schema / properties / tags / descriptionAdded value: +"Free-form labels stored with the memory. Part of the compared content, so changing them produces a new version." - added
Input schema / properties / text / descriptionAdded value: +"The memory content itself. Stored verbatim, searched as content, and compared to decide ADD, UPDATE, or NOOP." - added
Input schema / properties / validFrom / descriptionAdded value: +"ISO 8601 instant from which this memory is true in the modeled world. Defaults to the write time. Writes for one identity must arrive in non-decreasing validFrom order." - added
Input schema / properties / validTo / descriptionAdded value: +"ISO 8601 instant after which it stops being true, or null for open-ended. Must be later than validFrom." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "anyOf": [ + { + "properties": { + "indexUpdated": { + "description": "Present when identical content arrived with a different embedding: the index was refreshed without minting a new version.", + "type": "boolean" + }, + "memory": { + "description": "A stored scoped memory version.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "embedding": { + "anyOf": [ + { + "type": "array" + }, + { + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The stored vector, or null when none was supplied and no provider was configured." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Caller-chosen name within the scope and type." + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "memoryType": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "preference, profile, goal, instruction, procedure, episode, or note." + }, + "metadata": { + "description": "Caller-owned JSON stored with the memory.", + "type": "object" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "scope": { + "description": "The userId, agentId, and runId this memory is scoped to; each is a string or null.", + "type": "object" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "active, superseded, or invalidated." + }, + "supersededBy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the version that replaced this one." + }, + "supersedes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the version this one replaced." + }, + "tags": { + "description": "Labels stored with the memory.", + "type": "array" + }, + "temporal": { + "description": "Bi-temporal window: validFrom, validTo, recordedAt, invalidatedAt.", + "type": "object" + }, + "text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The memory content." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + }, + "verificationStatus": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Always unverified for memories." + }, + "version": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Version number within this identity, incrementing on each superseding write." + } + }, + "required": [ + "id", + "kind" + ], + "type": "object" + }, + "operation": { + "description": "ADD when no active memory existed, UPDATE when one was superseded, NOOP when content was identical.", + "enum": [ + "ADD", + "UPDATE", + "NOOP" + ], + "type": "string" + }, + "previous": { + "description": "A stored scoped memory version.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "embedding": { + "anyOf": [ + { + "type": "array" + }, + { + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The stored vector, or null when none was supplied and no provider was configured." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Caller-chosen name within the scope and type." + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "memoryType": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "preference, profile, goal, instruction, procedure, episode, or note." + }, + "metadata": { + "description": "Caller-owned JSON stored with the memory.", + "type": "object" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "scope": { + "description": "The userId, agentId, and runId this memory is scoped to; each is a string or null.", + "type": "object" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "active, superseded, or invalidated." + }, + "supersededBy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the version that replaced this one." + }, + "supersedes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the version this one replaced." + }, + "tags": { + "description": "Labels stored with the memory.", + "type": "array" + }, + "temporal": { + "description": "Bi-temporal window: validFrom, validTo, recordedAt, invalidatedAt.", + "type": "object" + }, + "text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The memory content." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + }, + "verificationStatus": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Always unverified for memories." + }, + "version": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Version number within this identity, incrementing on each superseding write." + } + }, + "required": [ + "id", + "kind" + ], + "type": "object" + } + }, + "required": [ + "operation", + "memory" + ], + "type": "object" + }, + { + "properties": { + "completeness": { + "description": "Plan accounting. This is not the paginated completeness envelope.", + "properties": { + "applied": { + "description": "Results produced, one per submitted operation.", + "minimum": 0, + "type": "integer" + }, + "complete": { + "description": "Always true: a plan is applied in full or rejected in full.", + "type": "boolean" + }, + "requested": { + "description": "Operations submitted.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "complete", + "requested", + "applied" + ], + "type": "object" + }, + "results": { + "description": "One result per submitted operation, in order.", + "items": { + "properties": { + "indexUpdated": { + "description": "Present when only the embedding was refreshed.", + "type": "boolean" + }, + "memory": { + "anyOf": [ + { + "description": "A stored scoped memory version.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "embedding": { + "anyOf": [ + { + "type": "array" + }, + { + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The stored vector, or null when none was supplied and no provider was configured." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Caller-chosen name within the scope and type." + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "memoryType": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "preference, profile, goal, instruction, procedure, episode, or note." + }, + "metadata": { + "description": "Caller-owned JSON stored with the memory.", + "type": "object" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "scope": { + "description": "The userId, agentId, and runId this memory is scoped to; each is a string or null.", + "type": "object" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "active, superseded, or invalidated." + }, + "supersededBy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the version that replaced this one." + }, + "supersedes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the version this one replaced." + }, + "tags": { + "description": "Labels stored with the memory.", + "type": "array" + }, + "temporal": { + "description": "Bi-temporal window: validFrom, validTo, recordedAt, invalidatedAt.", + "type": "object" + }, + "text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The memory content." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + }, + "verificationStatus": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Always unverified for memories." + }, + "version": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Version number within this identity, incrementing on each superseding write." + } + }, + "required": [ + "id", + "kind" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The resulting memory, or null for a NOOP on an identity that has no memory." + }, + "operation": { + "description": "What was actually applied, which may differ from the requested action when content already matched.", + "enum": [ + "ADD", + "UPDATE", + "DELETE", + "NOOP" + ], + "type": "string" + }, + "previous": { + "description": "A stored scoped memory version.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "embedding": { + "anyOf": [ + { + "type": "array" + }, + { + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The stored vector, or null when none was supplied and no provider was configured." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Caller-chosen name within the scope and type." + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "memoryType": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "preference, profile, goal, instruction, procedure, episode, or note." + }, + "metadata": { + "description": "Caller-owned JSON stored with the memory.", + "type": "object" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "scope": { + "description": "The userId, agentId, and runId this memory is scoped to; each is a string or null.", + "type": "object" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "active, superseded, or invalidated." + }, + "supersededBy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the version that replaced this one." + }, + "supersedes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the version this one replaced." + }, + "tags": { + "description": "Labels stored with the memory.", + "type": "array" + }, + "temporal": { + "description": "Bi-temporal window: validFrom, validTo, recordedAt, invalidatedAt.", + "type": "object" + }, + "text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The memory content." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + }, + "verificationStatus": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Always unverified for memories." + }, + "version": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Version number within this identity, incrementing on each superseding write." + } + }, + "required": [ + "id", + "kind" + ], + "type": "object" + } + }, + "required": [ + "operation", + "memory" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "results", + "completeness" + ], + "type": "object" + } + ], + "description": "Either the outcome of one reconciliation, or the outcome of a plan.", + "type": "object" +}
- Changed
shadowgraph_repair_plan1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "A plan that is never applied automatically.", + "properties": { + "actions": { + "description": "One action per diagnostic.", + "items": { + "properties": { + "action": { + "description": "remove_relation for a relationship whose endpoint is missing; manual_review for everything else.", + "enum": [ + "remove_relation", + "manual_review" + ], + "type": "string" + }, + "code": { + "description": "The diagnostic code, on a manual_review action.", + "type": "string" + }, + "reason": { + "description": "The diagnostic code that justified a remove_relation action.", + "type": "string" + }, + "relationId": { + "description": "Relationship to remove, on a remove_relation action.", + "type": "string" + }, + "severity": { + "description": "The diagnostic severity, on a manual_review action.", + "type": "string" + } + }, + "required": [ + "action" + ], + "type": "object" + }, + "type": "array" + }, + "apply": { + "const": false, + "description": "Always false: this tool proposes, it never repairs.", + "type": "boolean" + } + }, + "required": [ + "apply", + "actions" + ], + "type": "object" +}
- Changed
shadowgraph_restore2 fields changed- added
Input schema / properties / source / descriptionAdded value: +"Server-side path of the backup to install. Required. It must match the configured storage backend: a JSON export cannot overwrite a SQLite database. The backup file itself is never rewritten." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "What was restored from where. Fields beyond source and destination depend on the storage backend and on whether cleanup was confirmed.", + "properties": { + "artifactCleanup": { + "description": "Cleanup outcome: status complete, incomplete, or unknown, plus any per-path errors.", + "type": "object" + }, + "destination": { + "description": "Path of the store that was replaced.", + "type": "string" + }, + "records": { + "description": "Records installed. JSON restores only.", + "type": "integer" + }, + "recoveryArtifact": { + "description": "Retained recovery copy, when one is left behind.", + "type": "string" + }, + "retainedArtifacts": { + "description": "Rollback or recovery files still present after the restore.", + "items": { + "type": "string" + }, + "type": "array" + }, + "rollbackArtifact": { + "description": "Retained rollback copy of the previous store, when one is left behind.", + "type": "string" + }, + "source": { + "description": "Path the backup was read from.", + "type": "string" + }, + "temporaryArtifact": { + "description": "Retained temporary file, when one is left behind.", + "type": "string" + }, + "unchanged": { + "description": "True when source and destination were the same path and nothing was replaced.", + "type": "boolean" + }, + "unknownArtifacts": { + "description": "Artifact paths whose existence could not be determined, each { path, code }.", + "type": "array" + } + }, + "required": [ + "source", + "destination" + ], + "type": "object" +}
- Changed
shadowgraph_retrieve8 fields changed- added
Input schema / properties / kind / descriptionAdded value: +"Restrict results to decisions or to attempts. A structured filter, never a content match." - changed
Input schema / properties / limit / descriptionPrevious value: -"Page size. Omitted means a declared default, never silent truncation."New value: +"Maximum items to return, 1-1000; the default is 50 and completeness.limitSource reports which applied. Out of range is rejected, never silently clamped." - added
Input schema / properties / minConfidence / descriptionAdded value: +"Return only decisions whose current confidence is at least this value, 0-1. A structured filter, never a content match." - changed
Input schema / properties / offset / descriptionPrevious value: -"Page offset."New value: +"Items to skip before this window. Ordering is total and deterministic, so paging cannot drop or duplicate an item." - added
Input schema / properties / project / descriptionAdded value: +"Restrict to one project, including which neighbours may be pulled in." - added
Input schema / properties / query / descriptionAdded value: +"Whitespace-separated terms matched against the declared content fields (title, goal, chosen, assumption, evidence, alternative, attempt solution, attempt result, attempt reason, environment), exactly as in shadowgraph_search. Omit to retrieve by filters alone." - added
Input schema / properties / status / descriptionAdded value: +"Return only decisions in this lifecycle state. A structured filter, so matching it is never counted as a content match." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Matching records plus their one-hop neighbours, with pagination and completeness.", + "properties": { + "completeness": { + "description": "Declares exactly what this response left out, so a truncated result can never look complete.", + "properties": { + "complete": { + "description": "True only when every matching item is present.", + "type": "boolean" + }, + "contentFields": { + "description": "The declared content fields a query term could match.", + "items": { + "type": "string" + }, + "type": "array" + }, + "includesGraphNeighbours": { + "description": "Always true: this result may contain items reached by relationship rather than by content.", + "type": "boolean" + }, + "limitSource": { + "description": "Whose choice bounded the result.", + "enum": [ + "caller", + "default" + ], + "type": "string" + }, + "losslessItems": { + "description": "Always true: each returned item is a full-fidelity record, never a summary or a truncated field.", + "type": "boolean" + }, + "omitted": { + "description": "total minus returned.", + "minimum": 0, + "type": "integer" + }, + "returned": { + "description": "Items in this response.", + "minimum": 0, + "type": "integer" + }, + "scope": { + "description": "The project, query, and structured filters that produced this result, so it explains its own derivation.", + "type": "object" + }, + "total": { + "description": "Items that matched in total.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "scope", + "returned", + "total", + "complete", + "omitted", + "losslessItems", + "limitSource", + "contentFields", + "includesGraphNeighbours" + ], + "type": "object" + }, + "items": { + "description": "The items in this window, in deterministic order.", + "items": { + "description": "One hit, which may be a content match or a one-hop graph neighbour.", + "properties": { + "filters": { + "description": "The structured filters that were applied.", + "type": "object" + }, + "graphBoost": { + "description": "1 for an item included as a graph neighbour, 0 for a direct content match.", + "type": "number" + }, + "matched": { + "description": "The content fields that actually matched, never schema keys.", + "items": { + "type": "string" + }, + "type": "array" + }, + "matchedBy": { + "description": "content when query terms matched, filter when only structured filters applied, graph when the item was pulled in as a neighbour.", + "enum": [ + "content", + "filter", + "graph" + ], + "type": "string" + }, + "reason": { + "description": "Human-readable explanation built from matched, so it can never claim a match it cannot name.", + "type": "string" + }, + "reasons": { + "description": "All reasons this item is present.", + "items": { + "type": "string" + }, + "type": "array" + }, + "record": { + "description": "One stored entity: a decision, attempt, memory, fact, or alternative. Fields vary by kind, and an entity imported from an older schema may carry fewer of them.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + } + }, + "type": "object" + }, + "score": { + "description": "Relevance score; 0 when no query terms were supplied.", + "type": "number" + } + }, + "required": [ + "record", + "score", + "matched", + "reason", + "matchedBy", + "filters", + "graphBoost", + "reasons" + ], + "type": "object" + }, + "type": "array" + }, + "page": { + "description": "The window actually applied to the matching items.", + "properties": { + "hasMore": { + "description": "True when matching items exist beyond this window.", + "type": "boolean" + }, + "limit": { + "description": "Window size applied, whether the caller set it or the default did.", + "minimum": 1, + "type": "integer" + }, + "offset": { + "description": "Index of the first item returned.", + "minimum": 0, + "type": "integer" + }, + "total": { + "description": "Matching items before the window was applied.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "offset", + "limit", + "total", + "hasMore" + ], + "type": "object" + } + }, + "required": [ + "items", + "page", + "completeness" + ], + "type": "object" +}
- Changed
shadowgraph_review3 fields changed- added
Input schema / properties / changedFacts / descriptionAdded value: +"Fact keys that just changed. Only string-form reopenWhen rules match this list; it is an ephemeral signal, not durable state." - changed
Input schema / properties / facts / descriptionPrevious value: -"Optional overrides; these take precedence over stored facts."New value: +"Fact key/value overrides evaluated instead of the stored facts of the same key. Stored facts are used for every key not listed here, so reopen rules still work after a restart." - added
Input schema / properties / project / descriptionAdded value: +"Review only this project. Omit to review every project."
- Changed
shadowgraph_review_signals2 fields changed- added
Input schema / properties / project / descriptionAdded value: +"Only signals whose decision belongs to this project. Omit for every project." - added
Input schema / properties / status / descriptionAdded value: +"Filter by state. Omit to return both."
- Changed
shadowgraph_search9 fields changed- added
Input schema / properties / kind / descriptionAdded value: +"Restrict results to decisions or to attempts. A structured filter, never a content match." - changed
Input schema / properties / limit / descriptionPrevious value: -"Page size. Omitted means a declared default, never silent truncation."New value: +"Maximum items to return, 1-1000; the default is 50 and completeness.limitSource reports which applied. Out of range is rejected, never silently clamped." - added
Input schema / properties / minConfidence / descriptionAdded value: +"Return only decisions whose current confidence is at least this value, 0-1. A structured filter, never a content match." - changed
Input schema / properties / offset / descriptionPrevious value: -"Page offset."New value: +"Items to skip before this window. Ordering is total and deterministic, so paging cannot drop or duplicate an item." - added
Input schema / properties / project / descriptionAdded value: +"Restrict to one project. Omitted, decisions and facts are searched across projects, while memories stay in the default project and all-null scope." - added
Input schema / properties / query / descriptionAdded value: +"Whitespace-separated terms, matched case-insensitively as substrings against the declared content fields (title, goal, chosen, assumption, evidence, alternative, attempt solution, attempt result, attempt reason, environment). Every term must match something, so more terms narrow the result. Omit to filter without searching." - added
Input schema / properties / sourceClass / descriptionAdded value: +"Return only records carrying this claimed origin class. A structured filter, never a content match." - added
Input schema / properties / status / descriptionAdded value: +"Return only decisions in this lifecycle state. A structured filter, so matching it is never counted as a content match." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Matching records with their pagination and completeness declaration.", + "properties": { + "completeness": { + "description": "Declares exactly what this response left out, so a truncated result can never look complete.", + "properties": { + "complete": { + "description": "True only when every matching item is present.", + "type": "boolean" + }, + "contentFields": { + "description": "The declared content fields a query term could match.", + "items": { + "type": "string" + }, + "type": "array" + }, + "limitSource": { + "description": "Whose choice bounded the result.", + "enum": [ + "caller", + "default" + ], + "type": "string" + }, + "losslessItems": { + "description": "Always true: each returned item is a full-fidelity record, never a summary or a truncated field.", + "type": "boolean" + }, + "omitted": { + "description": "total minus returned.", + "minimum": 0, + "type": "integer" + }, + "returned": { + "description": "Items in this response.", + "minimum": 0, + "type": "integer" + }, + "scope": { + "description": "The project, query, and structured filters that produced this result, so it explains its own derivation.", + "type": "object" + }, + "total": { + "description": "Items that matched in total.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "scope", + "returned", + "total", + "complete", + "omitted", + "losslessItems", + "limitSource", + "contentFields" + ], + "type": "object" + }, + "items": { + "description": "The items in this window, in deterministic order.", + "items": { + "description": "One hit and the evidence for why it matched.", + "properties": { + "filters": { + "description": "The structured filters that were applied.", + "type": "object" + }, + "matched": { + "description": "The content fields that actually matched, never schema keys.", + "items": { + "type": "string" + }, + "type": "array" + }, + "matchedBy": { + "description": "content when query terms matched, filter when only structured filters applied, graph when the item was pulled in as a neighbour.", + "enum": [ + "content", + "filter", + "graph" + ], + "type": "string" + }, + "reason": { + "description": "Human-readable explanation built from matched, so it can never claim a match it cannot name.", + "type": "string" + }, + "record": { + "description": "One stored entity: a decision, attempt, memory, fact, or alternative. Fields vary by kind, and an entity imported from an older schema may carry fewer of them.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + } + }, + "type": "object" + }, + "score": { + "description": "Relevance score; 0 when no query terms were supplied.", + "type": "number" + } + }, + "required": [ + "record", + "score", + "matched", + "reason", + "matchedBy", + "filters" + ], + "type": "object" + }, + "type": "array" + }, + "page": { + "description": "The window actually applied to the matching items.", + "properties": { + "hasMore": { + "description": "True when matching items exist beyond this window.", + "type": "boolean" + }, + "limit": { + "description": "Window size applied, whether the caller set it or the default did.", + "minimum": 1, + "type": "integer" + }, + "offset": { + "description": "Index of the first item returned.", + "minimum": 0, + "type": "integer" + }, + "total": { + "description": "Matching items before the window was applied.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "offset", + "limit", + "total", + "hasMore" + ], + "type": "object" + } + }, + "required": [ + "items", + "page", + "completeness" + ], + "type": "object" +}
- Changed
shadowgraph_supersede3 fields changed- added
Input schema / properties / decisionId / descriptionAdded value: +"The decision being replaced. It becomes superseded and is excluded from current context." - added
Input schema / properties / replacementId / descriptionAdded value: +"The decision replacing it. Must be in the same project and must not be superseded, archived, abandoned, or stale." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Both sides of the supersession and the relationship that records it.", + "properties": { + "previous": { + "description": "A stored decision, including its alternatives and auditable confidence basis.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "alternatives": { + "description": "Rejected alternatives, each with id, label, reasonRejected, status, and the reopenWhen rules that make it reconsiderable.", + "type": "array" + }, + "assumptions": { + "description": "Assumptions the decision rests on. Searchable content.", + "items": { + "type": "string" + }, + "type": "array" + }, + "chosen": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The option that was chosen." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "confidence": { + "description": "Auditable confidence: initial, current (0-1), policy, a history entry per move, and a basis summarising the contributions it was folded from. Legacy records may lack basis.", + "type": "object" + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "evidence": { + "description": "Normalised evidence entries: source, type, sourceClass, confidence, observedAt, detail.", + "type": "array" + }, + "failedAttempts": { + "description": "Attempt identifiers or notes attached to this decision.", + "type": "array" + }, + "goal": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "What the decision was trying to achieve." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "migration": { + "description": "Present only on migrated records; records the legacy value a field was mapped from.", + "type": "object" + }, + "outcome": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The recorded outcome, or null until one is recorded." + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "reviewAfter": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 instant after which shadowgraph_maintain marks this decision stale." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Lifecycle state. Legacy records may carry a value this build does not recognise; shadowgraph_validate reports those." + }, + "supersededBy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the decision that replaced this one." + }, + "supersedes": { + "description": "Identifiers of decisions this one replaced.", + "type": "array" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Short name of the decision." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + } + }, + "required": [ + "id", + "kind" + ], + "type": "object" + }, + "relation": { + "anyOf": [ + { + "description": "A stored relationship between two entities.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "from": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Source entity identifier." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "relation": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Relationship name, such as depends_on or supersedes." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "temporal": { + "description": "Bi-temporal window for the relationship.", + "type": "object" + }, + "to": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Target entity identifier." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + } + }, + "required": [ + "id", + "from", + "to", + "relation" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The supersedes relationship, or null when a repeated supersession found none to report." + }, + "replacement": { + "description": "A stored decision, including its alternatives and auditable confidence basis.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "alternatives": { + "description": "Rejected alternatives, each with id, label, reasonRejected, status, and the reopenWhen rules that make it reconsiderable.", + "type": "array" + }, + "assumptions": { + "description": "Assumptions the decision rests on. Searchable content.", + "items": { + "type": "string" + }, + "type": "array" + }, + "chosen": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The option that was chosen." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "confidence": { + "description": "Auditable confidence: initial, current (0-1), policy, a history entry per move, and a basis summarising the contributions it was folded from. Legacy records may lack basis.", + "type": "object" + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "evidence": { + "description": "Normalised evidence entries: source, type, sourceClass, confidence, observedAt, detail.", + "type": "array" + }, + "failedAttempts": { + "description": "Attempt identifiers or notes attached to this decision.", + "type": "array" + }, + "goal": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "What the decision was trying to achieve." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "migration": { + "description": "Present only on migrated records; records the legacy value a field was mapped from.", + "type": "object" + }, + "outcome": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The recorded outcome, or null until one is recorded." + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "reviewAfter": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 instant after which shadowgraph_maintain marks this decision stale." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Lifecycle state. Legacy records may carry a value this build does not recognise; shadowgraph_validate reports those." + }, + "supersededBy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the decision that replaced this one." + }, + "supersedes": { + "description": "Identifiers of decisions this one replaced.", + "type": "array" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Short name of the decision." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + } + }, + "required": [ + "id", + "kind" + ], + "type": "object" + } + }, + "required": [ + "previous", + "replacement", + "relation" + ], + "type": "object" +}
- Changed
shadowgraph_traverse7 fields changed- added
Input schema / properties / depth / descriptionAdded value: +"How many relationship hops to follow, 1-10. Defaults to 1. Anything outside the range is rejected." - added
Input schema / properties / direction / descriptionAdded value: +"out follows relationships whose from is in the frontier, in follows their to, both follows either. Defaults to both." - added
Input schema / properties / id / descriptionAdded value: +"Entity id to start from. Must exist." - added
Input schema / properties / projectAdded value: +{ + "description": "Project whose memory nodes are visible during the walk. Defaults to \"default\"; decisions, facts, and attempts are not filtered by it.", + "type": "string" +} - added
Input schema / properties / relation / descriptionAdded value: +"Follow only relationships with this exact name. Omit to follow all of them." - added
Input schema / properties / scopeAdded value: +{ + "additionalProperties": false, + "description": "Scope selector. Omitted or partial fields mean explicit nulls, not \"any\": identity is the exact (project, userId, agentId, runId, memoryType, key) tuple, so a run-scoped memory never leaks into a user-only read.", + "properties": { + "agentId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Agent this memory belongs to, or null for none." + }, + "runId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Single run or task this memory belongs to, or null for none." + }, + "userId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Person this memory belongs to, or null for none." + } + }, + "type": "object" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "The reachable subgraph.", + "properties": { + "depth": { + "description": "The hop limit that was applied.", + "maximum": 10, + "minimum": 1, + "type": "integer" + }, + "direction": { + "description": "The direction that was applied.", + "enum": [ + "in", + "out", + "both" + ], + "type": "string" + }, + "nodes": { + "description": "Entities reached, root first. Mixed kinds, including alternatives synthesised from their decision.", + "items": { + "description": "One stored entity: a decision, attempt, memory, fact, or alternative. Fields vary by kind, and an entity imported from an older schema may carry fewer of them.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + } + }, + "type": "object" + }, + "type": "array" + }, + "relations": { + "description": "Relationships traversed. Named relations, not \"edges\".", + "items": { + "description": "A stored relationship between two entities.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "from": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Source entity identifier." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "relation": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Relationship name, such as depends_on or supersedes." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "temporal": { + "description": "Bi-temporal window for the relationship.", + "type": "object" + }, + "to": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Target entity identifier." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + } + }, + "required": [ + "id", + "from", + "to", + "relation" + ], + "type": "object" + }, + "type": "array" + }, + "root": { + "description": "The entity the walk started from.", + "type": "string" + } + }, + "required": [ + "root", + "direction", + "depth", + "nodes", + "relations" + ], + "type": "object" +}
- Changed
shadowgraph_update_status3 fields changed- added
Input schema / properties / decisionId / descriptionAdded value: +"Identifier of an existing decision, as returned by shadowgraph_record_decision, shadowgraph_search, or shadowgraph_retrieve." - added
Input schema / properties / status / descriptionAdded value: +"Target state. Legal moves are proposed to planned/in_progress/abandoned/archived; planned to in_progress/abandoned/archived; in_progress to executed/failed/abandoned/archived; executed to validated/failed/reconsidered/archived; validated to reconsidered/archived; failed to reconsidered/abandoned/archived; reconsidered to planned/in_progress/abandoned/archived; stale to reconsidered/archived; abandoned to archived. stale and superseded cannot be set by a caller." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "A stored decision, including its alternatives and auditable confidence basis.", + "properties": { + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Who performed the write." + }, + "alternatives": { + "description": "Rejected alternatives, each with id, label, reasonRejected, status, and the reopenWhen rules that make it reconsiderable.", + "type": "array" + }, + "assumptions": { + "description": "Assumptions the decision rests on. Searchable content.", + "items": { + "type": "string" + }, + "type": "array" + }, + "chosen": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The option that was chosen." + }, + "client": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Which client performed the write." + }, + "confidence": { + "description": "Auditable confidence: initial, current (0-1), policy, a history entry per move, and a basis summarising the contributions it was folded from. Legacy records may lack basis.", + "type": "object" + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 creation time." + }, + "evidence": { + "description": "Normalised evidence entries: source, type, sourceClass, confidence, observedAt, detail.", + "type": "array" + }, + "failedAttempts": { + "description": "Attempt identifiers or notes attached to this decision.", + "type": "array" + }, + "goal": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "What the decision was trying to achieve." + }, + "id": { + "description": "Stable entity identifier.", + "type": "string" + }, + "kind": { + "description": "Entity kind: decision, attempt, memory, fact, relation, review, or alternative.", + "type": "string" + }, + "migration": { + "description": "Present only on migrated records; records the legacy value a field was mapped from.", + "type": "object" + }, + "outcome": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The recorded outcome, or null until one is recorded." + }, + "project": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Project namespace; records imported from a schema that predates projects may carry null." + }, + "reviewAfter": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 instant after which shadowgraph_maintain marks this decision stale." + }, + "schemaVersion": { + "description": "Storage schema version this entity was written under. A value above the build’s own version is preserved rather than downgraded.", + "type": "integer" + }, + "sessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session identifier recorded with the write." + }, + "sourceClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Claimed origin class recorded with the write. A claim, never proof." + }, + "sourceRaw": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The original origin label when it differed from sourceClass. Audit only; never evidence." + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Lifecycle state. Legacy records may carry a value this build does not recognise; shadowgraph_validate reports those." + }, + "supersededBy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Identifier of the decision that replaced this one." + }, + "supersedes": { + "description": "Identifiers of decisions this one replaced.", + "type": "array" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Short name of the decision." + }, + "updatedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 time of the last change." + } + }, + "required": [ + "id", + "kind" + ], + "type": "object" +}
- Changed
shadowgraph_validate1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Integrity diagnostics.", + "properties": { + "counts": { + "description": "Issue counts per severity.", + "properties": { + "error": { + "description": "Genuinely invalid data.", + "minimum": 0, + "type": "integer" + }, + "info": { + "description": "Declared discontinuities, such as a hard-purge journal gap.", + "minimum": 0, + "type": "integer" + }, + "legacy": { + "description": "Readable data that predates a contract.", + "minimum": 0, + "type": "integer" + }, + "unsupported": { + "description": "Data from a newer schema or policy this build cannot interpret.", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "error", + "legacy", + "unsupported", + "info" + ], + "type": "object" + }, + "issues": { + "description": "Every diagnostic found, each with a stable code and severity.", + "items": { + "description": "One diagnostic. Extra fields identify the affected entity, entry, or scope.", + "properties": { + "code": { + "description": "Stable diagnostic code, such as missing_relation_source, unknown_decision_status, or journal_gap.", + "type": "string" + }, + "detail": { + "description": "Human-readable explanation.", + "type": "string" + }, + "entityId": { + "description": "Affected entity identifier.", + "type": "string" + }, + "entryId": { + "description": "Affected journal entry identifier.", + "type": "string" + }, + "recordId": { + "description": "Affected record or fact identifier.", + "type": "string" + }, + "relationId": { + "description": "Affected relationship identifier.", + "type": "string" + }, + "seq": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Affected journal sequence number." + }, + "severity": { + "description": "error is invalid data, legacy is readable but predates a contract, unsupported comes from a newer schema this build cannot interpret, info is a declared discontinuity.", + "enum": [ + "error", + "legacy", + "unsupported", + "info" + ], + "type": "string" + }, + "type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Affected journal entry type." + } + }, + "required": [ + "code", + "severity" + ], + "type": "object" + }, + "type": "array" + }, + "valid": { + "description": "False when any error or unsupported issue is present.", + "type": "boolean" + } + }, + "required": [ + "valid", + "issues", + "counts" + ], + "type": "object" +}
27 tool updates
v0.40.0- First observed
shadowgraph_ack_review - First observed
shadowgraph_backup - First observed
shadowgraph_confidence_evidence - First observed
shadowgraph_context - First observed
shadowgraph_journal - First observed
shadowgraph_link - First observed
shadowgraph_maintain - First observed
shadowgraph_purge - First observed
shadowgraph_purge_preview - First observed
shadowgraph_rebuild - First observed
shadowgraph_recall - First observed
shadowgraph_record_attempt - First observed
shadowgraph_record_decision - First observed
shadowgraph_record_fact - First observed
shadowgraph_record_outcome - First observed
shadowgraph_redact - First observed
shadowgraph_remember - First observed
shadowgraph_repair_plan - First observed
shadowgraph_restore - First observed
shadowgraph_retrieve - First observed
shadowgraph_review - First observed
shadowgraph_review_signals - First observed
shadowgraph_search - First observed
shadowgraph_supersede - First observed
shadowgraph_traverse - First observed
shadowgraph_update_status - First observed
shadowgraph_validate
TDQS
Scored across 20 tools
Most tools are distinct, but the description text itself reveals thin boundaries: shadowgraph_review, shadowgraph_review_context and shadowgraph_reconsider all 'recheck conditions and save reminders', differing only in output breadth or side effects. Similarly search/retrieve/recall/context/expand form a five-tool read cluster whose distinctions (every-term match vs. neighbours vs. ranked signals vs. working set vs. handle expansion) are explained but easy to misselect. Descriptions do help, so it lands mid-range rather than low.
Every tool uses the same 'shadowgraph_' prefix with a lower snake_case verb or resource tail, with no camelCase or style mixing anywhere. The pattern is predictable across all 20 tools.
At 20 tools this sits in the heavy band, and several entries are near-variants of one another (review vs. review_context, reconsider; recall vs. retrieve vs. search) that could be collapsed or made options. The domain is genuinely rich, so it is defensible, but it is borderline bloated.
Lifecycle coverage is broad (record decision/attempt/fact/memory, outcome, evidence, status, supersede, maintain, validate, review flow), but the descriptions repeatedly reference shadowgraph_repair_plan and shadowgraph_rebuild as 'full mode only' tools that are not actually in this set, leaving an advertised repair/replay capability unreachable. There is also no explicit delete/invalidate-decision operation beyond supersede, which creates dead ends in an otherwise deep surface.
Maintenance
Related MCP Connectors
Persistent, inspectable memory for AI agents with lineage, correction, and a hosted MCP endpoint.
Memory, reflection and safety for AI agents. Hosted or local, no vector database.
Graph-native persistent memory for AI agents — 33 MCP tools, zero-LLM writes.
Provenance-carrying memory for AI agents: corrections supersede, never overwrite. Free, API + MCP.
Related MCP Servers
AlicenseNot gradedqualityBmaintenancePersistent graph-based memory for AI agents, stored as plain markdown — no vector DB. Typed nodes and 11 relation types via 5 MCP tools (search, get, create, link, related), stdio and HTTP/SSE transports.3MIT- FlicenseNot gradedqualityCmaintenanceLocal-first cross-agent memory for AI coding agents. Persistent, shared memory over MCP — what you tell one agent can be recalled by another — with all data stored in a single local SQLite file, no cloud and no API keys.-
- AlicenseAqualityCmaintenanceLocal-first, source-traceable memory for AI agents — no LLM at ingest, $0 per message, zero data egress. Gives Claude Code, Cursor, and any MCP client one shared persistent memory with semantic recall, belief revision, selective forgetting, and a provenance guard that blocks acting on stale or unconfirmed memories.2319 PyPI14MIT
- AlicenseAqualityAmaintenanceSelf-hosted decision memory for AI coding agents. Captures decisions with the alternatives you rejected, and warns before an agent re-proposes a rejected approach.489Apache 2.0