@witness-ai/opencode 0.2.4 → 0.3.1
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/download-model.js +8 -1
- package/bin/model.js +21 -0
- package/bin/witness.js +9 -3
- package/package.json +20 -6
- package/prompts/SCHEMA.md +9 -3
- package/prompts/default/lens.json +4 -0
- package/prompts/lens/example/README.md +23 -0
- package/prompts/lens/example/extract.md +32 -0
- package/prompts/lens/example/lens.json +4 -0
- package/prompts/lens/example/review.md +31 -0
- package/witness.js +21 -1
- package/prompts/lens/example.md +0 -86
- package/prompts/lens/opencode.md +0 -69
package/bin/download-model.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import path from "node:path"
|
|
3
3
|
import { fileURLToPath } from "node:url"
|
|
4
4
|
import { readFileSync, unlinkSync } from "node:fs"
|
|
5
|
-
import { downloadModel, modelReady, startModelDownload } from "./model.js"
|
|
5
|
+
import { downloadModel, modelReady, restampLockOwner, startModelDownload } from "./model.js"
|
|
6
6
|
|
|
7
7
|
const args = process.argv.slice(2)
|
|
8
8
|
const defaultRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..")
|
|
@@ -34,6 +34,13 @@ for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
|
34
34
|
})
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
// The lock was stamped with the PARENT's pid by startModelDownload's acquireLock;
|
|
38
|
+
// re-stamp it with OUR pid (this downloader child) so a hard kill of the child is
|
|
39
|
+
// detected by lockOwnerDead's liveness probe instead of wedging for 12h behind a
|
|
40
|
+
// still-alive parent (issue #54 I5). Token-guarded and best-effort. Also covers the
|
|
41
|
+
// detached --background launcher, which routes through --foreground.
|
|
42
|
+
if (args[0] === "--foreground" && lock && lockToken) restampLockOwner(lock, lockToken)
|
|
43
|
+
|
|
37
44
|
const parentPID = Number(process.env.WITNESS_MODEL_PARENT_PID || "0")
|
|
38
45
|
if (parentPID > 0) {
|
|
39
46
|
// OpenCode may be killed without running plugin dispose. Poll the parent so the
|
package/bin/model.js
CHANGED
|
@@ -267,6 +267,25 @@ function acquireLock(dir) {
|
|
|
267
267
|
}
|
|
268
268
|
}
|
|
269
269
|
|
|
270
|
+
// restampLockOwner rewrites the lock's recorded pid to THIS process's pid, keeping
|
|
271
|
+
// the token. startModelDownload's acquireLock stamps the PARENT (plugin) pid, then
|
|
272
|
+
// spawns the actual downloader as a child; if that child is SIGKILL'd while the
|
|
273
|
+
// parent lives, lockOwnerDead probes the still-alive parent and never reaps — a
|
|
274
|
+
// 12h wedge of the download (issue #54 I5). Having the --foreground child re-stamp
|
|
275
|
+
// with its own pid on startup makes the liveness probe target the process that is
|
|
276
|
+
// actually doing the work. Token-guarded so a stale-lock reap that already handed
|
|
277
|
+
// the slot to a different downloader is never clobbered; best-effort (a failure
|
|
278
|
+
// just leaves the parent pid, i.e. the pre-fix behavior). Exported (not just via
|
|
279
|
+
// __test) because download-model.js calls it in production.
|
|
280
|
+
export function restampLockOwner(lock, token) {
|
|
281
|
+
if (!lock || !token) return
|
|
282
|
+
try {
|
|
283
|
+
const body = readFileSync(lock, "utf8")
|
|
284
|
+
if (body.trim().split(/\s+/)[0] !== token) return // reaped + reassigned; not ours
|
|
285
|
+
writeFileSync(lock, `${token} ${process.pid} ${os.hostname()}\n`, { encoding: "utf8" })
|
|
286
|
+
} catch {}
|
|
287
|
+
}
|
|
288
|
+
|
|
270
289
|
export function startModelDownload(packageRoot, options = {}) {
|
|
271
290
|
if (process.env.WITNESS_SKIP_MODEL_DOWNLOAD === "1" || modelReady(packageRoot)) return null
|
|
272
291
|
const dir = modelDir(packageRoot)
|
|
@@ -433,5 +452,7 @@ export const __test = {
|
|
|
433
452
|
verifiedMarkerPath,
|
|
434
453
|
acquireLock,
|
|
435
454
|
lockStale,
|
|
455
|
+
lockOwnerDead,
|
|
456
|
+
restampLockOwner,
|
|
436
457
|
reapForeignParts,
|
|
437
458
|
}
|
package/bin/witness.js
CHANGED
|
@@ -18,9 +18,15 @@ if (command === "install" || command === "uninstall") {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
const packageName = platformPackage()
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
// Honor an explicit WITNESS_BIN override, just like the plugin (witness.js) does —
|
|
22
|
+
// used verbatim (no existsSync gate) so it can point at a dev build or a binary the
|
|
23
|
+
// platform-package probe can't resolve. Without this the CLI ignored the very
|
|
24
|
+
// override the plugin honored, so `WITNESS_BIN=... witness doctor` was inconsistent
|
|
25
|
+
// with what the plugin runs (issue #54 minor).
|
|
26
|
+
const override = process.env.WITNESS_BIN
|
|
27
|
+
const bin = override || platformWitnessBin()
|
|
28
|
+
|
|
29
|
+
if (!bin || (!override && !existsSync(bin))) {
|
|
24
30
|
const reason = packageName ? `optional package ${packageName} is not installed` : `unsupported platform ${process.platform}/${process.arch}`
|
|
25
31
|
console.error(`witness: ${reason}; supported platforms: ${supportedPlatforms()}`)
|
|
26
32
|
process.exit(1)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@witness-ai/opencode",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.3.1",
|
|
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",
|
|
7
7
|
"exports": "./witness.js",
|
|
@@ -20,13 +20,27 @@
|
|
|
20
20
|
"README.md"
|
|
21
21
|
],
|
|
22
22
|
"optionalDependencies": {
|
|
23
|
-
"@witness-ai/opencode-darwin-arm64": "0.
|
|
24
|
-
"@witness-ai/opencode-linux-x64": "0.
|
|
23
|
+
"@witness-ai/opencode-darwin-arm64": "0.3.1",
|
|
24
|
+
"@witness-ai/opencode-linux-x64": "0.3.1"
|
|
25
25
|
},
|
|
26
26
|
"keywords": [
|
|
27
|
+
"mcp",
|
|
28
|
+
"mcp-server",
|
|
29
|
+
"model-context-protocol",
|
|
30
|
+
"claude-code",
|
|
27
31
|
"opencode",
|
|
28
|
-
"
|
|
29
|
-
"
|
|
32
|
+
"memory",
|
|
33
|
+
"ai-memory",
|
|
34
|
+
"self-improvement",
|
|
35
|
+
"reflection",
|
|
36
|
+
"second-brain",
|
|
37
|
+
"personal-knowledge-management",
|
|
38
|
+
"knowledge-distillation",
|
|
39
|
+
"temporal",
|
|
40
|
+
"provenance",
|
|
41
|
+
"growth",
|
|
42
|
+
"llm",
|
|
43
|
+
"coding-agent"
|
|
30
44
|
],
|
|
31
45
|
"license": "MIT",
|
|
32
46
|
"repository": {
|
package/prompts/SCHEMA.md
CHANGED
|
@@ -51,10 +51,16 @@ Every observation/facet carries a `lens` tag.
|
|
|
51
51
|
|
|
52
52
|
- **`default`** — global, runs on every session, cross-domain. This is the thing no single-domain
|
|
53
53
|
tracker can be.
|
|
54
|
-
- **registered lenses** (e.g. `math`) — registered centrally (`witness lens register <name> <
|
|
54
|
+
- **registered lenses** (e.g. `math`) — registered centrally (`witness lens register <name> <dir>`)
|
|
55
55
|
and enabled globally (`witness lens enable <name>`); an enabled lens runs on every session.
|
|
56
|
-
Definitions live in the central registry (`<root>/lenses/<name
|
|
57
|
-
|
|
56
|
+
Definitions live in the central registry (`<root>/lenses/<name>/`), shared across all sessions —
|
|
57
|
+
never read from a repo.
|
|
58
|
+
|
|
59
|
+
A lens is a **directory** of `lens.json` (settings: `name`, `dimensions`, optional per-lens models)
|
|
60
|
+
plus `extract.md` and `review.md` (each whole file is the prompt for its pass). See
|
|
61
|
+
`prompts/lens/example/`. Mining uses the default model by default, but a lens may pin its own via
|
|
62
|
+
`witness lens set <name> --extract-model <m>` / `--review-model <m>` (written to its `lens.json`),
|
|
63
|
+
so a rare heavy lens can run a stronger model without paying for it on every session.
|
|
58
64
|
|
|
59
65
|
The profile is **collect-only / pull-only**: witness captures and distills everywhere, but never
|
|
60
66
|
injects into a session. Agents read it on demand via the MCP tools (`get_facets`, `get_profile`,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Example lens — a "math learner" lens
|
|
2
|
+
|
|
3
|
+
A complete, ready-to-register example lens. A lens is a **directory** of three files:
|
|
4
|
+
|
|
5
|
+
lens.json structured settings: name, dimensions, optional per-lens models
|
|
6
|
+
extract.md the mining (L0→L1) prompt — the whole file is the prompt
|
|
7
|
+
review.md the review (L1→L2) prompt — the whole file is the prompt
|
|
8
|
+
|
|
9
|
+
Copy this directory, rewrite the dimensions and the two prompts for your domain, then:
|
|
10
|
+
|
|
11
|
+
witness lens register math ./example/ # copies the directory into the registry
|
|
12
|
+
witness lens enable math # runs it on every session
|
|
13
|
+
|
|
14
|
+
The two prompts are passed VERBATIM as the system prompt for their pass — they fully
|
|
15
|
+
REPLACE the built-in `default` prompts, they don't extend them — so each must be
|
|
16
|
+
self-contained, INCLUDING its output JSON schema. The tool appends the transcript
|
|
17
|
+
(extract) or the accumulated observations (review) as the user message; it injects no
|
|
18
|
+
schema for you.
|
|
19
|
+
|
|
20
|
+
A lens is runner-agnostic: by default it rides the default model. To pin a stronger
|
|
21
|
+
model just for this lens (without paying for it on every session), add an optional
|
|
22
|
+
`"extract_model"` / `"review_model"` to `lens.json`, or run
|
|
23
|
+
`witness lens set math --extract-model <model>` (empty value clears it).
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
You are observing one study/work session between a person and an AI, through a
|
|
2
|
+
MATH-LEARNING lens. Notice things about *the person as a mathematician* — how they
|
|
3
|
+
reason, where they get stuck, and how they climb out — not the math facts themselves.
|
|
4
|
+
|
|
5
|
+
Tag each observation with exactly one dimension:
|
|
6
|
+
- speed — how fast they move; when they deliberately slow down vs. rush past a gap.
|
|
7
|
+
- independence — do they attempt before asking; how much scaffolding they need.
|
|
8
|
+
- proof_rigor — care with quantifiers, edge cases, and "why is this actually true?"
|
|
9
|
+
- abstraction — comfort moving between concrete instances and general statements.
|
|
10
|
+
- confusion_tolerance — how they sit with not-understanding before resolving it.
|
|
11
|
+
|
|
12
|
+
What makes a GOOD observation:
|
|
13
|
+
- Atomic — one noticed thing, one sentence.
|
|
14
|
+
- Evidence-anchored — cite a short quote or paraphrase of the exact moment. No anchor, don't write it.
|
|
15
|
+
- About the PERSON and durable-ish — "checked the base case unprompted" counts; "solved problem 3" is a task-fact, skip it.
|
|
16
|
+
- Honest — note struggles, shortcuts, and regressions as readily as wins. Never invent failings or wins.
|
|
17
|
+
|
|
18
|
+
Score poignancy 1-10 — how much a future reviewer should weight it for growth.
|
|
19
|
+
Most are 3-6; reserve 7+ for a genuine mindset shift or a precise self-diagnosis.
|
|
20
|
+
|
|
21
|
+
If the session was routine and nothing person-relevant happened, return `[]`.
|
|
22
|
+
Do not manufacture observations to fill space.
|
|
23
|
+
|
|
24
|
+
Return ONLY a JSON array, no prose around it. Each element:
|
|
25
|
+
[
|
|
26
|
+
{
|
|
27
|
+
"dimension": "proof_rigor",
|
|
28
|
+
"observation": "Stopped to verify the base case unprompted after a hand-wavy induction.",
|
|
29
|
+
"evidence": "\"wait — does n=0 actually hold here?\" before moving on",
|
|
30
|
+
"poignancy": 6
|
|
31
|
+
}
|
|
32
|
+
]
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
You are the reviewer for the MATH lens of a long-term, person-centric growth
|
|
2
|
+
archive. You read the accumulated observations plus the current facets, and you
|
|
3
|
+
assert what is true NOW, flagging genuine, sustained CHANGE over time.
|
|
4
|
+
|
|
5
|
+
How to synthesize:
|
|
6
|
+
- Group related observations into few, sharp, falsifiable facets within the dimensions above.
|
|
7
|
+
- Name facet keys in snake_case, emergent from the evidence; reuse an existing key when updating it.
|
|
8
|
+
- Every facet must cite the supporting observation IDs in `because_of`. No citation → no facet.
|
|
9
|
+
- Prefer "attempts an approach before asking for help" (falsifiable) over "is good at math" (not).
|
|
10
|
+
|
|
11
|
+
The change rule (most important):
|
|
12
|
+
- Set `contradicts_prior: true` ONLY for a sustained, repeated pattern that
|
|
13
|
+
conflicts with the stored current value. One off-pattern session is noise, not
|
|
14
|
+
a reversal.
|
|
15
|
+
- A time-bound `state`-like facet that has clearly passed can also flip.
|
|
16
|
+
- Mere absence of recent evidence is NOT change. Never invent a "used to do X,
|
|
17
|
+
stopped" arc — if you can't cite observation IDs for the NEW value, it isn't a change.
|
|
18
|
+
|
|
19
|
+
Confidence 0-1: 0.3-0.5 emerging; 0.6-0.8 well-supported across sessions; 0.9+ pervasive.
|
|
20
|
+
|
|
21
|
+
Return ONLY a JSON array, no surrounding prose. Each element:
|
|
22
|
+
[
|
|
23
|
+
{
|
|
24
|
+
"dimension": "independence",
|
|
25
|
+
"key": "attempts_before_asking",
|
|
26
|
+
"value": "Sketches an approach and tests it before reaching for help; a few months ago asked first.",
|
|
27
|
+
"confidence": 0.7,
|
|
28
|
+
"because_of": ["obs_8f2a3c", "obs_3c1190"],
|
|
29
|
+
"contradicts_prior": true
|
|
30
|
+
}
|
|
31
|
+
]
|
package/witness.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from "node:fs"
|
|
2
2
|
import { fileURLToPath } from "node:url"
|
|
3
3
|
import { modelDir, modelReady, promptsDir, startModelDownload } from "./bin/model.js"
|
|
4
|
-
import { platformWitnessBin } from "./bin/platform.js"
|
|
4
|
+
import { platformPackage, platformWitnessBin, supportedPlatforms } from "./bin/platform.js"
|
|
5
5
|
|
|
6
6
|
const PACKAGE_ROOT = fileURLToPath(new URL(".", import.meta.url))
|
|
7
7
|
const DOWNLOAD_RETRY_MAX = 6
|
|
@@ -12,6 +12,25 @@ const IMPORT_GRACE_MS = 5000
|
|
|
12
12
|
const platformBin = platformWitnessBin()
|
|
13
13
|
const WITNESS_BIN = globalThis.WITNESS_SHIM || process.env.WITNESS_BIN || (existsSync(platformBin) ? platformBin : "")
|
|
14
14
|
|
|
15
|
+
// Warn ONCE, non-throwing, when the plugin is genuinely inert: no witness binary
|
|
16
|
+
// resolved for this platform/arch. Every hook below early-returns on an empty
|
|
17
|
+
// WITNESS_BIN, so without this a user on darwin-x64 / linux-arm64 / win32 (no
|
|
18
|
+
// matching optional package) sees the plugin load with zero diagnostic and
|
|
19
|
+
// believes witness is capturing when nothing runs (issue #54 I4). Mirrors the
|
|
20
|
+
// clear message the CLI (bin/witness.js) already prints. Suppressed inside the
|
|
21
|
+
// worker subprocess (WITNESS_WORKER=1) so the recursion guard stays quiet, and a
|
|
22
|
+
// warn must never throw — capture/plugin code must never break an OpenCode session.
|
|
23
|
+
function warnIfInert() {
|
|
24
|
+
if (WITNESS_BIN || process.env.WITNESS_WORKER === "1") return
|
|
25
|
+
try {
|
|
26
|
+
const pkg = platformPackage()
|
|
27
|
+
const reason = pkg ? `optional package ${pkg} is not installed` : `unsupported platform ${process.platform}/${process.arch}`
|
|
28
|
+
console.warn(`witness: plugin inactive — ${reason}; nothing is being captured. Supported platforms: ${supportedPlatforms()}`)
|
|
29
|
+
} catch {
|
|
30
|
+
// Never let a diagnostic break the session.
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
15
34
|
function spawnWitness(args, payload) {
|
|
16
35
|
if (!WITNESS_BIN || process.env.WITNESS_WORKER === "1") return
|
|
17
36
|
try {
|
|
@@ -54,6 +73,7 @@ function waitForExit(child) {
|
|
|
54
73
|
}
|
|
55
74
|
|
|
56
75
|
const plugin = async () => {
|
|
76
|
+
warnIfInert()
|
|
57
77
|
let disposed = false
|
|
58
78
|
let disposing = false
|
|
59
79
|
let disposePromise = null
|
package/prompts/lens/example.md
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
# name: math
|
|
2
|
-
# dimensions: speed, independence, proof_rigor, abstraction, confusion_tolerance
|
|
3
|
-
|
|
4
|
-
<!--
|
|
5
|
-
A complete, ready-to-register example lens (a "math learner" lens).
|
|
6
|
-
|
|
7
|
-
Copy it, rewrite the dimensions and the two prompts for your domain, then:
|
|
8
|
-
witness lens register math ./this-file.md
|
|
9
|
-
witness lens enable math
|
|
10
|
-
|
|
11
|
-
The `# name:` / `# dimensions:` lines above are real lens directives (the loader
|
|
12
|
-
parses them). The two sections below are passed VERBATIM as the system prompt for
|
|
13
|
-
their pass — they fully REPLACE the built-in `default` prompts, they don't extend
|
|
14
|
-
them — so each must be self-contained, INCLUDING its output JSON schema. The tool
|
|
15
|
-
appends the transcript (EXTRACT) or the accumulated observations (REVIEW) as the
|
|
16
|
-
user message; it injects no schema for you. Anything outside the two `##` sections
|
|
17
|
-
(like this comment) is ignored by the loader.
|
|
18
|
-
-->
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
## EXTRACT
|
|
22
|
-
You are observing one study/work session between a person and an AI, through a
|
|
23
|
-
MATH-LEARNING lens. Notice things about *the person as a mathematician* — how they
|
|
24
|
-
reason, where they get stuck, and how they climb out — not the math facts themselves.
|
|
25
|
-
|
|
26
|
-
Tag each observation with exactly one dimension:
|
|
27
|
-
- speed — how fast they move; when they deliberately slow down vs. rush past a gap.
|
|
28
|
-
- independence — do they attempt before asking; how much scaffolding they need.
|
|
29
|
-
- proof_rigor — care with quantifiers, edge cases, and "why is this actually true?"
|
|
30
|
-
- abstraction — comfort moving between concrete instances and general statements.
|
|
31
|
-
- confusion_tolerance — how they sit with not-understanding before resolving it.
|
|
32
|
-
|
|
33
|
-
What makes a GOOD observation:
|
|
34
|
-
- Atomic — one noticed thing, one sentence.
|
|
35
|
-
- Evidence-anchored — cite a short quote or paraphrase of the exact moment. No anchor, don't write it.
|
|
36
|
-
- About the PERSON and durable-ish — "checked the base case unprompted" counts; "solved problem 3" is a task-fact, skip it.
|
|
37
|
-
- Honest — note struggles, shortcuts, and regressions as readily as wins. Never invent failings or wins.
|
|
38
|
-
|
|
39
|
-
Score poignancy 1-10 — how much a future reviewer should weight it for growth.
|
|
40
|
-
Most are 3-6; reserve 7+ for a genuine mindset shift or a precise self-diagnosis.
|
|
41
|
-
|
|
42
|
-
If the session was routine and nothing person-relevant happened, return `[]`.
|
|
43
|
-
Do not manufacture observations to fill space.
|
|
44
|
-
|
|
45
|
-
Return ONLY a JSON array, no prose around it. Each element:
|
|
46
|
-
[
|
|
47
|
-
{
|
|
48
|
-
"dimension": "proof_rigor",
|
|
49
|
-
"observation": "Stopped to verify the base case unprompted after a hand-wavy induction.",
|
|
50
|
-
"evidence": "\"wait — does n=0 actually hold here?\" before moving on",
|
|
51
|
-
"poignancy": 6
|
|
52
|
-
}
|
|
53
|
-
]
|
|
54
|
-
|
|
55
|
-
## REVIEW
|
|
56
|
-
You are the reviewer for the MATH lens of a long-term, person-centric growth
|
|
57
|
-
archive. You read the accumulated observations plus the current facets, and you
|
|
58
|
-
assert what is true NOW, flagging genuine, sustained CHANGE over time.
|
|
59
|
-
|
|
60
|
-
How to synthesize:
|
|
61
|
-
- Group related observations into few, sharp, falsifiable facets within the dimensions above.
|
|
62
|
-
- Name facet keys in snake_case, emergent from the evidence; reuse an existing key when updating it.
|
|
63
|
-
- Every facet must cite the supporting observation IDs in `because_of`. No citation → no facet.
|
|
64
|
-
- Prefer "attempts an approach before asking for help" (falsifiable) over "is good at math" (not).
|
|
65
|
-
|
|
66
|
-
The change rule (most important):
|
|
67
|
-
- Set `contradicts_prior: true` ONLY for a sustained, repeated pattern that
|
|
68
|
-
conflicts with the stored current value. One off-pattern session is noise, not
|
|
69
|
-
a reversal.
|
|
70
|
-
- A time-bound `state`-like facet that has clearly passed can also flip.
|
|
71
|
-
- Mere absence of recent evidence is NOT change. Never invent a "used to do X,
|
|
72
|
-
stopped" arc — if you can't cite observation IDs for the NEW value, it isn't a change.
|
|
73
|
-
|
|
74
|
-
Confidence 0-1: 0.3-0.5 emerging; 0.6-0.8 well-supported across sessions; 0.9+ pervasive.
|
|
75
|
-
|
|
76
|
-
Return ONLY a JSON array, no surrounding prose. Each element:
|
|
77
|
-
[
|
|
78
|
-
{
|
|
79
|
-
"dimension": "independence",
|
|
80
|
-
"key": "attempts_before_asking",
|
|
81
|
-
"value": "Sketches an approach and tests it before reaching for help; a few months ago asked first.",
|
|
82
|
-
"confidence": 0.7,
|
|
83
|
-
"because_of": ["obs_8f2a3c", "obs_3c1190"],
|
|
84
|
-
"contradicts_prior": true
|
|
85
|
-
}
|
|
86
|
-
]
|
package/prompts/lens/opencode.md
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
# name: opencode
|
|
2
|
-
# dimensions: agent_collaboration, tool_discipline, verification, context_management, autonomy_calibration, opencode_usage_preference
|
|
3
|
-
|
|
4
|
-
<!--
|
|
5
|
-
A ready-to-register lens for OpenCode sessions:
|
|
6
|
-
|
|
7
|
-
witness lens register opencode prompts/lens/opencode.md
|
|
8
|
-
witness lens enable opencode
|
|
9
|
-
|
|
10
|
-
It observes how a person collaborates with agentic coding tools, especially
|
|
11
|
-
OpenCode: what they delegate, how they steer, how they verify, and where their
|
|
12
|
-
workflow is becoming more or less disciplined.
|
|
13
|
-
-->
|
|
14
|
-
|
|
15
|
-
## EXTRACT
|
|
16
|
-
|
|
17
|
-
You are observing one work session between a person and an AI coding agent through an OPENCODE-WORKFLOW lens. Notice things about the person as an operator of agentic coding tools: how they frame work, delegate, inspect evidence, correct course, use tools, verify outcomes, and calibrate autonomy.
|
|
18
|
-
|
|
19
|
-
Focus on person-centric growth/change, not on the task result. Good observations are anchored in concrete moments and reveal a reusable pattern in how the person works with agents.
|
|
20
|
-
|
|
21
|
-
Dimensions:
|
|
22
|
-
|
|
23
|
-
- agent_collaboration: how the person frames goals, constraints, feedback, and division of labor with the agent.
|
|
24
|
-
- tool_discipline: how they choose, sequence, or constrain tools and data access.
|
|
25
|
-
- verification: how they ask for, design, or interpret verification evidence.
|
|
26
|
-
- context_management: how they preserve, recover, or compress project/session context.
|
|
27
|
-
- autonomy_calibration: when they let the agent proceed, when they intervene, and how they handle uncertainty or risk.
|
|
28
|
-
- opencode_usage_preference: what they prefer OpenCode for, which OpenCode workflows/models/data sources they trust, and when they choose OpenCode-specific affordances over Claude Code or generic agent workflows.
|
|
29
|
-
|
|
30
|
-
Rules:
|
|
31
|
-
|
|
32
|
-
- Evidence-anchored only. Every observation must cite a short concrete phrase or event from the session.
|
|
33
|
-
- Person-centric only. Do not write observations like "implemented X" unless it reveals how the person works.
|
|
34
|
-
- Prefer specific behavioral patterns over generic praise.
|
|
35
|
-
- If the session is routine or contains no person-relevant signal, return `[]`.
|
|
36
|
-
- Return 0-8 observations.
|
|
37
|
-
|
|
38
|
-
Return ONLY a JSON array. Each element must be:
|
|
39
|
-
|
|
40
|
-
[{ "dimension": "agent_collaboration", "observation": "one concise person-centric observation", "evidence": "short quote or paraphrase from the session", "poignancy": 1 }]
|
|
41
|
-
|
|
42
|
-
Poignancy is 1-10: 1-3 minor signal, 4-6 useful recurring-pattern signal, 7-10 unusually clear change/risk/breakthrough.
|
|
43
|
-
|
|
44
|
-
## REVIEW
|
|
45
|
-
|
|
46
|
-
You are the reviewer for the OPENCODE-WORKFLOW lens of a long-term person-centric growth archive. You are given atomic observations about how the person works with agentic coding tools and the current stored facets for this lens.
|
|
47
|
-
|
|
48
|
-
Synthesize observations into a small set of stable, falsifiable facets about the person's agentic workflow. Each facet should name a durable pattern, not a one-off event. Preserve change over time: only mark `contradicts_prior: true` when the observations show a sustained new pattern that genuinely conflicts with the current value.
|
|
49
|
-
|
|
50
|
-
Facet guidance:
|
|
51
|
-
|
|
52
|
-
- agent_collaboration facets can describe goal framing, feedback style, delegation boundaries, or how the person corrects the agent.
|
|
53
|
-
- tool_discipline facets can describe how they inspect sources, avoid unsafe operations, or prefer evidence over assumptions.
|
|
54
|
-
- verification facets can describe test selection, acceptance criteria, and how much proof they require.
|
|
55
|
-
- context_management facets can describe how they use local memory, docs, databases, handoffs, or summaries.
|
|
56
|
-
- autonomy_calibration facets can describe when they push for autonomous execution versus pausing for decisions.
|
|
57
|
-
- opencode_usage_preference facets can describe when the person prefers OpenCode, which OpenCode-native evidence or models they ask for, and how they evaluate OpenCode-specific workflows compared with Claude Code.
|
|
58
|
-
|
|
59
|
-
Rules:
|
|
60
|
-
|
|
61
|
-
- Keep facets few and sharp. Avoid duplicating the same pattern under multiple names.
|
|
62
|
-
- Ground every facet in observation IDs from `because_of`.
|
|
63
|
-
- Do not infer personality, identity, or private facts beyond the evidence.
|
|
64
|
-
- Absence of evidence is not contradiction.
|
|
65
|
-
- Confidence 0-1: 0.3-0.5 emerging, 0.6-0.8 recurring, 0.9+ pervasive across sessions.
|
|
66
|
-
|
|
67
|
-
Return ONLY a JSON array. Each element must be:
|
|
68
|
-
|
|
69
|
-
[{ "dimension": "verification", "key": "diagnosis_before_action", "value": "The person increasingly asks the agent to inspect source evidence and verify with targeted commands before claiming completion.", "confidence": 0.7, "because_of": ["obs_abc123"], "contradicts_prior": false }]
|