@witness-ai/opencode 0.3.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/witness.js CHANGED
@@ -12,8 +12,8 @@ const PACKAGE_ROOT = path.dirname(path.dirname(fileURLToPath(import.meta.url)))
12
12
 
13
13
  const command = process.argv[2] || ""
14
14
 
15
- if (command === "install" || command === "uninstall") {
16
- console.error("witness: `install` and `uninstall` are source-checkout commands. With @witness-ai/opencode, add the plugin to opencode.json and let the plugin auto-register MCP.")
15
+ if (command === "wire" || command === "unwire") {
16
+ console.error("witness: `wire` and `unwire` are source-checkout commands for editor integrations. With @witness-ai/opencode, add the plugin to opencode.json and let the plugin auto-register MCP. The `install` (archive provisioning) and `ingest` (records-in) commands are supported.")
17
17
  process.exit(1)
18
18
  }
19
19
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@witness-ai/opencode",
3
- "version": "0.3.1",
3
+ "version": "0.5.0",
4
4
  "description": "MCP memory / second brain for Claude Code & OpenCode — captures your coding sessions and distills how your knowledge and habits evolve over time, queryable by your agent.",
5
5
  "type": "module",
6
6
  "main": "./witness.js",
@@ -20,8 +20,8 @@
20
20
  "README.md"
21
21
  ],
22
22
  "optionalDependencies": {
23
- "@witness-ai/opencode-darwin-arm64": "0.3.1",
24
- "@witness-ai/opencode-linux-x64": "0.3.1"
23
+ "@witness-ai/opencode-darwin-arm64": "0.5.0",
24
+ "@witness-ai/opencode-linux-x64": "0.5.0"
25
25
  },
26
26
  "keywords": [
27
27
  "mcp",
package/prompts/SCHEMA.md CHANGED
@@ -68,3 +68,70 @@ injects into a session. Agents read it on demand via the MCP tools (`get_facets`
68
68
 
69
69
  One moment can produce several observations — one per lens that finds it salient — sharing a raw
70
70
  anchor but framed for each lens.
71
+
72
+ ## Records-in: the `ingest` contract
73
+
74
+ witness can accept records from external sources (notes, market data, timestamped logs) via the
75
+ `witness ingest` command. This is a **stable, versioned public interface** for bringing structured
76
+ text into the distillation engine as a first-class L0 source alongside captured sessions.
77
+
78
+ ### Format
79
+
80
+ NDJSON (newline-delimited JSON): one JSON object per line, delivered via stdin or a file path.
81
+
82
+ ```sh
83
+ witness ingest < records.ndjson
84
+ witness ingest --file records.ndjson
85
+ ```
86
+
87
+ ### Fields
88
+
89
+ Each record is a JSON object with these fields:
90
+
91
+ - **`text`** (REQUIRED, non-empty string) — the content to distill. This is what the extract lens sees.
92
+ - **`id`** (optional string) — the caller-defined deduplication identity. Records sharing the same
93
+ `id` are considered versions of one logical entry. **Recommended** — supply an id when you have a
94
+ natural stable identifier (a filename, a URL, a database primary key).
95
+ - **`session`** (optional string) — a caller-defined grouping key. Records sharing a `session` value
96
+ are mined together as one chunk (one distillation unit), so the lens sees them in context. Omit
97
+ `session` (or pass different values) to mine records independently. All ingested sessions are
98
+ namespaced with the `file:` prefix in L0.
99
+ - **`ts`** (optional string) — the content timestamp in RFC3339 format (`YYYY-MM-DDTHH:MM:SSZ`) or
100
+ UTC date (`YYYY-MM-DD`). Defaults to ingest-time if absent. This becomes the L0 row's `ts` and
101
+ propagates to observations. Used for temporal facets (valid_from) and profile narrative.
102
+ - **`role`** (optional string) — defaults to `"document"`. May be any string; this becomes the L0
103
+ `role` field. Reserved for future use (e.g., distinguishing user notes from assistant summaries).
104
+
105
+ Unknown fields are ignored (forward compatibility).
106
+
107
+ ### Deduplication semantics
108
+
109
+ witness dedups records on the caller-provided `id`:
110
+
111
+ - **Same id + unchanged text** → skip (already ingested).
112
+ - **Same id + changed text** → update the existing L0 row with the new text and `ts`; observations
113
+ are re-mined on next distillation (the lens sees the new version).
114
+ - **New id** (or no prior record with this id) → append as a new L0 row.
115
+ - **No id provided** → fall back to content-hash dedup (same hash → skip; new hash → append). Less
116
+ precise — changing a single character creates a new row rather than updating the logical entry.
117
+
118
+ Re-ingesting the same record set is idempotent (no duplicate rows, no redundant observations).
119
+
120
+ ### Grouping semantics
121
+
122
+ Records with the same `session` value mine as one batch — the lens reads the whole group in one
123
+ pass, so cross-record patterns are visible (e.g., a recurring theme across multiple notes). Omit
124
+ `session` (or use distinct values) to mine each record independently; witness derives a session id
125
+ from the record `id` (or content hash) so each record becomes its own session. All ingested sessions
126
+ are namespaced with `file:` in the L0 `session` field, so they never collide with captured agent
127
+ sessions.
128
+
129
+ ### Example
130
+
131
+ ```jsonl
132
+ {"id": "note-2026-07-01", "session": "weekly-retros", "ts": "2026-07-01", "text": "Caught myself rushing to a fix before isolating the cause. Stopped, wrote repro steps, found it in two minutes."}
133
+ {"id": "note-2026-07-08", "session": "weekly-retros", "ts": "2026-07-08", "text": "Same trap again — saw a failing test, went straight to the code. Forced myself to read the failure message first; saved an hour."}
134
+ ```
135
+
136
+ After ingest, `witness distill start` mines these as one session (they share `session`), and the
137
+ lens sees both notes together — enough context to notice a pattern.