You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(cli): align observation_source enum with API + document v0.17→v0.18 breaking change (#1841) (#1851)
* fix(cli): align observation_source enum with API + document v0.17→v0.18 breaking change (#1841)
`observation_source` was tightened from arbitrary strings (v0.17) to a
closed enum in v0.18.0, but the change shipped undocumented and the CLI
enum drifted from the API.
- CLI/API parity: add the missing `sync` value to
OBSERVATION_SOURCE_CLI_VALUES so the CLI accepts exactly what the API
and openapi.yaml accept (sensor, llm_summary, workflow_state, human,
import, sync).
- Improve the "Invalid --observation-source" error to list the valid
values and tell users to put custom v0.17 labels in the free-form
`data_source` field.
- Update all three `--observation-source` CLI help strings (store, ingest,
snapshots export) to include `sync` + a migration note.
- Docs: CLI reference enum + migration link; new "Migrating
observation_source from v0.17 to v0.18" subsection in fleet_onboarding.md
with a custom-string → enum + data_source mapping table.
- Release: document the retroactive breaking change in the v0.18.3
release supplement (Breaking changes + Fixes#1841).
- Mark the enum as an intentional v0.17 breaking change in
action_schemas.ts.
- Test: tests/unit/cli_observation_source_flag.test.ts asserts CLI↔API
enum parity, that `sync` is accepted, and that an invalid value's error
carries the data_source migration hint.
No back-compat shim (operator verdict P2: document, don't widen).
Closes#1841
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* chore(catalog): regenerate automated test catalog for #1841 enum/migration tests
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: ateles-agent <agent@ateles.ai>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: docs/developer/cli_reference.md
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -693,6 +693,7 @@ Cross-instance peer sync. Backed by `src/services/sync/` and the HTTP `/peers` s
693
693
- Use `--json=` (equals, no space) so the payload is parsed as entities input.
694
694
- Bare `--json` (without `=`) remains the global output-format flag.
695
695
-`--file <path>`: Path to JSON file containing entity array. Use for long payloads.
696
+
-`--observation-source <kind>`: Classify the *kind* of write. Closed enum — `sensor | llm_summary | workflow_state | human | import | sync` (default `llm_summary`). **Breaking change in v0.18.x (was open in v0.17):** arbitrary strings are rejected. Put custom v0.17 labels (e.g. `cboe_live`, `stale_cache`) in the free-form `data_source` field and map the closest enum value here. See [Migrating from v0.17 to v0.18](fleet_onboarding.md#migrating-observation_source-from-v017-to-v018).
696
697
-`--interpretation-source-id <id>` / `--interpretation-source-ref <structured|unstructured>` plus `--interpretation-config <json>`: Opt into Source -> Interpretation -> Observation provenance for source-derived extraction. Omit for ordinary already-structured/chat-native facts.
697
698
- Silent-failure guard (v0.5.1+): when a commit-mode store returns `entities_created=0`, no resolved entities, and is not an idempotency replay (`replayed: true`), the CLI emits a non-fatal stderr warning so agents/humans don't mistake an empty result for success. Typical root cause: fields nested under `attributes` (see v0.5.0 breaking change) or mismatched `user_id` scope.
698
699
- Idempotency replays: `POST /store` returns `replayed: true` when a request is a deterministic re-commit of a previously committed `(user_id, idempotency_key)` tuple. Use this to distinguish "same call, no new work" from "call produced zero entities."
@@ -951,7 +952,7 @@ Fleet-general write-integrity tooling built on the canonical snapshot layer. `sn
951
952
-`--entity-types <csv>`: Restrict to comma-separated entity types (e.g. `agent_task,agent_attempt`).
952
953
-`--agent-sub <sub>`: Restrict to a single AAuth `agent_sub`.
953
954
-`--attribution-tier <tier>`: Restrict to one tier — `hardware | software | unverified_client | anonymous`.
954
-
-`--observation-source <kind>`: Restrict to one write kind — `sensor | llm_summary | workflow_state | human | import`.
955
+
-`--observation-source <kind>`: Restrict to one write kind — `sensor | llm_summary | workflow_state | human | import | sync`.
955
956
-`--since <iso>`: ISO-8601 lower bound on `last_observation_at`.
956
957
-`--limit <n>`: Cap on returned entities (default: 500).
957
958
-`--out <path>`: Write the export to this file instead of stdout.
Copy file name to clipboardExpand all lines: docs/developer/fleet_onboarding.md
+23Lines changed: 23 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -41,6 +41,9 @@ Set `observation_source` on every structured write. The value is orthogonal to A
41
41
|`llm_summary`| LLM-authored summaries / extractions. **Default** when `observation_source` is unspecified. |
42
42
|`human`| Direct human edits, acceptances, corrections. |
43
43
|`import`| Batch / ETL ingestion. Ranked last by default because provenance is typically second-hand. |
44
+
|`sync`| Writes replayed from a peer during fleet sync (Phase 5 loop prevention). Set automatically by the sync path; rarely supplied by hand. |
45
+
46
+
`sensor`, `llm_summary`, `workflow_state`, `human`, `import`, and `sync` are the **only** accepted values — this is a closed enum (see the v0.17→v0.18 migration note below).
44
47
45
48
Reducer tie-breaking proceeds `source_priority → observation_source_priority → observed_at`. Per-schema overrides (e.g. `agent_sensor_signal` locks `observation_source_priority` so sensor rows always win) live on `SchemaDefinition.reducer_config.observation_source_priority`.
46
49
@@ -69,6 +72,26 @@ neotoma store \
69
72
70
73
See the applied rules in [`.cursor/rules/neotoma_cli.mdc`](../../.cursor/rules/neotoma_cli.mdc) (rule 14a) or [`docs/developer/mcp/instructions.md`](./mcp/instructions.md) for the agent-instruction wording.
71
74
75
+
### Migrating `observation_source` from v0.17 to v0.18
76
+
77
+
**Breaking change (v0.18.x, [#1841](https://github.com/markmhendrickson/neotoma/issues/1841)).** In v0.17, `observation_source` (and the `--observation-source` CLI flag) accepted arbitrary strings — e.g. `cboe_live`, `stale_cache`, `computed_greeks`. v0.18 restricts it to the closed enum above. Stores and `--observation-source` flags carrying a custom string now fail with:
78
+
79
+
```
80
+
Invalid --observation-source "cboe_live". Expected one of: sensor, llm_summary, workflow_state, human, import, sync. Custom v0.17 observation_source labels are no longer accepted — put them in the free-form "data_source" field instead.
81
+
```
82
+
83
+
`observation_source` is a *fixed classification* of the kind of write (it drives reducer tie-breaking); the descriptive label of *where* a value came from belongs in the free-form `data_source` field, which remains unconstrained. To migrate, map each custom string to the closest enum value and move the original label into `data_source`:
If no enum value fits the *kind* of write, default to `import` (second-hand provenance) or `llm_summary` (the system default) and preserve the original string in `data_source`. There is no back-compat shim — the enum is enforced at the parse boundary on both the CLI and the API.
94
+
72
95
## 3. Use the fleet-general `agent_*` schemas
73
96
74
97
Neotoma ships a v0.1 "lowest common denominator" schema set in the `agent_runtime` category. Store runtime data against these types so your drift reports, timeline views, and Inspector filters work without fleet-specific migrations:
Copy file name to clipboardExpand all lines: docs/releases/in_progress/v0.18.3/github_release_supplement.md
+14-1Lines changed: 14 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -37,6 +37,7 @@ No OpenAPI changes. `source_storage` is an existing `StoreRequest` field; this r
37
37
-**#1826** — `source_storage: "reference"` was unreachable over HTTP `POST /store`. The OpenAPI contract accepted it (v0.18.1) but `handleStorePost` still stored inline. The REST handler now honors reference mode end to end.
38
38
-**#1827 (REST extension)** — the combined `entities[] + file + source_storage:reference` call returned a 500 on `observations.id` UNIQUE collision because the REST structured leg lacked the existing-observation guard that the MCP path has. Brought to parity.
39
39
-**#1837** — the Inspector graph viewer fired `retrieve_graph_neighborhood` in an unbounded loop and never painted. Root cause was a global `refetchInterval: 5000`, not unbounded traversal. Polling disabled on the graph hooks; canvas height fixed.
40
+
-**#1841** — the v0.18.0 `observation_source` enum restriction was undocumented, and the CLI enum had drifted from the API (missing `sync`). Documented the breaking change + migration mapping, aligned the CLI enum and error message to the API, no back-compat shim. See *Breaking changes* above.
No breaking changes. No OpenAPI tightening, no request-shape changes, no field promotions or removals. Both behavior changes (reference stores honored, duplicate observations replayed) are strict improvements aligning REST with MCP. Patch bump is correct per SemVer.
56
+
This patch introduces no *new* breaking changes. No OpenAPI tightening, no request-shape changes, no field promotions or removals. Both behavior changes (reference stores honored, duplicate observations replayed) are strict improvements aligning REST with MCP. Patch bump is correct per SemVer.
[#1841](https://github.com/markmhendrickson/neotoma/issues/1841) surfaced a v0.18.0 breaking change that shipped **undocumented**: `observation_source` was tightened from arbitrary strings (v0.17) to a closed enum — `sensor`, `llm_summary`, `workflow_state`, `human`, `import`, `sync`. Stores carrying a custom string (e.g. `cboe_live`, `stale_cache`) now hard-fail at the parse boundary on both the CLI and the API. There is no back-compat shim (operator verdict P2: document, don't widen).
61
+
62
+
This release does **not** change that enforcement; it documents and de-drifts it:
63
+
64
+
- The CLI `--observation-source` enum now matches the API/OpenAPI exactly (added the missing `sync`); previously the CLI rejected a value the API accepts.
65
+
- The invalid-value error message now tells users to put custom v0.17 labels in the free-form `data_source` field.
66
+
- A migration guide (custom v0.17 strings → closest enum + `data_source`) was added to [`docs/developer/fleet_onboarding.md`](../../developer/fleet_onboarding.md#migrating-observation_source-from-v017-to-v018) and the [CLI reference](../../developer/cli_reference.md).
67
+
68
+
**If you upgraded from v0.17 and used custom `observation_source` strings:** map each to the closest enum value and move the original label to `data_source`. See the migration guide for the mapping table.
0 commit comments