@ponythewhite/base-context 1.0.14 → 1.0.16

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.
Files changed (90) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/base-context-runtime/pyproject.toml +1 -1
  3. package/dist/base-context-runtime/src/rlm/bash.py +19 -0
  4. package/dist/base-context-runtime/src/rlm/job_watch.py +156 -0
  5. package/dist/base-context-runtime/src/rlm/repl.md +28 -6
  6. package/dist/base-context-runtime/src/rlm/repl.py +6 -1
  7. package/dist/base-context-runtime/test/test_bash.py +4 -4
  8. package/dist/base-context-runtime/test/test_job_watch.py +67 -0
  9. package/dist/base-context-runtime/uv.lock +1 -1
  10. package/dist/build-info.json +1 -1
  11. package/dist/bundle/{bundled-modules-UODO7ZR7.js → bundled-modules-2DMTK7VK.js} +2 -2
  12. package/dist/bundle/{chunk-SX7CAXWU.js → chunk-MSH6QRP5.js} +1730 -867
  13. package/dist/bundle/{chunk-NLRWERWA.js → chunk-T2OK7SRV.js} +53 -21
  14. package/dist/bundle/{cli-main-6GXXIMQQ.js → cli-main-WL2L5IEQ.js} +2 -2
  15. package/dist/bundle/cli.js +1 -1
  16. package/dist/bundle/{main-HF64B4HM.js → main-XPIEIEQJ.js} +2 -2
  17. package/dist/core/agent-session.d.ts +2 -0
  18. package/dist/core/agent-session.d.ts.map +1 -1
  19. package/dist/core/agent-session.js +191 -33
  20. package/dist/core/agent-session.js.map +1 -1
  21. package/dist/core/compaction/compaction.d.ts +1 -1
  22. package/dist/core/compaction/compaction.d.ts.map +1 -1
  23. package/dist/core/compaction/compaction.js +11 -9
  24. package/dist/core/compaction/compaction.js.map +1 -1
  25. package/dist/core/history-index-worker.d.ts.map +1 -1
  26. package/dist/core/history-index-worker.js +22 -1
  27. package/dist/core/history-index-worker.js.map +1 -1
  28. package/dist/core/history-index.d.ts +2 -0
  29. package/dist/core/history-index.d.ts.map +1 -1
  30. package/dist/core/history-index.js.map +1 -1
  31. package/dist/core/inference-coordinator.d.ts.map +1 -1
  32. package/dist/core/inference-coordinator.js +13 -2
  33. package/dist/core/inference-coordinator.js.map +1 -1
  34. package/dist/core/job-watch.d.ts +120 -0
  35. package/dist/core/job-watch.d.ts.map +1 -0
  36. package/dist/core/job-watch.js +648 -0
  37. package/dist/core/job-watch.js.map +1 -0
  38. package/dist/core/kernel/repl-manager.d.ts +5 -1
  39. package/dist/core/kernel/repl-manager.d.ts.map +1 -1
  40. package/dist/core/kernel/repl-manager.js +57 -0
  41. package/dist/core/kernel/repl-manager.js.map +1 -1
  42. package/dist/core/kernel/shared.d.ts +12 -0
  43. package/dist/core/kernel/shared.d.ts.map +1 -1
  44. package/dist/core/kernel/shared.js.map +1 -1
  45. package/dist/core/prompts/rlm.d.ts.map +1 -1
  46. package/dist/core/prompts/rlm.js +49 -39
  47. package/dist/core/prompts/rlm.js.map +1 -1
  48. package/dist/core/session-manager.d.ts +10 -0
  49. package/dist/core/session-manager.d.ts.map +1 -1
  50. package/dist/core/session-manager.js +66 -1
  51. package/dist/core/session-manager.js.map +1 -1
  52. package/dist/core/tools/prime-context.d.ts.map +1 -1
  53. package/dist/core/tools/prime-context.js +1 -1
  54. package/dist/core/tools/prime-context.js.map +1 -1
  55. package/dist/modes/daemon/daemon-mode.d.ts.map +1 -1
  56. package/dist/modes/daemon/daemon-mode.js +17 -17
  57. package/dist/modes/daemon/daemon-mode.js.map +1 -1
  58. package/dist/modes/daemon/daemon-worker-client.d.ts +1 -0
  59. package/dist/modes/daemon/daemon-worker-client.d.ts.map +1 -1
  60. package/dist/modes/daemon/daemon-worker-client.js +8 -0
  61. package/dist/modes/daemon/daemon-worker-client.js.map +1 -1
  62. package/dist/modes/interactive/interactive-mode.d.ts +2 -0
  63. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  64. package/dist/modes/interactive/interactive-mode.js +31 -5
  65. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  66. package/dist/skills/agent-message/SKILL.md +8 -2
  67. package/dist/skills/bounded-inspect/SKILL.md +78 -0
  68. package/dist/skills/bounded-inspect/pyproject.toml +16 -0
  69. package/dist/skills/bounded-inspect/src/bounded_inspect/__init__.py +313 -0
  70. package/dist/skills/bounded-inspect/src/bounded_inspect/__main__.py +3 -0
  71. package/dist/skills/job-watch/SKILL.md +43 -0
  72. package/dist/skills/job-watch/pyproject.toml +13 -0
  73. package/dist/skills/job-watch/src/job_watch/__init__.py +61 -0
  74. package/dist/skills/rlm-heartbeat/SKILL.md +10 -6
  75. package/dist/utils/file-lines.d.ts.map +1 -1
  76. package/dist/utils/file-lines.js +6 -2
  77. package/dist/utils/file-lines.js.map +1 -1
  78. package/docs/rlm-runtime.md +4 -1
  79. package/docs/skills.md +18 -26
  80. package/docs/upstream-1.0.15.md +83 -0
  81. package/package.json +4 -4
  82. package/skills/agent-message/SKILL.md +8 -2
  83. package/skills/bounded-inspect/SKILL.md +78 -0
  84. package/skills/bounded-inspect/pyproject.toml +16 -0
  85. package/skills/bounded-inspect/src/bounded_inspect/__init__.py +313 -0
  86. package/skills/bounded-inspect/src/bounded_inspect/__main__.py +3 -0
  87. package/skills/job-watch/SKILL.md +43 -0
  88. package/skills/job-watch/pyproject.toml +13 -0
  89. package/skills/job-watch/src/job_watch/__init__.py +61 -0
  90. package/skills/rlm-heartbeat/SKILL.md +10 -6
@@ -1 +1 @@
1
- {"version":3,"file":"file-lines.js","sourceRoot":"","sources":["../../src/utils/file-lines.ts"],"names":[],"mappings":"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","sourcesContent":["import { closeSync, createReadStream, openSync, readSync } from \"node:fs\";\n\nexport function readFirstLineBufferSync(\n\tfilePath: string,\n\tmaxBytes = 64 * 1024,\n\tallowIncomplete = false,\n): Buffer | undefined {\n\tconst fd = openSync(filePath, \"r\");\n\tconst chunks: Buffer[] = [];\n\tlet position = 0;\n\ttry {\n\t\tconst buffer = Buffer.alloc(1024);\n\t\twhile (position < maxBytes) {\n\t\t\tconst count = readSync(fd, buffer, 0, Math.min(buffer.length, maxBytes - position), position);\n\t\t\tif (count === 0) break;\n\t\t\tconst chunk = buffer.subarray(0, count);\n\t\t\tconst newline = chunk.indexOf(0x0a);\n\t\t\tif (newline !== -1) {\n\t\t\t\tchunks.push(Buffer.from(chunk.subarray(0, newline + 1)));\n\t\t\t\treturn Buffer.concat(chunks);\n\t\t\t}\n\t\t\tchunks.push(Buffer.from(chunk));\n\t\t\tposition += count;\n\t\t}\n\t} finally {\n\t\tcloseSync(fd);\n\t}\n\treturn allowIncomplete && chunks.length > 0 ? Buffer.concat(chunks) : undefined;\n}\n\nexport function readFirstLineSync(filePath: string, maxBytes = 64 * 1024, completeOnly = false): string | undefined {\n\treturn readFirstLineBufferSync(filePath, maxBytes, !completeOnly)\n\t\t?.toString(\"utf8\")\n\t\t.replace(/\\n$/, \"\")\n\t\t.replace(/\\r$/, \"\");\n}\n\nexport async function* readLinesAsBuffers(\n\tfilePath: string,\n\toptions: { maxLineBytes?: number; includeNewline?: boolean; completeOnly?: boolean } = {},\n): AsyncGenerator<Buffer> {\n\tconst maxBytes = options.maxLineBytes ?? Infinity;\n\tif (maxBytes <= 0 || (maxBytes !== Infinity && !Number.isSafeInteger(maxBytes)))\n\t\tthrow new Error(\"Invalid line byte limit\");\n\tconst pendingParts: Buffer[] = [];\n\tlet pendingBytes = 0;\n\tfor await (const chunk of createReadStream(filePath)) {\n\t\tconst buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n\t\tlet start = 0;\n\t\twhile (start < buffer.length) {\n\t\t\tconst end = buffer.indexOf(0x0a, start);\n\t\t\tconst stop = end === -1 ? buffer.length : end + (options.includeNewline ? 1 : 0);\n\t\t\tconst part = buffer.subarray(start, stop);\n\t\t\tif (pendingBytes + part.length > maxBytes) throw new Error(\"Line byte limit exceeded\");\n\t\t\tif (end === -1) {\n\t\t\t\tpendingParts.push(part);\n\t\t\t\tpendingBytes += part.length;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (pendingParts.length > 0) {\n\t\t\t\tpendingParts.push(part);\n\t\t\t\tconst line = Buffer.concat(pendingParts, pendingBytes + part.length);\n\t\t\t\tpendingParts.length = 0;\n\t\t\t\tpendingBytes = 0;\n\t\t\t\tyield line;\n\t\t\t} else yield part;\n\t\t\tstart = end + 1;\n\t\t}\n\t}\n\tif (pendingParts.length > 0 && !options.completeOnly) yield Buffer.concat(pendingParts, pendingBytes);\n}\n"]}
1
+ {"version":3,"file":"file-lines.js","sourceRoot":"","sources":["../../src/utils/file-lines.ts"],"names":[],"mappings":"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","sourcesContent":["import { closeSync, createReadStream, openSync, readSync } from \"node:fs\";\n\nexport function readFirstLineBufferSync(\n\tfilePath: string,\n\tmaxBytes = 64 * 1024,\n\tallowIncomplete = false,\n): Buffer | undefined {\n\tconst fd = openSync(filePath, \"r\");\n\tconst chunks: Buffer[] = [];\n\tlet position = 0;\n\ttry {\n\t\tconst buffer = Buffer.alloc(1024);\n\t\twhile (position < maxBytes) {\n\t\t\tconst count = readSync(fd, buffer, 0, Math.min(buffer.length, maxBytes - position), position);\n\t\t\tif (count === 0) break;\n\t\t\tconst chunk = buffer.subarray(0, count);\n\t\t\tconst newline = chunk.indexOf(0x0a);\n\t\t\tif (newline !== -1) {\n\t\t\t\tchunks.push(Buffer.from(chunk.subarray(0, newline + 1)));\n\t\t\t\treturn Buffer.concat(chunks);\n\t\t\t}\n\t\t\tchunks.push(Buffer.from(chunk));\n\t\t\tposition += count;\n\t\t}\n\t} finally {\n\t\tcloseSync(fd);\n\t}\n\treturn allowIncomplete && chunks.length > 0 ? Buffer.concat(chunks) : undefined;\n}\n\nexport function readFirstLineSync(filePath: string, maxBytes = 64 * 1024, completeOnly = false): string | undefined {\n\treturn readFirstLineBufferSync(filePath, maxBytes, !completeOnly)\n\t\t?.toString(\"utf8\")\n\t\t.replace(/\\n$/, \"\")\n\t\t.replace(/\\r$/, \"\");\n}\n\nexport async function* readLinesAsBuffers(\n\tfilePath: string,\n\toptions: { maxLineBytes?: number; includeNewline?: boolean; completeOnly?: boolean } = {},\n): AsyncGenerator<Buffer> {\n\tconst maxBytes = options.maxLineBytes ?? Infinity;\n\tif (maxBytes <= 0 || (maxBytes !== Infinity && !Number.isSafeInteger(maxBytes)))\n\t\tthrow new Error(\"Invalid line byte limit\");\n\tconst pendingParts: Buffer[] = [];\n\tlet pendingBytes = 0;\n\tfor await (const chunk of createReadStream(filePath)) {\n\t\tconst buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n\t\tlet start = 0;\n\t\twhile (start < buffer.length) {\n\t\t\tconst end = buffer.indexOf(0x0a, start);\n\t\t\tconst stop = end === -1 ? buffer.length : end + (options.includeNewline ? 1 : 0);\n\t\t\tconst part = buffer.subarray(start, stop);\n\t\t\tif (pendingBytes + part.length > maxBytes) throw new Error(\"Line byte limit exceeded\");\n\t\t\tif (end === -1) {\n\t\t\t\tpendingParts.push(part);\n\t\t\t\tpendingBytes += part.length;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (pendingParts.length > 0) {\n\t\t\t\tpendingParts.push(part);\n\t\t\t\tconst line = Buffer.concat(pendingParts, pendingBytes + part.length);\n\t\t\t\tpendingParts.length = 0;\n\t\t\t\tpendingBytes = 0;\n\t\t\t\tyield line;\n\t\t\t} else yield part;\n\t\t\tstart = end + 1;\n\t\t}\n\t}\n\tif (pendingParts.length > 0 && !options.completeOnly) {\n\t\tconst line = Buffer.concat(pendingParts, pendingBytes);\n\t\tpendingParts.length = 0;\n\t\tpendingBytes = 0;\n\t\tyield line;\n\t}\n}\n"]}
@@ -90,6 +90,7 @@ Requests flow to the runtime on stdin and events return on stdout, one JSON obje
90
90
 
91
91
  ```text
92
92
  requests execute, interrupt, host_reply, snapshot, restore, list_names, shutdown
93
+ optional job_watch_probe (job_watch_probe_v1 capability)
93
94
  events ready, stdout, stderr, result, display, host_request, error, done
94
95
  ```
95
96
 
@@ -97,6 +98,8 @@ Output events carry the id of the cell that was running when the bytes were prod
97
98
 
98
99
  Calls to `ReplKernelManager.execute()` are serialized. One kernel has one shared namespace and does not run two ordinary Python cells concurrently. RLM child agents can still run concurrently because each delegation uses a distinct host request and child runtime.
99
100
 
101
+ The optional `job_watch_probe_v1` ready capability supports contained read-only probes outside the cell FIFO and passive Bash completion callbacks. `AgentSession` schedules and compares observations before model admission, then uses ordinary prepared follow-ups. Explicit parking gates goal and autonomous continuation, not user input or unrelated work. No daemon protocol version changes; an older runtime without the capability is refused locally. See [job-watch](../skills/job-watch/SKILL.md) for reporting, restoration, and supported backlog limits.
102
+
100
103
  ## Host-Request Event Flow
101
104
 
102
105
  A running cell can await task admission:
@@ -173,7 +176,7 @@ test_review = await rlm("review the tests", name="test-reviewer")
173
176
  audit = await rlm("slow independent audit", name="audit-reviewer")
174
177
  ```
175
178
 
176
- End the turn instead of waiting for completion. Children send requested answers with `await agent_message.send(message, receiver_role="parent")`, and replies arrive as ordinary agent messages over later turns. A child may instead write results to files for the parent to read. The host runs each admitted child as an independent `AgentSession`; daemon-backed children can be retained as independently addressable session workers.
179
+ End the turn instead of waiting for completion. Use `agent_message.send` for short coordination and `await agent_message.send_result(summary, findings, receiver_role="parent")` for substantial findings or final reports. Replies arrive over later turns; recover capsule details only when needed. Without that capability, use files for fan-in. The host runs each admitted child as an independent `AgentSession`; daemon-backed children can be retained as independently addressable session workers.
177
180
 
178
181
  ## Parent-Scoped Sub-Agent Registry
179
182
 
package/docs/skills.md CHANGED
@@ -51,6 +51,8 @@ Base Context ships with built-in skills that load by default:
51
51
 
52
52
  - `skill-creator` - teaches the agent to create new skills: markdown skill layout, frontmatter rules, placement and precedence, and the full Python-backed skill contract (package layout, `run()` convention, optional CLI, kernel venv behavior) with a working template in `references/python-skills.md`.
53
53
  - `websearch` - a Python-backed Google search skill using the [Serper](https://serper.dev) API.
54
+ - [`job-watch`](../skills/job-watch/SKILL.md) - native job completion/probe monitoring, prepared reports, and scoped goal/autonomous waiting. Launch jobs through `bash()` or existing authorized helpers.
55
+ - [`bounded-inspect`](../skills/bounded-inspect/SKILL.md) - selected text/JSON evidence under shared source and serialized-output budgets. Historical conversation recovery remains with `prime_context`.
54
56
 
55
57
  Built-in skills behave like any other skill but have the lowest precedence: a user, project, package, or `--skill` skill with the same name overrides the built-in one.
56
58
 
@@ -138,8 +140,9 @@ This is progressive disclosure: only descriptions are always in context, full in
138
140
 
139
141
  For native epochs, select an advertised skill with
140
142
  `prime_context` using `{"action":"skill","name":"..."}`. The response gives its
141
- captured body and canonical source reference. Use the returned ref and field with
142
- `action="read"` for bounded recovery; do not reopen the mutable location to replace
143
+ captured body and canonical source reference. If the complete body is already
144
+ in context, no duplicate read is needed. For later bounded recovery, use the
145
+ returned ref and field with `action="read"`; do not reopen the mutable location to replace
143
146
  a selected version. A committed epoch keeps that selected descriptor and instruction
144
147
  body. After an existing context transition commits a new epoch, a later selection
145
148
  can capture updated contents. The original captured body remains recoverable from
@@ -157,18 +160,19 @@ Skills with `disable-model-invocation: true` are hidden from the startup skill l
157
160
 
158
161
  For repeated multi-step work, start with an ordinary named Python function in
159
162
  `ipython`. Keep one-off operations inline and prefer an existing project command
160
- when it already does the work. Give changing paths, selectors, output paths and
161
- options explicit parameters. Reuse the code, not its previous answer: read current
163
+ when it already does the work. Pass the current commit, configuration, paths,
164
+ resource identity, selectors and limits explicitly where applicable. Reuse the code, not its previous answer: read current
162
165
  inputs on every call. Do not capture an open handle or hidden mutable REPL state.
163
166
 
164
- After two useful occurrences across tasks, or an explicit request for reuse, save
165
- the function in an editable `.py` file with a short project markdown skill. This
166
- is a practical heuristic, not a repetition detector. A small helper needs no
167
+ After two useful occurrences, or an explicit request for reuse, save the function
168
+ in a small editable project `.py` file. Short project instructions are optional;
169
+ no new global skill is needed. This is a practical heuristic, not a repetition
170
+ detector. A small helper needs no
167
171
  `pyproject.toml`, package installation, manifest or promotion step. Use the standard
168
172
  library and dependencies already available in the selected environment.
169
173
 
170
- For example, save `scripts/matching_lines.py` in
171
- `.base-context/skills/matching-lines/`:
174
+ For example, save `scripts/matching_lines.py` in the project. This example is
175
+ for small files; use `bounded-inspect` for potentially large evidence:
172
176
 
173
177
  ```python
174
178
  from pathlib import Path
@@ -188,26 +192,13 @@ def matching_lines(path: str, needle: str, limit: int = 20) -> list[tuple[int, s
188
192
  return matches
189
193
  ```
190
194
 
191
- Add the ordinary `SKILL.md` next to `scripts/`:
192
-
193
- ```markdown
194
- ---
195
- name: matching-lines
196
- description: Read current UTF-8 files for repeated literal line lookups. Inputs are path, needle and limit; output is a list of one-based line numbers and text.
197
- ---
198
- Load scripts/matching_lines.py afresh with runpy.run_path, then call
199
- matching_lines(path, needle, limit=20). Resolve the script path against this
200
- skill directory. No matches returns an empty list; ordinary errors propagate.
201
- ```
202
-
203
- Only the short skill description enters discovery. Load the instructions and code
204
- when the active task needs them. For this standard-library helper, a fresh load
205
- and call in `ipython` can be:
195
+ For this standard-library helper, load the saved file afresh and call it in
196
+ `ipython`. No registration or package installation is needed:
206
197
 
207
198
  ```python
208
199
  from runpy import run_path
209
200
 
210
- matching_lines = run_path("/repo/.base-context/skills/matching-lines/scripts/matching_lines.py")["matching_lines"]
201
+ matching_lines = run_path("/repo/scripts/matching_lines.py")["matching_lines"]
211
202
  matches = matching_lines("/repo/current.txt", "needle", limit=20)
212
203
  ```
213
204
 
@@ -217,7 +208,8 @@ use the project's own environment instead of installing them into the kernel.
217
208
  Fresh execution of editable code does not replace the captured instruction body
218
209
  of an active native skill epoch.
219
210
 
220
- Saving a helper does not schedule or authorize execution. Invocation still needs
211
+ Repetition never authorizes another deployment or experiment. Saving a helper
212
+ does not schedule or authorize execution. Invocation still needs
221
213
  the normal model/tool decision or an explicit user workflow, under the existing
222
214
  permissions. Do not add an import manager, dependency snapshots or per-call setup.
223
215
 
@@ -0,0 +1,83 @@
1
+ # Prime Agent selection for Base Context 1.0.15
2
+
3
+ This is a selective adaptation, not an upstream merge.
4
+
5
+ Base Context forked Prime Agent 0.9.3 at
6
+ `915c78f42c248b08238dd27fcd4bcab32c60beab`. This review screened all 222
7
+ subsequent commits through `2d24ad4e6b2d1ee8e6919af6f108e980a14d550e`
8
+ (2026-09-27): 10 through 0.9.4, the 113 commits covered by the prior
9
+ [0.9.5 selection](upstream-0.9.5.md), and 99 after 0.9.5. Relevant runtime,
10
+ compaction, goal, and workflow changes received focused source comparison;
11
+ this is not a full audit of every changed function.
12
+
13
+ The latest stable release in this review was Prime Agent 0.9.6,
14
+ `e260085dd8f742e0def3d871860c9a888b114851`, published 2026-09-24. Six later
15
+ main commits were also screened. A commit can be absent from fork ancestry
16
+ while its selected behavior is already implemented locally.
17
+
18
+ ## Selected small fixes
19
+
20
+ | Exact upstream commit | Adaptation |
21
+ |---|---|
22
+ | `a0660bb5f823bcd9490a83ca3e822d7d53f36e24` | Clear a failed direct daemon-worker connection's socket and channel references, so the same client can retry after a connection error or timeout. Keep Base Context's native-owner, compatibility, and probe-timeout handling. Do not refactor the already-correct daemon-client connection path merely to share a helper. |
23
+ | `b6b94c78a7747997e0ec6c690c0e8f2a563dbe14` | Add the missing kernel stderr stream error listener, matching the existing stdin/stdout listeners. Record the diagnostic without taking cleanup ownership from pending writes and child exit. |
24
+
25
+ These changes add no provider, model, daemon command, wire shape, or protocol
26
+ version. Focused coverage belongs in the existing `daemon-client.test.ts` and
27
+ `repl-kernel-pipe-errors.test.ts` files. Test outcomes belong to the change's
28
+ validation record, not to this upstream-selection rationale.
29
+
30
+ ## Relevant decisions
31
+
32
+ Upstream commits can be viewed at
33
+ `https://github.com/PrimeIntellect-ai/prime-agent/commit/<commit>`.
34
+
35
+ | Exact upstream commit | Decision | Reason |
36
+ |---|---|---|
37
+ | `90ca4a457e0fef0bd925215d4c973abd6264f067` | Already adapted | Kernel stdin/stdout pipe errors are already handled. Keep that behavior; only stderr was missing. |
38
+ | `55ade48b73f636d992855b7cab797d71dc1f6f1c` | Already adapted | LiteLLM overflow recognition and rate-limit exclusions already match upstream. A local history-source limit is not a provider context overflow. |
39
+ | `8eaa00c37385c6b25fed9d46584b50ffc2e87f9c` | Already adapted | Blocked input-pump idle waits already yield, with additional native settlement/admission guards. |
40
+ | `b3e04b58b358ae9adc02387e6d01937ef9f8064f` | Defer native adaptation | Restoring non-durable next-turn prefixes from every cancelled turn is relevant, but must preserve the native action/source owner. Not part of the two isolated runtime patches. |
41
+ | `c4afa57352e71a8532f04ef04a09ce14720ddeca` | Defer | Deriving displayed activity from actual session activity rather than summary freshness is useful, but is a separate UI/state change. |
42
+ | `bcdcd6e65e10959c9904ec4467747528303493b0` | Defer native adaptation | Manual-compaction goal resume must use Base Context's captured-owner continuation lifecycle, not upstream queue scheduling. |
43
+ | `215e7a7409b2931b49d3aad62d29fa8e94345973` | Defer native adaptation | Same-goal accounting should remain monotonic across summary moves, without applying maxima across unrelated goals or deliberate branch navigation. The upstream reload helper has been replaced locally. |
44
+ | `9bd6a9bc0fbc1e4072cfd7162f855a305c39efb0` | Defer native adaptation | Refresh queued goal accounting at a native admission/capture boundary; do not copy upstream in-place mutation of accepted message content. |
45
+ | `2e43ebca3753c82ed0ef2064cb14081588ebd4d3`, `b08f08efad6830856318e994447162ba3fd4c6ee` | Reject as-is | Blanket continuation pauses while children or background shells run prevent independent work. A running resource does not establish a dependency. |
46
+ | `5fb3d9acbafa06ae9228c49a4b8a4eca9abc0997` | Defer summary adaptation | Tool name, error status, and matching call indices improve summary input, but change prompt representation and need to fit native context budgets. |
47
+ | `27f32ddb7e99803555c4654c9ce38edad3e90e22` | Defer summary adaptation | Strip repeated mechanical file lists if adopted. Kept-tail recency must not promote assistant statements over user constraints or TaskFrame authority. Silent list caps are not acceptable substitutes for visible limits. |
48
+ | `6be5d4f297f112df8b57b6807de9405c5444fc0f`, `f31c440c788499a4ba49736acbf1504a25e3ad4c` | Retain prior deferral | Head/tail excerpts and kernel-reported file paths change summary selection. Retain recoverable original evidence; do not silently cap file lists or promote tool observations to task authority. |
49
+ | `4f6df9d14385368a148c22e65dfc6050fbb984f1` | Reject routing policy | Automatic auxiliary-model fallback and suppressed reasoning would override explicit compaction model/effort selection. Native request budgeting remains authoritative. |
50
+ | `c91e6e991fc006098ea21c3640eed3bdd268c222`, `0e3c900225f8beea4ecd57180902d437cd394117`, `2d24ad4e6b2d1ee8e6919af6f108e980a14d550e` | Defer larger runtime change | Bounded frames/payloads and linear protocol reading are a coherent later adaptation, not part of the stderr listener fix. They do not fix full-parent history hydration. |
51
+ | `8ee46be35b6fcc4ab28aa6d524aeed1fff69ffe4` | Defer larger runtime change | Restored functions need live namespace globals, but the revival change must preserve native staged restore and interrupt behavior. No dill/restore rewrite is included here. |
52
+ | `561401b273b5affa3877aae51e3b44ce201cc2d5` | Defer | Bound attached cell-source metadata separately from complete execution/canonical source. The upstream cap is characters plus a marker, not a byte limit. |
53
+ | `d73349d508075cb4d6c3d9d6eec677f029e294c8` | Defer legacy-only adaptation | The retained opt-in owned-worker frontend differs from normal daemon startup. Its cleanup may throw on corrupt tracking; copying upstream's error callback would bypass native cleanup reporting. |
54
+ | `ecd60e3cd4313643dede3cb2fcf13b4e2e9a2a75`, `66df06fc12d721c919d61c5ce4d6fb3ef0da479f` | Defer together | Consumed shell-notice withdrawal and its ordering fix form one optional workflow change. Preserve native action/source semantics. |
55
+ | `e2fb7bfa1372552d81c33e9b3261d6a9cf82d30f` | Defer product decision | Interrupt-and-send-queued changes user controls and adds a capability-gated command. It requires explicit selection and compatibility coverage, not a protocol-version transplant. |
56
+
57
+ ## Native context and command boundaries
58
+
59
+ Upstream does not implement Base Context's framed source/indexed working-view
60
+ architecture. Full-transcript branch caches and JSONL parse optimizations are
61
+ not repairs for a native source-byte refusal. Compaction must select required
62
+ source-backed views before hydrating unrelated old payloads. Captured owners,
63
+ replay groups, accepted epochs, recovery authorization, and acknowledged writes
64
+ must remain intact. A `baseContextEpoch` record is not necessarily a model-written
65
+ summary.
66
+
67
+ The `/goal` text parser is unchanged from upstream at the reviewed revisions.
68
+ Single-line objectives are supported; session slash commands reject multiline
69
+ input, and the command name must start at column zero. Changing that grammar is
70
+ a local product decision, not an upstream bug-fix transplant. Historical goal
71
+ regressions added by the commits above were removed in upstream
72
+ `cf07c5a3f5eca98e7744f2df83050044c920252a`; they are useful test vectors, not
73
+ claims about current upstream test coverage.
74
+
75
+ ## What stays out
76
+
77
+ All PrimeRL/Prime product provider, subscription, model, account, team, and
78
+ catalog integrations remain excluded. No implicit backup models, credential
79
+ migration, compiled installer migration, `rlm.spawn`/`collect` API replacement,
80
+ new ledger/audit system, or benchmark pipeline is introduced. Base Context keeps
81
+ explicit provider/auth/model/effort selection, its package and state roots,
82
+ callable `await rlm(...)`, native context authority, and independent-work policy.
83
+ Lawful upstream copyright and MIT attribution remain intact.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ponythewhite/base-context",
3
- "version": "1.0.14",
3
+ "version": "1.0.16",
4
4
  "description": "Synerise base-context: a coding and research agent with durable context and a persistent Python REPL",
5
5
  "type": "module",
6
6
  "bin": {
@@ -42,9 +42,9 @@
42
42
  },
43
43
  "dependencies": {
44
44
  "@agentclientprotocol/sdk": "^1.3.0",
45
- "@ponythewhite/base-context-agent": "1.0.14",
46
- "@ponythewhite/base-context-ai": "1.0.14",
47
- "@ponythewhite/base-context-tui": "1.0.14",
45
+ "@ponythewhite/base-context-agent": "1.0.16",
46
+ "@ponythewhite/base-context-ai": "1.0.16",
47
+ "@ponythewhite/base-context-tui": "1.0.16",
48
48
  "@silvia-odwyer/photon-node": "^0.3.4",
49
49
  "chalk": "^5.5.0",
50
50
  "cli-highlight": "^2.1.11",
@@ -62,7 +62,8 @@ if child is not None:
62
62
 
63
63
  ## Result capsules
64
64
 
65
- Use `send()` for short coordination. Use `send_result()` for a full public report:
65
+ Use `send()` for short steering, blockers, and decisions. Use `send_result()`
66
+ for substantial findings or a final public report, not for a short message:
66
67
 
67
68
  ```python
68
69
  from pathlib import Path
@@ -74,7 +75,9 @@ receipt = await agent_message.send_result(
74
75
  )
75
76
  ```
76
77
 
77
- State conclusions, caveats, and decisions in the capsule. If it revises or
78
+ State the outcome, important caveats, decisions, and evidence references in the
79
+ capsule. Child findings are evidence, not independently verified truth. Retrieve
80
+ details only when needed. If it revises or
78
81
  replaces earlier reports, name their exact report refs in the summary. With
79
82
  several updates, skim the capsules first, then retrieve the last relevant
80
83
  report or reports. Older reports remain readable. Do not treat unrelated
@@ -83,6 +86,9 @@ arrived. There is no automatic latest-wins, dropping, or coalescing.
83
86
 
84
87
  ## Safety
85
88
 
89
+ - Avoid routine acknowledgements and repeated status broadcasts. Messaging an
90
+ idle child can start another turn; not every message needs a reply.
91
+
86
92
  - Do not delete a child immediately after `send`: delivered follow-ups may still
87
93
  be running and queued receipts have not run yet. Wait until observation shows
88
94
  the child is idle and its context is no longer needed before calling
@@ -0,0 +1,78 @@
1
+ ---
2
+ name: bounded-inspect
3
+ description: Inspect selected text windows and JSON fields from project files under shared source and serialized-output byte budgets. Emit one source-linked bundle; continue within oversized lines without repeating full reads.
4
+ ---
5
+
6
+ # Bounded Inspect
7
+
8
+ Use for repeated, selective file inspection. Keep tiny one-off reads inline.
9
+ Historical conversation evidence belongs to `prime_context`, not this skill.
10
+ Filesystem paths and byte cursors are **not native recovery refs**.
11
+
12
+ ```python
13
+ bounded_inspect.emit(
14
+ bounded_inspect.text("runs/example/train.log", tail_lines=25),
15
+ bounded_inspect.json_fields("runs/example/metrics.json",
16
+ pointers=["/run", "/config", "/seed", "/eligible", "/failures",
17
+ "/units", "/updates", "/skips", "/wall"]),
18
+ max_bytes=4096, max_source_bytes=65536,
19
+ )
20
+ ```
21
+
22
+ Selectors are lazy; only `emit` reads. It prints one JSON object and returns
23
+ `None`, so a final cell expression does not duplicate the result. Stateless
24
+ extraction works in ordinary, goal, and AUTONOMOUS sessions. It does not park,
25
+ finish, or change autonomous limits. Consume the supplied evidence; do not
26
+ rerun its generating command merely to get a smaller answer.
27
+
28
+ ## API and coverage
29
+
30
+ - `text(path)` selects the first 25 lines. Choose one of `head_lines=N`,
31
+ `tail_lines=N`, `start_line=N, end_line=M`, or `cursor=item["next"]`.
32
+ Line ranges are 1-based and inclusive; omitted `end_line` means through EOF.
33
+ - `json_fields(path, pointers=[...], max_source_bytes=65536)` uses exact JSON
34
+ pointers, including `~0` and `~1` escapes. An empty pointer selects the root.
35
+ Null stays null. Missing fields, invalid JSON, unavailable files, and oversized
36
+ values have distinct statuses. Selected values are never string-sliced. Numeric
37
+ tokens stay exact, including exponents and nested values; no float conversion.
38
+ - `emit(*selectors, max_bytes=4096, max_source_bytes=65536)` shares both budgets
39
+ across all selectors, in order. `max_bytes` must be at least 128 for refusal
40
+ metadata. Raise explicit limits when necessary, not by an unbounded retry.
41
+
42
+ `output_bytes` counts the complete UTF-8 JSON serialization, escaping, metadata,
43
+ paths, warnings, and final newline. `source_bytes` counts bytes actually read,
44
+ not file size or OS device traffic. The enclosing tool/protocol envelope is
45
+ outside this budget; normal `ipython` retention still applies. `omitted` identifies
46
+ unreturned selector indices in the original call; `omitted_fields` counts the
47
+ unreturned suffix of requested pointers. Order important metadata first.
48
+
49
+ Text includes a stat version, half-open byte range, starting line (or null),
50
+ and next byte cursor. Partial Unicode lines advance at UTF-8 boundaries.
51
+ A continuation advances, finishes, or explicitly refuses. Source-limited line
52
+ seeking can return an empty window with an advancing cursor. Reuse the same
53
+ path and returned cursor; modification or replacement returns `changed_source`.
54
+ Stat tokens are practical guards, not immutable captures.
55
+
56
+ Tail reads only a bounded suffix. If it cannot establish the requested start,
57
+ `tail_prefix_unread` marks missing prefix coverage; terminal `tail_window_limit`
58
+ means that coverage is incomplete. Absolute line numbers may be unknown. JSON parsing refuses files above the explicit source ceiling before
59
+ reading. Large histories need a project-native summary producer, not larger
60
+ unbounded `json.load` calls. Select scientific units, run/config/seed identifiers,
61
+ eligibility, and failures together. Extraction does not infer quality crossings,
62
+ repair failed controls, or turn unavailable measurements into zero.
63
+
64
+ ## Run where the data lives
65
+
66
+ Use `python -m bounded_inspect`, or stage `src/bounded_inspect/__init__.py` once
67
+ and execute that file with standard-library Python through existing authorized
68
+ remote execution. Pass a JSON list on stdin:
69
+
70
+ ```json
71
+ [{"kind":"text","path":"train.log","tail_lines":25},
72
+ {"kind":"json","path":"metrics.json","pointers":["/run","/units","/wall"]}]
73
+ ```
74
+
75
+ CLI flags: `--max-bytes` and `--max-source-bytes`. No SSH setup is provided.
76
+ Save a small parameterized project parser after demonstrated reuse. Log full
77
+ execution evidence to explicit files when needed: this skill cannot recover
78
+ bytes that Bash or another capture already discarded.
@@ -0,0 +1,16 @@
1
+ [project]
2
+ name = "bounded-inspect"
3
+ version = "0.1.0"
4
+ description = "Bounded text and selected JSON file evidence"
5
+ requires-python = ">=3.10"
6
+ dependencies = []
7
+
8
+ [project.scripts]
9
+ bounded-inspect = "bounded_inspect:main"
10
+
11
+ [build-system]
12
+ requires = ["hatchling"]
13
+ build-backend = "hatchling.build"
14
+
15
+ [tool.hatch.build.targets.wheel]
16
+ packages = ["src/bounded_inspect"]