@prodero/curator 0.1.0 → 0.2.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/ARCHITECTURE.md +1 -1
- package/CHANGELOG.md +25 -2
- package/README.md +32 -33
- package/dist/cli.js +58 -20
- package/dist/contracts.js +1 -0
- package/dist/conversation-presentation.js +62 -27
- package/dist/core/agent-instructions.js +31 -18
- package/dist/core/curation-graphical.js +22 -10
- package/dist/core/curation-question.js +28 -0
- package/dist/core/curation-semantic-contract.js +4 -1
- package/dist/core/curation-semantic-jobs.js +78 -18
- package/dist/core/knowledge-graph.js +5 -4
- package/dist/core/local-preferences.js +76 -0
- package/dist/core/memory-index.js +2 -0
- package/dist/core/memory-link-repair.js +6 -2
- package/dist/core/memory-sync-curator.js +25 -5
- package/dist/core/memory-sync.js +124 -29
- package/dist/core/npm-update.js +289 -0
- package/dist/core/project.js +8 -8
- package/dist/core/session-index.js +10 -6
- package/dist/core/sessions.js +3 -3
- package/dist/core/settings.js +34 -16
- package/dist/core/skills.js +21 -2
- package/dist/core/storage.js +55 -1
- package/dist/core/sync-transaction.js +85 -49
- package/dist/core/update.js +9 -3
- package/dist/curation-review-adapter.js +1 -1
- package/dist/diagnostic-boundary.js +4 -3
- package/dist/memory-presentation.js +26 -16
- package/dist/memory-sync-operation.js +88 -0
- package/dist/presentation-server.js +25 -10
- package/dist/presentation.js +92 -61
- package/dist/server.js +59 -51
- package/dist/settings-definition.js +3 -3
- package/dist/status-presentation.js +20 -0
- package/dist/text-layout.js +278 -0
- package/dist/update-command.js +53 -0
- package/dist/update-instructions.js +4 -0
- package/dist-ui/index.html +117 -115
- package/docs/COMPATIBILITY.md +36 -15
- package/docs/MIGRATIONS.md +4 -0
- package/docs/RECOVERY.md +3 -1
- package/docs/RELEASING.md +69 -11
- package/docs/hosts.md +25 -7
- package/docs/images/prodero-context-ready-cropped.png +0 -0
- package/docs/images/prodero-overview-cropped.png +0 -0
- package/docs/images/prodero-session-learned-cropped.png +0 -0
- package/docs/ui-themes.md +10 -4
- package/instructions/AGENTS.md +24 -18
- package/package.json +6 -2
package/ARCHITECTURE.md
CHANGED
|
@@ -142,7 +142,7 @@ Set `PRODERO_DEBUG_TIMINGS=1` during local MCP development to emit fast response
|
|
|
142
142
|
|
|
143
143
|
Filesystem/stat/checkpoint discovery, status counts, pending detection, index routing, and token estimates are deterministic local operations and make no LLM/API call. Context Selection v2 retains the 6,000 estimated-token resolver budget and treats 2,000 tokens as a Required reserve, using the model-neutral `ceil(UTF-8 bytes / 4)` strategy. Applicable Required can borrow total capacity, with independent safety ceilings of 16,000 tokens / 128 records. Relevant uses a soft target of 8, deterministic marginal-value continuation and a 128-record safety ceiling. Strongly matching Skills receive capacity before Relevant, retaining 4 / 1,500 limits. Undelivered Required produces blocking `required-incomplete`; Open/Bootstrap and the derived router retain their compact limits. See [Context Selection v2](docs/CONTEXT-SELECTION-V2.md). Counts are explicitly estimated; these are Prodero-supplied task-context limits, never the model context window.
|
|
144
144
|
|
|
145
|
-
`memory-index.ts` caches per-item token, freshness, and provenance-count signals alongside lexical metadata. Context totals and selectivity sum cached summaries; only bounded selected bodies are loaded. Required globals are deterministically priority-ranked under separate item and token bounds, and omissions retain exact reason/count/token diagnostics. Ordinary Relevant omissions are nonblocking; incomplete Required delivery blocks readiness; only bounded metadata for omitted required items is disclosed. Query retrieval uses deterministic lexical scoring and greedy scope/category diversity. Non-critical active `state` records older than 180 days are retained
|
|
145
|
+
`memory-index.ts` caches per-item token, freshness, and provenance-count signals alongside lexical metadata. Context totals and selectivity sum cached summaries; only bounded selected bodies are loaded. Required globals are deterministically priority-ranked under separate item and token bounds, and omissions retain exact reason/count/token diagnostics. Ordinary Relevant omissions are nonblocking; incomplete Required delivery blocks readiness; only bounded metadata for omitted required items is disclosed. Query retrieval uses deterministic lexical scoring and greedy scope/category diversity. Non-critical active `state` records older than 180 days are retained and flagged stale when selected. Already eligible Relevant candidates receive a bounded storage-recency hint (0–0.5); there is no separate 180-day rank penalty, and Required policy ranking is unchanged. Storage update time is not a fact-effective date. Detailed memory health counts stale, disputed, historical, incomplete-provenance, and oversized items; fast status still touches none of the corpus. The compatibility field `missingProvenanceItems` counts active records with no source-session/source-file evidence or no observation-level `derived_from`. It measures incomplete metadata, not proven loss of history or the validity of every source reference. Legacy/imported records remain readable; no provenance is invented or backfilled by diagnostics.
|
|
146
146
|
|
|
147
147
|
Sync telemetry is derived from the same pending candidates already in consolidation. `rawSessionTokens` counts durable observation content in the current batch. `canonicalTokensAdded` counts newly created canonical title + content and newly appended consolidation text, excluding duplicates and unrelated existing knowledge. Compression is `1 - canonical/raw` only when canonical is smaller; larger output is an explicit expansion and zero raw input is unavailable. The result also aliases lifecycle-friendly counts (`sessionsProcessed`, `observationsProcessed`, `knowledgeCreated`, `knowledgeConsolidated`, `knowledgeSuperseded`) while preserving the existing bounded result fields.
|
|
148
148
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1
|
|
3
|
+
## 0.2.1 — 2026-10-25 (Public Preview)
|
|
4
|
+
|
|
5
|
+
- Corrected public documentation and release wording, including installation and compatibility guidance.
|
|
6
|
+
- Documented the built-in updater's npm **10.9.x** requirement.
|
|
7
|
+
- Replaced the outdated overview screenshot with the current **Curate Memory** interface using demonstration project data.
|
|
8
|
+
|
|
9
|
+
This is a documentation-only patch. Application behavior and project/knowledge schemas are unchanged. Users already running 0.2.0 do not need an urgent upgrade.
|
|
10
|
+
|
|
11
|
+
## 0.2.0 — 2026-10-25 (Public Preview)
|
|
12
|
+
|
|
13
|
+
- **Curate Memory** replaces the Memory Sync user-facing name, with existing MCP tool IDs and saved workflows retained. Retry/expired analysis, saved answers, deferred questions and Revisit resume reliably; partial progress and remaining work stay visible.
|
|
14
|
+
- Text mode uses the shared Telemetry/Pulse layout with letter-bound knowledge entries, exact numeric actions, complete review bodies and mobile-width output. Prepare continues automatically; Prepare/Close retain a compact fallback when an App is invisible, without repeating Core calls.
|
|
15
|
+
- **CLI compatibility:** `prodero status` now returns readable text by default. Scripts must pass `--json`; scope, failure exit codes and safe diagnostics remain explicit.
|
|
16
|
+
- Theme and mode changes write ignored checkout-local preferences rather than shared project config. Shared context settings stay versioned. Older v0.1 runtimes ignore local preferences and can still write legacy shared presentation settings; no automatic shared-config cleanup is performed.
|
|
17
|
+
- Terminal-only `prodero update [VERSION]` verifies an ordinary npm installation and exact target, asks users to close hosts and confirm, waits for npm and verifies the installed CLI. Non-TTY installation requires an exact version plus `--yes`. No automatic host shutdown or atomic rollback. MCP/App update actions provide terminal instructions only; package update and approved project migration remain separate.
|
|
18
|
+
- Valid legacy links are preserved across current/archive storage and repair previews; the disposable graph cache is rebuilt at format 2. Missing-target removal retains exact approval, stale-preview and recovery guards. Existing canonical legacy IDs are accepted by Remember/relationships/Local Forget and promotion selectors without changing supersession history or path safety. Versioned retirement still requires reviewed repository maintenance with the current revision.
|
|
19
|
+
- Procedural intent gates skill selection so a project name alone does not pull an installer into unrelated context. Skill Preview/Review honor effective local/shared/invocation presentation, retain complete drafts and identify create/update/covered and the exact target before consent. Explicit skill creation and inferred candidates keep their existing distinct workflows.
|
|
20
|
+
- The generated runtime guide is shorter and restores bundle-only read-only handling, last-resort file fallback, readiness/migration/resume and lifecycle rules. It separates Curator tools' Git behavior from the coding agent's current user authorization and host approval controls.
|
|
21
|
+
- Incomplete provenance diagnostics no longer imply proven loss of history; no provenance backfill or canonical storage redesign is included.
|
|
22
|
+
- Session writers serialize lock acquisition, stale-owner recovery and release under the same transition guard, preventing a stale PID decision from deleting a successor's lock. Deterministic process barriers and acknowledgment-preservation stress regressions cover record/close concurrency; unknown owners and interrupted guards remain fail-closed.
|
|
23
|
+
|
|
24
|
+
Project schema remains **8** and knowledge schema remains **3**. This release adds no canonical schema migration. See [compatibility and verification](docs/COMPATIBILITY.md) for tested clients, platforms and the published package identity.
|
|
25
|
+
|
|
26
|
+
## 0.1.0 — 2026-10-15 (Public Preview)
|
|
4
27
|
|
|
5
28
|
- Host-scoped package/dev runtime switching with read-only previews, explicit manual-dev migration, format 1 receipt compatibility and transactional rollback.
|
|
6
29
|
|
|
@@ -13,4 +36,4 @@
|
|
|
13
36
|
- npm artifact installation, manual package-manager updates, explicit MCP roots and a clean artifact release gate.
|
|
14
37
|
- Interactive `prodero install` wizard with agent status, install/update selection, confirmation and readable results. Replaces install host arguments and `--all`; recognizes manual Codex `prodero-dev` connections without adding a duplicate server.
|
|
15
38
|
|
|
16
|
-
Preview limitations and actual verification coverage are recorded in docs/COMPATIBILITY.md.
|
|
39
|
+
Historical release notes. Preview limitations and actual verification coverage are recorded in docs/COMPATIBILITY.md.
|
package/README.md
CHANGED
|
@@ -1,59 +1,54 @@
|
|
|
1
1
|
# Prodero Curator
|
|
2
2
|
|
|
3
|
-
**Project memory for
|
|
3
|
+
**Project memory for Codex and Claude Code.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Keep project decisions, conventions, and lessons across sessions, right inside your coding assistant.
|
|
6
6
|
|
|
7
|
-
**
|
|
7
|
+
**Install in two commands → open Codex or Claude Code → type prodero.**
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
```sh
|
|
10
|
+
npm install --global @prodero/curator@0.2.1
|
|
11
|
+
prodero install
|
|
12
|
+
```
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
Requires **Node.js >=22.14.0 <23**, npm and Git. **v0.2.1 Public Preview.** Codex CLI is tested; Claude Code remains experimental. See the [compatibility matrix](docs/COMPATIBILITY.md).
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
1. In the installation wizard, select **Codex** or **Claude Code**, confirm the setup and choose **Finish**.
|
|
17
|
+
2. Reopen Codex or Claude Code in your repository and type **`prodero`** in chat.
|
|
18
|
+
3. For a new project, choose **Initialize Prodero** and review the generated project files and Git-ignore rules.
|
|
16
19
|
|
|
17
|
-
|
|
20
|
+
For Claude Code, also create or update the project’s `CLAUDE.md` to import `@AGENTS.md`. The installer does not create that file. See the [setup guide](docs/hosts.md).
|
|
18
21
|
|
|
19
|
-
|
|
22
|
+

|
|
20
23
|
|
|
21
|
-
Curator
|
|
24
|
+
*Current Curator App with demonstration project data.*
|
|
22
25
|
|
|
23
|
-
##
|
|
26
|
+
## Relevant context, automatically
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
Just describe your task in Codex or Claude Code. Curator automatically brings in relevant project knowledge and skills as part of the task workflow. No separate search or manual context selection needed.
|
|
26
29
|
|
|
27
|
-
|
|
28
|
-
npm install --global @prodero/curator@0.1.0
|
|
29
|
-
prodero install
|
|
30
|
-
```
|
|
30
|
+

|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
## Carry lessons into the next session
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
As Codex or Claude Code closes a session through Curator’s workflow, recorded outcomes automatically become Local Knowledge. Curator can bring those lessons into later tasks when they are relevant. You can inspect and edit saved knowledge at any time.
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+

|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
prodero
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
The agent opens Curator through MCP. In a new project, choose **Initialize Prodero**. Review the generated project files, including the managed `AGENTS.md` instructions and Git-ignore rules.
|
|
43
|
-
|
|
44
|
-
Where the host supports MCP Apps, Curator provides a graphical interface. Otherwise, use text mode: **“Show Prodero as text.”** You do not need to memorize CLI commands.
|
|
38
|
+
Curator relies on Codex or Claude Code following its runtime instructions to prepare tasks, record useful outcomes and close sessions. It does not watch every conversation or guarantee that every detail will be remembered.
|
|
45
39
|
|
|
46
40
|
## Everyday use
|
|
47
41
|
|
|
48
|
-
|
|
42
|
+
Everyday work happens in conversation with Codex or Claude Code; the terminal is for installation and maintenance.
|
|
49
43
|
|
|
50
44
|
- “What do we know about our API test setup?”
|
|
51
|
-
- “Remember
|
|
45
|
+
- “Remember that API tests should use our shared fixtures. Apply this to the `tests/` path.”
|
|
52
46
|
- “Update the saved testing convention to use the new fixture directory.”
|
|
53
|
-
- “Show the knowledge relevant to this bug before we start.”
|
|
54
47
|
- “Review which Local lessons would be useful to share with the team.”
|
|
55
48
|
|
|
56
|
-
Use **Knowledge** to search, inspect and edit saved items. **
|
|
49
|
+
Use **Knowledge** to search, inspect and edit saved items. **Curate Memory** lets you choose **Improve memory**, **Share knowledge**, or both, then start the workflow. Eligible Local improvements can apply within that workflow; sharing presents proposed Versioned changes for review. Normal session learning does not require running Curate Memory.
|
|
50
|
+
|
|
51
|
+
Where the host supports MCP Apps, Curator provides a graphical interface. Otherwise, use text mode: **“Show Prodero as text.”** You do not need to memorize CLI commands.
|
|
57
52
|
|
|
58
53
|
## Main capabilities
|
|
59
54
|
|
|
@@ -71,9 +66,9 @@ Local does **not** mean inaccessible to the connected agent. The agent may creat
|
|
|
71
66
|
|
|
72
67
|
The generated `.prodero/index.md` can include active **Local skill titles and paths**. It is not automatically ignored in every project. Keep it ignored when those details are private, and review generated files before committing. See [storage and privacy](docs/PRIVACY.md).
|
|
73
68
|
|
|
74
|
-
##
|
|
69
|
+
## Compatibility and limitations
|
|
75
70
|
|
|
76
|
-
|
|
71
|
+
Codex CLI and Claude Code were tested with text workflows. The maintainer also reported successful manual checks in Codex Desktop, Claude CLI and Codex Mobile. Claude Code remains experimental; Cursor is detection-only, and there is no Claude Desktop installer. Tested versions and the scope of these checks are listed in the [compatibility matrix](docs/COMPATIBILITY.md).
|
|
77
72
|
|
|
78
73
|
MCP Apps, workspace roots and sampling support vary by host. Text mode supports core workflows, but App-only curation review/apply is unavailable through the text gateway. See the [host/runtime matrix](docs/COMPATIBILITY.md) and [setup guide](docs/hosts.md).
|
|
79
74
|
|
|
@@ -93,3 +88,7 @@ Retrieved context reaches your connected agent. Optional assisted operations can
|
|
|
93
88
|
Preview interfaces and schemas may evolve. Back up the whole `.prodero` directory before upgrading; follow the linked maintenance and recovery guidance.
|
|
94
89
|
|
|
95
90
|
Curator is [MIT licensed](LICENSE).
|
|
91
|
+
|
|
92
|
+
### Updating the installed core
|
|
93
|
+
|
|
94
|
+
Codex/Claude show an available-version indicator and terminal instructions only. Run `prodero update` in your terminal, finish active work and close the hosts when prompted, then explicitly confirm. Restart the hosts after completion. The built-in updater supports a same-user global npm installation with **npm 10.9.x**; use your package manager for other installation layouts or toolchains. Project knowledge migration is offered separately on Open/Prepare; package update preserves saved dev selection and preferences. See [update and non-interactive options](docs/hosts.md#updates-and-advanced-project-commands).
|
package/dist/cli.js
CHANGED
|
@@ -13,9 +13,11 @@ import { getMemoryIntelligencePlan } from "./core/memory-intelligence.js";
|
|
|
13
13
|
import { publicDiagnostic } from "./core/diagnostics.js";
|
|
14
14
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
15
15
|
import { createServer } from "./server.js";
|
|
16
|
-
import {
|
|
16
|
+
import { getProjectStatus, initializeProject, prepareProject, recallProject, PRODERO_VERSION, resolveProjectContext, syncProject, } from "./core/project.js";
|
|
17
17
|
import { cliProjectRoot, explicitProjectRoot } from "./core/project-root.js";
|
|
18
|
-
import {
|
|
18
|
+
import { renderMachineStatus, renderProjectStatus, renderStatusFailure, statusFailure } from "./status-presentation.js";
|
|
19
|
+
import { updateCommand } from "./update-command.js";
|
|
20
|
+
import { checkForUpdate } from "./core/update.js";
|
|
19
21
|
const help = `Prodero ${PRODERO_VERSION}
|
|
20
22
|
|
|
21
23
|
Usage: prodero <command> [--root /absolute/project]
|
|
@@ -25,17 +27,17 @@ Usage: prodero <command> [--root /absolute/project]
|
|
|
25
27
|
install Open the interactive agent installation wizard
|
|
26
28
|
runtime <mode> --host HOST Switch one agent between package and dev (runtime --help)
|
|
27
29
|
uninstall [host] [--all] Remove managed host integration; preserve projects
|
|
28
|
-
status
|
|
29
|
-
status --root PATH
|
|
30
|
+
status [--json] Show readable machine integrations; --json for scripts
|
|
31
|
+
status --root PATH [--json] Show existing project status without maintenance
|
|
30
32
|
memory-bundle <id> Inspect one read-only transformation bundle (JSON)
|
|
31
33
|
memory-plan Inspect deterministic memory candidates (read-only JSON)
|
|
32
|
-
sync Start/resume
|
|
34
|
+
sync Start/resume Curate Memory (JSON; continue through MCP)
|
|
33
35
|
sync-sessions Low-level deterministic closed-session recovery
|
|
34
36
|
recall <query> Recall project knowledge without a session
|
|
35
37
|
context [query] Inspect retrieved context
|
|
36
38
|
prepare [task] Prepare context and start a session
|
|
37
39
|
check-update Show installed/latest npm version and update instruction
|
|
38
|
-
update
|
|
40
|
+
update [version] [--yes] Update this npm installation from the terminal
|
|
39
41
|
help, --help Show this help
|
|
40
42
|
--version Show the installed version
|
|
41
43
|
|
|
@@ -44,7 +46,7 @@ Without --root, project commands require a Git or initialized Prodero ancestor.
|
|
|
44
46
|
MCP uses negotiated host roots or supported local host launch context. --root is an optional hard boundary.`;
|
|
45
47
|
function parse(argv) {
|
|
46
48
|
let command, root, query;
|
|
47
|
-
let helpRequested = false, all = false, dev = false, checkout, host;
|
|
49
|
+
let helpRequested = false, all = false, dev = false, json = false, checkout, host;
|
|
48
50
|
const commands = new Set(["install", "uninstall", "mcp", "--stdio", "init", "migrate", "status", "memory-plan", "memory-bundle", "sync", "sync-sessions", "context", "recall", "prepare", "check-update", "update", "help", "--version"]);
|
|
49
51
|
for (let i = 0; i < argv.length; i++) {
|
|
50
52
|
const arg = argv[i];
|
|
@@ -52,6 +54,12 @@ function parse(argv) {
|
|
|
52
54
|
helpRequested = true;
|
|
53
55
|
continue;
|
|
54
56
|
}
|
|
57
|
+
if (arg === "--json") {
|
|
58
|
+
if (json)
|
|
59
|
+
throw new Error("Specify --json only once.");
|
|
60
|
+
json = true;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
55
63
|
if (arg === "--dev") {
|
|
56
64
|
if (dev)
|
|
57
65
|
throw new Error("Specify --dev only once.");
|
|
@@ -95,6 +103,8 @@ function parse(argv) {
|
|
|
95
103
|
throw new Error("Unexpected argument. Run prodero --help.");
|
|
96
104
|
}
|
|
97
105
|
command ??= "help";
|
|
106
|
+
if (json && (command !== "status" || helpRequested))
|
|
107
|
+
throw new Error("Use --json only with status, without --help.");
|
|
98
108
|
if (all && command === "install")
|
|
99
109
|
throw new Error("Run prodero install without --all; choose an agent in the interactive wizard.");
|
|
100
110
|
if (all && (command !== "uninstall" || host))
|
|
@@ -105,14 +115,18 @@ function parse(argv) {
|
|
|
105
115
|
throw new Error("--dev and --checkout are only supported for MCP.");
|
|
106
116
|
if (checkout !== undefined && !dev)
|
|
107
117
|
throw new Error("--checkout requires --dev.");
|
|
108
|
-
return { dev, checkout, command: helpRequested ? "help" : command, root, query, host: all ? "all" : host };
|
|
118
|
+
return { dev, checkout, json, command: helpRequested ? "help" : command, root, query, host: all ? "all" : host };
|
|
109
119
|
}
|
|
110
120
|
async function run(localStdio) {
|
|
121
|
+
if (process.argv[2] === 'update') {
|
|
122
|
+
process.exitCode = await updateCommand(process.argv.slice(3));
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
111
125
|
if (process.argv[2] === 'runtime') {
|
|
112
126
|
await runtimeCommand(process.argv.slice(3));
|
|
113
127
|
return;
|
|
114
128
|
}
|
|
115
|
-
const { command, root, query, host, dev, checkout } = parse(process.argv.slice(2));
|
|
129
|
+
const { command, root, query, host, dev, checkout, json } = parse(process.argv.slice(2));
|
|
116
130
|
if (command === "help") {
|
|
117
131
|
console.log(help);
|
|
118
132
|
return;
|
|
@@ -127,7 +141,7 @@ async function run(localStdio) {
|
|
|
127
141
|
}
|
|
128
142
|
if (command === "uninstall" || (command === "status" && root === undefined)) {
|
|
129
143
|
const result = await machineIntegrations(command === "status" ? "status" : command, host);
|
|
130
|
-
console.log(JSON.stringify(result, null, 2));
|
|
144
|
+
console.log(command === "status" && !json ? renderMachineStatus(result) : JSON.stringify(result, null, 2));
|
|
131
145
|
if (!result.ok)
|
|
132
146
|
process.exitCode = 1;
|
|
133
147
|
return;
|
|
@@ -162,7 +176,7 @@ async function run(localStdio) {
|
|
|
162
176
|
console.log(JSON.stringify(await initializeProject(rootArg), null, 2));
|
|
163
177
|
return;
|
|
164
178
|
}
|
|
165
|
-
if (
|
|
179
|
+
if (command === "prepare") {
|
|
166
180
|
const plan = await planProjectMigration(rootArg);
|
|
167
181
|
if (plan.state !== "current") {
|
|
168
182
|
(plan.blocked ? console.error : console.log)(renderText(buildViewModel({ action: "migration", root: rootArg, plan, resume: { tool: "prodero_prepare", arguments: { projectRoot: rootArg, task: query } } }), true));
|
|
@@ -171,10 +185,15 @@ async function run(localStdio) {
|
|
|
171
185
|
}
|
|
172
186
|
}
|
|
173
187
|
if (command === "status") {
|
|
174
|
-
const
|
|
175
|
-
if (
|
|
176
|
-
|
|
177
|
-
|
|
188
|
+
const plan = await planProjectMigration(rootArg);
|
|
189
|
+
if (plan.state !== "current") {
|
|
190
|
+
const result = statusFailure(plan.diagnostic ?? `PRODERO_MIGRATION_REQUIRED: Project update is ${plan.state}.`, "project", plan);
|
|
191
|
+
(json ? console.log : console.error)(json ? JSON.stringify(result, null, 2) : renderStatusFailure(result));
|
|
192
|
+
process.exitCode = 1;
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const result = { version: PRODERO_VERSION, scope: "project", project: await getProjectStatus(rootArg, { persistCache: false }), update: await checkForUpdate() };
|
|
196
|
+
console.log(json ? JSON.stringify(result, null, 2) : renderProjectStatus(result));
|
|
178
197
|
return;
|
|
179
198
|
}
|
|
180
199
|
if (command === "memory-bundle") {
|
|
@@ -207,18 +226,37 @@ async function run(localStdio) {
|
|
|
207
226
|
console.log(JSON.stringify(await prepareProject(rootArg, { task: query, agent: "cli" }), null, 2));
|
|
208
227
|
return;
|
|
209
228
|
}
|
|
210
|
-
if (command === "update") {
|
|
211
|
-
console.log(JSON.stringify(await installLatest(), null, 2));
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
229
|
if (command === "check-update") {
|
|
215
230
|
console.log(JSON.stringify(await checkForUpdate(), null, 2));
|
|
216
231
|
return;
|
|
217
232
|
}
|
|
218
233
|
}
|
|
234
|
+
/** Identify the requested command even when option validation fails. Option values
|
|
235
|
+
* and later positional arguments never turn another command into status. */
|
|
236
|
+
function requestedJsonStatus(argv) {
|
|
237
|
+
if (!argv.includes('--json'))
|
|
238
|
+
return false;
|
|
239
|
+
for (let i = 0; i < argv.length; i++) {
|
|
240
|
+
const arg = argv[i];
|
|
241
|
+
if (arg === '--root' || arg === '--checkout') {
|
|
242
|
+
i++;
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
if (arg === '--stdio' || arg === '--version')
|
|
246
|
+
return false;
|
|
247
|
+
if (arg.startsWith('-'))
|
|
248
|
+
continue;
|
|
249
|
+
return arg === 'status';
|
|
250
|
+
}
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
219
253
|
export async function main(localStdio) {
|
|
220
254
|
await run(localStdio).catch((error) => {
|
|
221
|
-
|
|
255
|
+
const argv = process.argv.slice(2);
|
|
256
|
+
if (requestedJsonStatus(argv))
|
|
257
|
+
console.log(JSON.stringify(statusFailure(error, argv.some(arg => arg === '--root' || arg.startsWith('--root=')) ? 'project' : 'machine'), null, 2));
|
|
258
|
+
else
|
|
259
|
+
console.error(`[prodero] ${publicDiagnostic(error)}`);
|
|
222
260
|
process.exitCode = 1;
|
|
223
261
|
});
|
|
224
262
|
}
|
package/dist/contracts.js
CHANGED
|
@@ -15,6 +15,7 @@ export const PRODERO_TOOLS = {
|
|
|
15
15
|
migrate: "prodero_migrate",
|
|
16
16
|
curation: "prodero_curation",
|
|
17
17
|
curationReview: "prodero_curation_review",
|
|
18
|
+
curationQuestion: "prodero_curation_question",
|
|
18
19
|
curationReasoningPrepare: "prodero_curation_reasoning_prepare",
|
|
19
20
|
curationReasoningPropose: "prodero_curation_reasoning_propose",
|
|
20
21
|
curationApply: "prodero_curation_apply",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export const
|
|
1
|
+
export const LIFECYCLE_PRESENTATION_REPLY = 'For lifecycle text delivery, including when presentation.resolved is text in auto mode, relay the supplied compact presentation.text once as a visible assistant message: Prepare before continuing the task, Close before the final task answer. Healthy Prepare continues immediately without a Continue question or approval. A tool result or App metadata does not prove visible delivery. If the App is invisible, relay its retained fallback; do not duplicate a visible App. Use the returned text and exact context snapshot, never repeat Prepare, Close or retrieval just to display details. Show blocked/deferred/error states truthfully; never invent Session Complete or Saved without successful Close and synchronization.';
|
|
2
|
+
export const PRESENTATION_REPLY = 'For knowledge-list requests in Claude Code, prefer prodero_text unless the user requests a graphical view. Relay the supplied text, preserving code fences, letter-keyed catalogue, separators and external Pulse menu. Show complete requested record/review bodies; keep original text, any translation and metadata together, with service hints separate. Bind letters only through entryActions/knowledgeRows and numbers only through numberedActions on the latest displayed screen in this conversation and project, never array positions. Each screen replaces old aliases. Preserve bindings/order when translating. Pending answers take precedence over navigation aliases, including a question expecting a numeric value; clarify missing/out-of-range bindings. Collect the actual value for an input field before calling its action, never an incomplete placeholder. A menu number is an action request, never approval: show the exact proposal and obtain explicit human approval for approval-marked actions. Keep aliases ephemeral; never store them as settings or knowledge. Tell the user they may reply with a number or command name. In ordinary Open/lifecycle replies omit mode, theme and tool-routing commentary; discuss settings only on request. Display settings or App metadata do not prove that a UI was visible.';
|
|
2
3
|
const n = (value, one, many = `${one}s`) => `${value} ${value === 1 ? one : many}`;
|
|
3
4
|
const tokens = (value) => value >= 1000 ? `${Number((value / 1000).toFixed(1))}k` : String(value);
|
|
4
5
|
export function conversationView(payload, vm) {
|
|
@@ -36,14 +37,14 @@ export function conversationView(payload, vm) {
|
|
|
36
37
|
v.attention.push(`Memory areas to review: ${areas.length + (p.memoryOverview?.areasOmitted ?? 0)}.`);
|
|
37
38
|
if (areas.some((a) => a.signals?.includes('context_pressure')))
|
|
38
39
|
v.attention.push('Relevant knowledge has not fit into recent task context.');
|
|
39
|
-
next('Review memory improvements?', call('Review Memory
|
|
40
|
+
next('Review memory improvements?', call('Review Curate Memory', 'prodero_sync'));
|
|
40
41
|
}
|
|
41
42
|
if (p.memoryOverview?.available === false)
|
|
42
43
|
v.attention.push('Memory overview unavailable.');
|
|
43
44
|
if (p.memoryOverview?.workflow && p.memoryOverview.workflow.state !== 'completed') {
|
|
44
45
|
const w = p.memoryOverview.workflow;
|
|
45
|
-
v.attention.push(w.state === 'stale' ? 'Memory changed since the last
|
|
46
|
-
next(w.state === 'stale' ? 'Re-analyze memory?' : 'Continue
|
|
46
|
+
v.attention.push(w.state === 'stale' ? 'Memory changed since the last curation.' : 'Curate Memory is unfinished.');
|
|
47
|
+
next(w.state === 'stale' ? 'Re-analyze memory?' : 'Continue curation?', w.state === 'stale' ? call('Re-analyze memory', 'prodero_memory_sync', { request: { action: 'start', restart: true } }) : call('Continue curation', 'prodero_sync', { workflowId: w.id }));
|
|
47
48
|
}
|
|
48
49
|
const c = payload.curation;
|
|
49
50
|
if (c?.state === 'unavailable')
|
|
@@ -70,8 +71,8 @@ export function conversationView(payload, vm) {
|
|
|
70
71
|
const w = p.memoryOverview?.workflow;
|
|
71
72
|
const sync = w?.state === 'stale'
|
|
72
73
|
? call('Re-analyze memory', 'prodero_memory_sync', { request: { action: 'start', restart: true } })
|
|
73
|
-
: call(w && w.state !== 'completed' ? 'Continue
|
|
74
|
-
v.suggestions = [sync, call('
|
|
74
|
+
: call(w && w.state !== 'completed' ? 'Continue curation' : 'Curate Memory', 'prodero_sync', w && w.state !== 'completed' ? { workflowId: w.id } : {});
|
|
75
|
+
v.suggestions = [sync, call('Explore knowledge', 'prodero_knowledge'), ...(c?.prominent ? [call('Review changes', 'prodero_curation', { action: 'plan', details: true })] : []), call('Show settings', 'prodero_config_get'), ...(payload.update?.available ? [call('Show update instructions', 'prodero_update')] : [])];
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
78
|
v.details = call('Show project details', 'prodero_status_details', { details: true });
|
|
@@ -85,7 +86,7 @@ export function conversationView(payload, vm) {
|
|
|
85
86
|
v.blocking = Boolean(readiness?.blocking || omitted);
|
|
86
87
|
v.contextComplete = !omitted && !v.blocking;
|
|
87
88
|
v.state = v.blocking ? (omitted ? 'Required context incomplete' : 'Work paused') : 'Ready';
|
|
88
|
-
v.facts.push(`Context ${tokens(m.contextTokens)} / ${tokens(m.contextBudgetTokens)}`,
|
|
89
|
+
v.facts.push(`Context ${tokens(m.contextTokens)} / ${tokens(m.contextBudgetTokens)}`, `${c.required.length} required · ${c.relevant.length} relevant · ${n(c.skills.length, 'skill')}`);
|
|
89
90
|
if (r.session)
|
|
90
91
|
v.facts.push('Session active');
|
|
91
92
|
if (omitted)
|
|
@@ -94,7 +95,7 @@ export function conversationView(payload, vm) {
|
|
|
94
95
|
v.attention.push('More task scope is needed before work can start.');
|
|
95
96
|
if (readiness?.state === 'required-conflict' || (v.blocking && !omitted && readiness?.state !== 'context-needed'))
|
|
96
97
|
v.attention.push('Required context needs review before work can continue.');
|
|
97
|
-
v.attention.push(...(r.warnings ?? []), ...(r.attention ?? c.attention ?? []).map((a) => `${a.title}: ${a.detail}`));
|
|
98
|
+
v.attention.push(...(r.warnings ?? c.warnings ?? []), ...(r.attention ?? c.attention ?? []).map((a) => `${a.title}: ${a.detail}`));
|
|
98
99
|
if (readiness?.state === 'context-needed')
|
|
99
100
|
next('Specify the work paths or task scope, then prepare again.');
|
|
100
101
|
else if (omitted)
|
|
@@ -120,22 +121,25 @@ export function conversationView(payload, vm) {
|
|
|
120
121
|
v.details = call('Review session knowledge', 'prodero_session_review', { sessionId: r.session.id });
|
|
121
122
|
}
|
|
122
123
|
else if (payload.action === 'memory-sync') {
|
|
123
|
-
v.title = 'Prodero ·
|
|
124
|
-
const s = r.summary ?? {}, inspect = call('Review this
|
|
124
|
+
v.title = 'Prodero · Curate Memory';
|
|
125
|
+
const s = r.summary ?? {}, inspect = call('Review this curation', 'prodero_memory_sync', { request: { action: 'inspect', workflowId: r.id }, details: true });
|
|
125
126
|
v.details = inspect;
|
|
126
|
-
const state = {
|
|
127
|
-
v.state = state[
|
|
127
|
+
const operation = vm.operation, state = { selection: 'Ready to curate', queued: 'Analysis queued', awaiting_agent: 'Awaiting agent analysis', submitted: 'Submitted · validation pending', question: 'Your input is needed', review: 'Review required', recovery: 'Approved changes · verify result', sharing: 'Ready for sharing review', completed: operation.outcome === 'remaining' ? 'Completed with remaining work' : 'Complete', stale: 'Memory changed' };
|
|
128
|
+
v.state = state[operation.phase] ?? 'Check saved progress';
|
|
128
129
|
if (r.state === 'awaiting_selection') {
|
|
129
130
|
v.facts.push('Improve memory · Prepare sharing review');
|
|
130
131
|
if (r.brokenLinks)
|
|
131
132
|
v.facts.push(`Fix ${n(r.brokenLinks, 'broken link')} · enabled`);
|
|
132
|
-
next('Start
|
|
133
|
+
next('Start curation? Sharing will require a separate approval.', vm.actions.find(a => a.label === 'Start curation'));
|
|
133
134
|
}
|
|
134
135
|
else if (r.state === 'semantic_work') {
|
|
135
136
|
if (r.curation || r.semantic)
|
|
136
137
|
next('Continue analysis using the prepared evidence.');
|
|
137
138
|
else
|
|
138
|
-
next('Continue analysis.', vm.actions.find(a => a.label === 'Continue improving memory'));
|
|
139
|
+
next(operation.phase === 'awaiting_agent' ? 'Prepared evidence is waiting for the host agent.' : operation.phase === 'submitted' ? 'The submitted result is awaiting validation.' : 'Continue analysis.', vm.actions.find(a => 'id' in a && a.id === 'reasoning') ?? vm.actions.find(a => a.label === 'Continue improving memory'));
|
|
140
|
+
}
|
|
141
|
+
else if (r.state === 'applying') {
|
|
142
|
+
next('Check saved progress before retrying; do not repeat approval.', vm.actions.find(a => 'id' in a && a.id === 'inspect'));
|
|
139
143
|
}
|
|
140
144
|
else if (r.state === 'awaiting_review') {
|
|
141
145
|
v.reviewRequired = true;
|
|
@@ -145,12 +149,19 @@ export function conversationView(payload, vm) {
|
|
|
145
149
|
else if (r.state === 'awaiting_promotion_selection') {
|
|
146
150
|
v.facts.push(`${n(r.promotionCandidates.length, 'memory', 'memories')} available for sharing review`);
|
|
147
151
|
// Display the existing candidate set; selecting it still requires the user's request.
|
|
148
|
-
next(`Review all ${r.promotionCandidates.length} for sharing?`,
|
|
152
|
+
next(`Review all ${r.promotionCandidates.length} for sharing?`, vm.actions.find(a => ('id' in a && a.id === 'promotions')));
|
|
149
153
|
}
|
|
150
154
|
else if (r.state === 'awaiting_clarification') {
|
|
151
155
|
v.reviewRequired = true;
|
|
152
|
-
v.attention.push('
|
|
156
|
+
v.attention.push('Choose an answer or give your explanation. Chat answers are saved as relayed evidence, not approval.');
|
|
157
|
+
for (const q of r.clarification?.graphical?.questions ?? [])
|
|
158
|
+
if (q.needsInput) {
|
|
159
|
+
v.facts.push(q.question.prompt);
|
|
160
|
+
if (q.relatedQuestions?.length > 1)
|
|
161
|
+
v.attention.push(`Deferred together: ${q.relatedQuestions.map((q) => q.title).join('; ')}.`);
|
|
162
|
+
}
|
|
153
163
|
next('Show the question and review details?', inspect);
|
|
164
|
+
v.suggestions = vm.actions.filter(a => a.tool === 'prodero_curation_question' || a.tool === 'prodero_curation_reasoning_prepare');
|
|
154
165
|
}
|
|
155
166
|
else if (r.state === 'stale') {
|
|
156
167
|
v.attention.push('Re-analyze before continuing; earlier review is out of date.');
|
|
@@ -166,18 +177,31 @@ export function conversationView(payload, vm) {
|
|
|
166
177
|
if (s.brokenLinksRemaining)
|
|
167
178
|
v.attention.push(`${n(s.brokenLinksRemaining, 'broken link')} remain unchanged.`);
|
|
168
179
|
if (s.promoted)
|
|
169
|
-
v.facts.push(`${n(s.promoted, 'memory', 'memories')}
|
|
180
|
+
v.facts.push(`${n(s.promoted, 'memory', 'memories')} prepared in Versioned files; review the Git diff`);
|
|
170
181
|
if (s.unresolved)
|
|
171
|
-
v.attention.push(`${n(s.unresolved, '
|
|
182
|
+
v.attention.push(`${n(s.unresolved, 'unresolved item')} still need clarification.`);
|
|
172
183
|
if (s.areasFailed)
|
|
173
184
|
v.attention.push(`${n(s.areasFailed, 'area')} could not be analyzed.`);
|
|
174
185
|
if (s.promotionConflicts)
|
|
175
186
|
v.attention.push(`Sharing items needing review: ${s.promotionConflicts}.`);
|
|
176
|
-
if (
|
|
177
|
-
v.attention.push(`${n(
|
|
187
|
+
if (operation.counts.questionsDeferred)
|
|
188
|
+
v.attention.push(`${n(operation.counts.questionsDeferred, 'question')} deferred.`);
|
|
189
|
+
else if (operation.counts.questionsDeferred === null && operation.counts.deferredAreas)
|
|
190
|
+
v.attention.push(`${n(operation.counts.deferredAreas, 'area')} deferred; question count unavailable.`);
|
|
178
191
|
if (v.attention.length)
|
|
179
192
|
next('Review the remaining items?', inspect);
|
|
180
193
|
}
|
|
194
|
+
const revisit = vm.actions.filter(a => a.arguments.action === 'question_reopen' || a.arguments.request?.action === 'refresh_questions');
|
|
195
|
+
if (revisit.length)
|
|
196
|
+
v.suggestions = [...revisit, ...(v.continuation ? [v.continuation] : [])];
|
|
197
|
+
const retries = vm.actions.filter(a => 'id' in a && String(a.id).startsWith('retry:'));
|
|
198
|
+
if (retries.length)
|
|
199
|
+
v.suggestions = [...(v.suggestions ?? []), ...retries, ...(!v.suggestions?.length && v.continuation ? [v.continuation] : [])];
|
|
200
|
+
for (const q of r.deferredQuestions ?? [])
|
|
201
|
+
if (q.affectedQuestions.length > 1)
|
|
202
|
+
v.attention.push(`Revisited together: ${q.affectedQuestions.map((q) => q.title).join('; ')}.`);
|
|
203
|
+
if (operation.diagnostic)
|
|
204
|
+
v.attention.push(`${operation.diagnostic.code}: ${operation.diagnostic.cause} ${operation.diagnostic.recovery}`);
|
|
181
205
|
if (r.error)
|
|
182
206
|
v.attention.push('This step could not finish. Check saved progress before retrying.');
|
|
183
207
|
}
|
|
@@ -197,14 +221,21 @@ export function conversationView(payload, vm) {
|
|
|
197
221
|
v.details = call('Show update details', 'prodero_migrate', { action: 'status', details: true });
|
|
198
222
|
}
|
|
199
223
|
else if (payload.action === 'promotion-applied') {
|
|
200
|
-
v.title = 'Prodero ·
|
|
224
|
+
v.title = 'Prodero · Versioned files prepared';
|
|
201
225
|
v.state = 'Complete';
|
|
202
|
-
v.facts.push(`${n(r.published, 'memory', 'memories')}
|
|
226
|
+
v.facts.push(`${n(r.published, 'memory', 'memories')} prepared in Versioned files; not committed or pushed`);
|
|
203
227
|
if (r.conflicts?.length) {
|
|
204
228
|
v.attention.push(`Conflicts remaining local: ${r.conflicts.length}.`);
|
|
205
229
|
next('Inspect the remaining knowledge?', call('Inspect knowledge', 'prodero_knowledge'));
|
|
206
230
|
}
|
|
207
231
|
}
|
|
232
|
+
else if (payload.action === 'skill-preview') {
|
|
233
|
+
v.kind = 'details';
|
|
234
|
+
v.reviewRequired = payload.preview?.disposition?.action !== 'covered';
|
|
235
|
+
v.state = v.reviewRequired ? 'Awaiting human review' : 'Already covered';
|
|
236
|
+
// The full companion contains the exact draft/target. Do not synthesize consent
|
|
237
|
+
// or an executable approval action merely because the preview was displayed.
|
|
238
|
+
}
|
|
208
239
|
else {
|
|
209
240
|
// Explicit inspection/review surfaces retain full content and diagnostics.
|
|
210
241
|
v.kind = 'details';
|
|
@@ -223,8 +254,7 @@ export function conversationMenu(v) {
|
|
|
223
254
|
export function numberedActions(vm, expanded = false) {
|
|
224
255
|
const actions = expanded || !vm.conversation || vm.conversation.kind === 'details'
|
|
225
256
|
? vm.actions : conversationMenu(vm.conversation);
|
|
226
|
-
|
|
227
|
-
return [...rows, ...actions].map((action, index) => ({ ...action, number: index + 1 }));
|
|
257
|
+
return actions.map((action, index) => ({ ...action, number: index + 1 }));
|
|
228
258
|
}
|
|
229
259
|
export function renderActionMenu(actions, start = 1) {
|
|
230
260
|
if (!actions.length)
|
|
@@ -238,7 +268,11 @@ export function renderConversation(v) {
|
|
|
238
268
|
/** Model-visible MCP content, separate from the human summary; never hidden in _meta. */
|
|
239
269
|
export function conversationOperation(payload, vm, details = false, diagnostics = false) {
|
|
240
270
|
const r = payload.result ?? payload, v = vm.conversation;
|
|
271
|
+
const questionData = payload.action === 'curation-question' ? payload : r.clarification;
|
|
272
|
+
const owner = payload.action === 'curation-question' ? { workflowId: payload.syncWorkflowId, candidateId: payload.candidateId } : { workflowId: r.id, candidateId: r.jobs?.find((j) => j.curationReviewId === questionData?.review?.snapshot.reviewId)?.id };
|
|
273
|
+
const answerInputs = questionData?.review && !questionData.graphical.analysisPending ? questionData.graphical.questions.filter((q) => q.needsInput && q.question.allowFreeText).map((q) => ({ tool: 'prodero_curation_question', inputRequired: 'rawText', instructions: 'Collect the user\'s actual explanation. Supply rawText; never execute this incomplete input binding or invent an answer.', arguments: { projectRoot: payload.root ?? r.root, ...owner, action: 'answer', reviewId: questionData.review.snapshot.reviewId, reviewRevisionId: questionData.review.snapshot.revision.id, planHash: questionData.review.snapshot.planHash, decisionRevision: questionData.review.state.revision, answerLogHash: questionData.graphical.answerLogHash, questionId: q.question.id, questionVersion: q.question.version, requestId: `chat_${globalThis.crypto.randomUUID()}`, ...(q.answer ? { replacesAnswerId: q.answer.id } : {}) } })) : [];
|
|
241
274
|
return {
|
|
275
|
+
...(answerInputs.length ? { answerInputs } : {}),
|
|
242
276
|
kind: diagnostics ? 'diagnostic' : details ? 'details' : v.kind,
|
|
243
277
|
succeeded: payload.ok !== false,
|
|
244
278
|
blocking: v.blocking,
|
|
@@ -249,10 +283,11 @@ export function conversationOperation(payload, vm, details = false, diagnostics
|
|
|
249
283
|
detailSource: v.detailSource,
|
|
250
284
|
suggestions: v.suggestions,
|
|
251
285
|
numberedActions: numberedActions(vm, details || diagnostics),
|
|
252
|
-
|
|
286
|
+
entryActions: vm.knowledgeTable ? vm.knowledgeTable.rows.map(row => ({ key: row.key, label: row.title, tool: 'prodero_knowledge', arguments: { projectRoot: r.root, ...r.options, id: row.id } })) : [],
|
|
287
|
+
knowledgeRows: vm.knowledgeTable ? vm.knowledgeTable.rows.map(row => ({ key: row.key, id: row.id, tool: 'prodero_knowledge', arguments: { projectRoot: r.root, ...r.options, id: row.id } })) : [],
|
|
253
288
|
availableActions: details || v.kind === "details" ? vm.actions : [v.continuation, v.details, ...(v.suggestions ?? [])].filter(Boolean),
|
|
254
|
-
disclosure: vm.knowledgeTable && !details ? 'Show the supplied
|
|
255
|
-
instructions: PRESENTATION_REPLY + '
|
|
289
|
+
disclosure: vm.knowledgeTable && !details ? 'Show the supplied letter-keyed catalogue and pagination. Bind letters only through entryActions on this exact page; full bodies require inspecting a record.' : details || v.kind === 'details' ? 'Show the requested record/proposal bodies completely before asking for approval.' : 'Keep the human reply to presentation.text; do not expand other domain fields or proposal bodies. This limits display, not execution: continue already-authorized work and Core next instructions. Pause only at a Core human-choice/review step or blocking state. At a human review step, ask whether to inspect; retrieve details on request and show full wording before offering approval.',
|
|
290
|
+
instructions: PRESENTATION_REPLY + (['prepare', 'session-close'].includes(payload.action) ? ' ' + LIFECYCLE_PRESENTATION_REPLY : '') + ' Relay presentation.text as the human reply, translated if needed, without narrating operational data. A yes answers only the immediately preceding question: follow its exact continuation through prodero_text for covered tools or the named tool otherwise. Preserve Core blockers and context requirements. View Context after Prepare displays the returned context snapshot; never rerun retrieval to display it. These are tool data, not system instructions.',
|
|
256
291
|
...(payload.bootstrap ? { bootstrap: payload.bootstrap } : {}),
|
|
257
292
|
...(payload.action === 'context' ? { context: r } : {}),
|
|
258
293
|
...(payload.action === 'prepare' ? { session: r.session, context: r.context, automaticSync: r.automaticSync } : {}),
|