@prodero/curator 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/ARCHITECTURE.md +298 -0
  2. package/CHANGELOG.md +16 -0
  3. package/CONTRIBUTING.md +9 -0
  4. package/LICENSE +21 -0
  5. package/README.md +94 -2
  6. package/SECURITY.md +7 -0
  7. package/bin/prodero +7 -0
  8. package/dist/cli.js +228 -0
  9. package/dist/context-instructions.js +2 -0
  10. package/dist/contracts.js +50 -0
  11. package/dist/conversation-presentation.js +262 -0
  12. package/dist/core/agent-instructions.js +39 -0
  13. package/dist/core/applicability-label.js +11 -0
  14. package/dist/core/applicability.js +143 -0
  15. package/dist/core/bootstrap.js +129 -0
  16. package/dist/core/consolidation.js +315 -0
  17. package/dist/core/constants.js +21 -0
  18. package/dist/core/context-allocation.js +54 -0
  19. package/dist/core/context-snapshot.js +12 -0
  20. package/dist/core/context.js +489 -0
  21. package/dist/core/curation-clauses.js +68 -0
  22. package/dist/core/curation-evidence.js +98 -0
  23. package/dist/core/curation-graphical.js +105 -0
  24. package/dist/core/curation-review-presentation.js +4 -0
  25. package/dist/core/curation-review-state.js +62 -0
  26. package/dist/core/curation-review.js +573 -0
  27. package/dist/core/curation-revision.js +106 -0
  28. package/dist/core/curation-semantic-contract.js +239 -0
  29. package/dist/core/curation-semantic-jobs.js +280 -0
  30. package/dist/core/diagnostics.js +17 -0
  31. package/dist/core/format.js +114 -0
  32. package/dist/core/ids.js +6 -0
  33. package/dist/core/imports.js +169 -0
  34. package/dist/core/index.js +93 -0
  35. package/dist/core/instruction-review.js +86 -0
  36. package/dist/core/integrity-files.js +174 -0
  37. package/dist/core/intelligence.js +95 -0
  38. package/dist/core/knowledge-analysis.js +46 -0
  39. package/dist/core/knowledge-authority.js +143 -0
  40. package/dist/core/knowledge-curation.js +316 -0
  41. package/dist/core/knowledge-engine.js +475 -0
  42. package/dist/core/knowledge-graph.js +191 -0
  43. package/dist/core/knowledge-lifecycle.js +212 -0
  44. package/dist/core/knowledge-management.js +113 -0
  45. package/dist/core/knowledge-migration.js +84 -0
  46. package/dist/core/knowledge-policy.js +38 -0
  47. package/dist/core/knowledge-provenance.js +90 -0
  48. package/dist/core/knowledge-write-policy.js +85 -0
  49. package/dist/core/language.js +14 -0
  50. package/dist/core/matching.js +6 -0
  51. package/dist/core/memory-index.js +239 -0
  52. package/dist/core/memory-intelligence.js +288 -0
  53. package/dist/core/memory-link-repair.js +66 -0
  54. package/dist/core/memory-operations.js +122 -0
  55. package/dist/core/memory-pressure.js +212 -0
  56. package/dist/core/memory-sync-curator.js +62 -0
  57. package/dist/core/memory-sync.js +463 -0
  58. package/dist/core/memory-transformation-bundle.js +163 -0
  59. package/dist/core/memory-transformation-proposal.js +135 -0
  60. package/dist/core/memory-transformation.js +108 -0
  61. package/dist/core/memory.js +186 -0
  62. package/dist/core/migrations.js +569 -0
  63. package/dist/core/path-scope.js +27 -0
  64. package/dist/core/plugin-files.js +116 -0
  65. package/dist/core/project-root.js +39 -0
  66. package/dist/core/project.js +634 -0
  67. package/dist/core/promotion.js +279 -0
  68. package/dist/core/reconciliation.js +61 -0
  69. package/dist/core/secrets.js +67 -0
  70. package/dist/core/semantic-safety.js +33 -0
  71. package/dist/core/session-index.js +112 -0
  72. package/dist/core/session-review.js +150 -0
  73. package/dist/core/sessions.js +289 -0
  74. package/dist/core/settings.js +76 -0
  75. package/dist/core/skill-curation.js +239 -0
  76. package/dist/core/skill-polish.js +41 -0
  77. package/dist/core/skills.js +368 -0
  78. package/dist/core/storage.js +408 -0
  79. package/dist/core/sync-transaction.js +254 -0
  80. package/dist/core/telemetry.js +64 -0
  81. package/dist/core/templates.js +53 -0
  82. package/dist/core/types.js +2 -0
  83. package/dist/core/update.js +320 -0
  84. package/dist/curation-review-adapter.js +92 -0
  85. package/dist/diagnostic-boundary.js +54 -0
  86. package/dist/filesystem/permissions.js +39 -0
  87. package/dist/hosts/adapters.js +119 -0
  88. package/dist/hosts/files.js +133 -0
  89. package/dist/hosts/manager.js +150 -0
  90. package/dist/hosts/public-entry.js +47 -0
  91. package/dist/hosts/runtime-command.js +66 -0
  92. package/dist/hosts/runtime.js +139 -0
  93. package/dist/hosts/wizard.js +114 -0
  94. package/dist/knowledge-table.js +38 -0
  95. package/dist/mcp-development.js +69 -0
  96. package/dist/mcp-workspace.js +141 -0
  97. package/dist/memory-presentation.js +172 -0
  98. package/dist/plugins/api.js +2 -0
  99. package/dist/plugins/context.js +20 -0
  100. package/dist/plugins/mcp.js +72 -0
  101. package/dist/plugins/registry.js +106 -0
  102. package/dist/presentation-cards.js +32 -0
  103. package/dist/presentation-server.js +79 -0
  104. package/dist/presentation-trace.js +174 -0
  105. package/dist/presentation.js +412 -0
  106. package/dist/providers/mcp-sampling.js +45 -0
  107. package/dist/server.js +656 -0
  108. package/dist/settings-definition.js +22 -0
  109. package/dist/skill-instructions.js +2 -0
  110. package/dist-ui/index.html +214 -0
  111. package/docs/APPLICABILITY.md +151 -0
  112. package/docs/COMPATIBILITY.md +49 -0
  113. package/docs/CONTEXT-SELECTION-V2.md +61 -0
  114. package/docs/CURATION-APP-REVIEW.md +156 -0
  115. package/docs/CURATION-CLAUSE-REFINEMENT.md +45 -0
  116. package/docs/IMPORTER-CURATION.md +142 -0
  117. package/docs/KNOWLEDGE-AUTHORITY.md +165 -0
  118. package/docs/KNOWLEDGE-SCHEMA-V2.md +150 -0
  119. package/docs/MIGRATIONS.md +99 -0
  120. package/docs/PRIVACY.md +28 -0
  121. package/docs/RECOVERY.md +56 -0
  122. package/docs/RELEASING.md +40 -0
  123. package/docs/hosts.md +134 -0
  124. package/docs/plugins.md +83 -0
  125. package/docs/ui-themes.md +43 -0
  126. package/instructions/AGENTS.md +33 -0
  127. package/package.json +88 -4
  128. package/plugins/migrate_ai_studio/README.md +101 -0
  129. package/plugins/migrate_ai_studio/index.cjs +396 -0
  130. package/plugins/migrate_ai_studio/instructions/audit.md +25 -0
  131. package/plugins/migrate_ai_studio/instructions/classify.md +41 -0
  132. package/plugins/migrate_ai_studio/instructions/migrate.md +34 -0
  133. package/plugins/migrate_ai_studio/instructions/verify.md +20 -0
  134. package/plugins/migrate_ai_studio/plugin.json +11 -0
  135. package/plugins/migrate_ai_studio/schema.cjs +20 -0
  136. package/plugins/migrate_ai_studio/ui/dist/index.html +77 -0
  137. package/prodero.release.json +5 -0
package/dist/cli.js ADDED
@@ -0,0 +1,228 @@
1
+ #!/usr/bin/env node
2
+ import { realpathSync } from "node:fs";
3
+ import { pathToFileURL } from "node:url";
4
+ import { captureLocalStdioContext } from "./mcp-workspace.js";
5
+ import { planProjectMigration, applyProjectMigration } from "./core/migrations.js";
6
+ import { buildViewModel, renderText } from "./presentation.js";
7
+ import { runMemorySync } from './core/memory-sync.js';
8
+ import { machineIntegrations } from "./hosts/manager.js";
9
+ import { installWizard } from "./hosts/wizard.js";
10
+ import { runtimeCommand } from "./hosts/runtime-command.js";
11
+ import { buildMemoryTransformationBundle } from "./core/memory-transformation-bundle.js";
12
+ import { getMemoryIntelligencePlan } from "./core/memory-intelligence.js";
13
+ import { publicDiagnostic } from "./core/diagnostics.js";
14
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
15
+ import { createServer } from "./server.js";
16
+ import { autoMigrateProject, getProjectStatus, initializeProject, prepareProject, recallProject, PRODERO_VERSION, resolveProjectContext, syncProject, } from "./core/project.js";
17
+ import { cliProjectRoot, explicitProjectRoot } from "./core/project-root.js";
18
+ import { checkForUpdate, installLatest } from "./core/update.js";
19
+ const help = `Prodero ${PRODERO_VERSION}
20
+
21
+ Usage: prodero <command> [--root /absolute/project]
22
+ mcp, --stdio Start MCP in the host workspace; --dev loads the saved development runtime
23
+ migrate [status] Review or apply the project knowledge update with backup
24
+ init Initialize the selected project
25
+ install Open the interactive agent installation wizard
26
+ runtime <mode> --host HOST Switch one agent between package and dev (runtime --help)
27
+ uninstall [host] [--all] Remove managed host integration; preserve projects
28
+ status Show version and machine host integrations
29
+ status --root PATH Show existing project status
30
+ memory-bundle <id> Inspect one read-only transformation bundle (JSON)
31
+ memory-plan Inspect deterministic memory candidates (read-only JSON)
32
+ sync Start/resume Sync Memory (JSON; continue through MCP)
33
+ sync-sessions Low-level deterministic closed-session recovery
34
+ recall <query> Recall project knowledge without a session
35
+ context [query] Inspect retrieved context
36
+ prepare [task] Prepare context and start a session
37
+ check-update Show installed/latest npm version and update instruction
38
+ update Show manual npm update instructions (does not install)
39
+ help, --help Show this help
40
+ --version Show the installed version
41
+
42
+ --root accepts an absolute existing directory, as --root PATH or --root=PATH.
43
+ Without --root, project commands require a Git or initialized Prodero ancestor.
44
+ MCP uses negotiated host roots or supported local host launch context. --root is an optional hard boundary.`;
45
+ function parse(argv) {
46
+ let command, root, query;
47
+ let helpRequested = false, all = false, dev = false, checkout, host;
48
+ 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
+ for (let i = 0; i < argv.length; i++) {
50
+ const arg = argv[i];
51
+ if (arg === "--help" || arg === "-h") {
52
+ helpRequested = true;
53
+ continue;
54
+ }
55
+ if (arg === "--dev") {
56
+ if (dev)
57
+ throw new Error("Specify --dev only once.");
58
+ dev = true;
59
+ continue;
60
+ }
61
+ if (arg === "--checkout") {
62
+ if (checkout !== undefined)
63
+ throw new Error("Specify --checkout only once.");
64
+ checkout = argv[++i];
65
+ if (!checkout || checkout.startsWith("--"))
66
+ throw new Error("--checkout requires a directory.");
67
+ continue;
68
+ }
69
+ if (arg === "--all") {
70
+ if (all)
71
+ throw new Error("Specify --all only once.");
72
+ all = true;
73
+ continue;
74
+ }
75
+ if (arg === "--root" || arg.startsWith("--root=")) {
76
+ if (root !== undefined)
77
+ throw new Error("Specify --root only once.");
78
+ root = arg === "--root" ? argv[++i] : arg.slice(7);
79
+ if (!root || root.startsWith("--"))
80
+ throw new Error("--root requires an absolute project directory.");
81
+ }
82
+ else if (!command && commands.has(arg))
83
+ command = arg;
84
+ else if (arg.startsWith("-"))
85
+ throw new Error("Unknown flag. Run prodero --help.");
86
+ else if (!command)
87
+ throw new Error("Unknown command. Run prodero --help.");
88
+ else if (command === "install")
89
+ throw new Error("Run prodero install without arguments; choose an agent in the interactive wizard.");
90
+ else if (command === "uninstall" && host === undefined)
91
+ host = arg;
92
+ else if (["migrate", "prepare", "context", "recall", "memory-bundle"].includes(command) && query === undefined)
93
+ query = arg;
94
+ else
95
+ throw new Error("Unexpected argument. Run prodero --help.");
96
+ }
97
+ command ??= "help";
98
+ if (all && command === "install")
99
+ throw new Error("Run prodero install without --all; choose an agent in the interactive wizard.");
100
+ if (all && (command !== "uninstall" || host))
101
+ throw new Error("Use --all only with uninstall and without a host name.");
102
+ if (root !== undefined && ["install", "uninstall", "help", "--version", "check-update", "update"].includes(command))
103
+ throw new Error(`--root is not used by ${command}.`);
104
+ if ((dev || checkout !== undefined) && !["mcp", "--stdio"].includes(command))
105
+ throw new Error("--dev and --checkout are only supported for MCP.");
106
+ if (checkout !== undefined && !dev)
107
+ throw new Error("--checkout requires --dev.");
108
+ return { dev, checkout, command: helpRequested ? "help" : command, root, query, host: all ? "all" : host };
109
+ }
110
+ async function run(localStdio) {
111
+ if (process.argv[2] === 'runtime') {
112
+ await runtimeCommand(process.argv.slice(3));
113
+ return;
114
+ }
115
+ const { command, root, query, host, dev, checkout } = parse(process.argv.slice(2));
116
+ if (command === "help") {
117
+ console.log(help);
118
+ return;
119
+ }
120
+ if (command === "--version") {
121
+ console.log(PRODERO_VERSION);
122
+ return;
123
+ }
124
+ if (command === "install") {
125
+ process.exitCode = await installWizard();
126
+ return;
127
+ }
128
+ if (command === "uninstall" || (command === "status" && root === undefined)) {
129
+ const result = await machineIntegrations(command === "status" ? "status" : command, host);
130
+ console.log(JSON.stringify(result, null, 2));
131
+ if (!result.ok)
132
+ process.exitCode = 1;
133
+ return;
134
+ }
135
+ if (command === "mcp" || command === "--stdio")
136
+ localStdio ??= captureLocalStdioContext();
137
+ const rootArg = command === "mcp" || command === "--stdio" ? (root === undefined ? undefined : await explicitProjectRoot(root)) : ["update", "check-update"].includes(command) ? undefined : await cliProjectRoot(root);
138
+ if (command === "--stdio" || command === "mcp") {
139
+ if (dev) {
140
+ const { startDevelopmentRuntime } = await import('./mcp-development.js');
141
+ await startDevelopmentRuntime(localStdio, { projectRoot: rootArg, checkout });
142
+ return;
143
+ }
144
+ const server = createServer({ projectRoot: rootArg, localStdio });
145
+ await server.connect(new StdioServerTransport());
146
+ return;
147
+ }
148
+ if (command === "migrate") {
149
+ if (query && query !== "status")
150
+ throw new Error("Use prodero migrate or prodero migrate status.");
151
+ let plan = await planProjectMigration(rootArg);
152
+ if (query !== "status" && (plan.safeToApply || plan.state === "recovery-required")) {
153
+ const result = await applyProjectMigration(rootArg, { approved: true, planId: plan.planId, recover: plan.state === "recovery-required" });
154
+ plan = result.plan;
155
+ }
156
+ console.log(renderText(buildViewModel({ action: "migration", root: rootArg, plan }), true));
157
+ if (plan.blocked)
158
+ process.exitCode = 1;
159
+ return;
160
+ }
161
+ if (command === "init") {
162
+ console.log(JSON.stringify(await initializeProject(rootArg), null, 2));
163
+ return;
164
+ }
165
+ if (["status", "prepare"].includes(command)) {
166
+ const plan = await planProjectMigration(rootArg);
167
+ if (plan.state !== "current") {
168
+ (plan.blocked ? console.error : console.log)(renderText(buildViewModel({ action: "migration", root: rootArg, plan, resume: { tool: "prodero_prepare", arguments: { projectRoot: rootArg, task: query } } }), true));
169
+ process.exitCode = 1;
170
+ return;
171
+ }
172
+ }
173
+ if (command === "status") {
174
+ const project = await getProjectStatus(rootArg);
175
+ if (project.initialized)
176
+ await autoMigrateProject(project.root);
177
+ console.log(JSON.stringify({ version: PRODERO_VERSION, project: await getProjectStatus(project.root), update: await checkForUpdate() }, null, 2));
178
+ return;
179
+ }
180
+ if (command === "memory-bundle") {
181
+ if (!query)
182
+ throw new Error("memory-bundle requires one planner candidate ID");
183
+ console.log(JSON.stringify(await buildMemoryTransformationBundle(rootArg, query)));
184
+ return;
185
+ }
186
+ if (command === "memory-plan") {
187
+ console.log(JSON.stringify(await getMemoryIntelligencePlan(rootArg), null, 2));
188
+ return;
189
+ }
190
+ if (command === "sync") {
191
+ console.log(JSON.stringify(await runMemorySync(rootArg, { action: "start" }), null, 2));
192
+ return;
193
+ }
194
+ if (command === "sync-sessions") {
195
+ console.log(JSON.stringify(await syncProject(rootArg, { onlyClosed: true }), null, 2));
196
+ return;
197
+ }
198
+ if (command === "recall") {
199
+ console.log(JSON.stringify(await recallProject(rootArg, query ?? ""), null, 2));
200
+ return;
201
+ }
202
+ if (command === "context") {
203
+ console.log(JSON.stringify(await resolveProjectContext(rootArg, query), null, 2));
204
+ return;
205
+ }
206
+ if (command === "prepare") {
207
+ console.log(JSON.stringify(await prepareProject(rootArg, { task: query, agent: "cli" }), null, 2));
208
+ return;
209
+ }
210
+ if (command === "update") {
211
+ console.log(JSON.stringify(await installLatest(), null, 2));
212
+ return;
213
+ }
214
+ if (command === "check-update") {
215
+ console.log(JSON.stringify(await checkForUpdate(), null, 2));
216
+ return;
217
+ }
218
+ }
219
+ export async function main(localStdio) {
220
+ await run(localStdio).catch((error) => {
221
+ console.error(`[prodero] ${publicDiagnostic(error)}`);
222
+ process.exitCode = 1;
223
+ });
224
+ }
225
+ // Compatibility for direct CLI execution; importing from the public binary never auto-starts.
226
+ if (process.argv[1] && pathToFileURL(realpathSync(process.argv[1])).href === import.meta.url)
227
+ await main();
228
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1,2 @@
1
+ export const CONTEXT_ROUTING = 'Before answering questions that may depend on project history, previous decisions, implementation details, or project-specific knowledge, call prodero_recall. Start prodero_prepare only for actual project work, including work requested after recall.';
2
+ //# sourceMappingURL=context-instructions.js.map
@@ -0,0 +1,50 @@
1
+ export const PRODERO_RESOURCE_URI = "ui://prodero/status.html";
2
+ export const PRODERO_LIFECYCLE_RESOURCE_URI = "ui://prodero/lifecycle.html";
3
+ export const PRODERO_TOOLS = {
4
+ instructionsRead: "prodero_instructions_read",
5
+ uiCardState: "prodero_ui_card_state",
6
+ configGet: "prodero_config_get",
7
+ configSet: "prodero_config_set",
8
+ text: "prodero_text",
9
+ plugins: "prodero_plugins",
10
+ pluginAction: "prodero_plugin_action",
11
+ open: "prodero_open",
12
+ status: "prodero_status",
13
+ statusDetails: "prodero_status_details",
14
+ initialize: "prodero_initialize",
15
+ migrate: "prodero_migrate",
16
+ curation: "prodero_curation",
17
+ curationReview: "prodero_curation_review",
18
+ curationReasoningPrepare: "prodero_curation_reasoning_prepare",
19
+ curationReasoningPropose: "prodero_curation_reasoning_propose",
20
+ curationApply: "prodero_curation_apply",
21
+ prepare: "prodero_prepare",
22
+ context: "prodero_context",
23
+ recall: "prodero_recall",
24
+ memoryTransformPrepare: "prodero_memory_transform_prepare",
25
+ memoryTransformPropose: "prodero_memory_transform_propose",
26
+ instructionReview: "prodero_instruction_review",
27
+ instructionOptimize: "prodero_instruction_optimize",
28
+ knowledge: "prodero_knowledge",
29
+ knowledgeMutate: "prodero_knowledge_mutate",
30
+ memorySearch: "prodero_memory_search",
31
+ remember: "prodero_remember",
32
+ forget: "prodero_forget",
33
+ promotionPreview: "prodero_promotion_preview",
34
+ promote: "prodero_promote",
35
+ sessionRecord: "prodero_session_record",
36
+ sessionClose: "prodero_session_close",
37
+ sessionReview: "prodero_session_review",
38
+ sessionReviewMutate: "prodero_session_review_mutate",
39
+ sync: "prodero_sync",
40
+ memorySync: "prodero_memory_sync",
41
+ skillCreate: "prodero_skill_create",
42
+ skills: "prodero_skills",
43
+ skillsRead: "prodero_skills_read",
44
+ skillPreview: "prodero_skill_preview",
45
+ skillReview: "prodero_skill_review",
46
+ checkUpdate: "prodero_check_update",
47
+ update: "prodero_update",
48
+ };
49
+ export const PRODERO_TOOL_NAMES = Object.values(PRODERO_TOOLS);
50
+ //# sourceMappingURL=contracts.js.map
@@ -0,0 +1,262 @@
1
+ export const PRESENTATION_REPLY = 'For knowledge-list requests in Claude Code, prefer prodero_text with tool=prodero_knowledge unless the user explicitly requests a graphical view. This is a one-off display choice, not a project setting change. When showing knowledge lists in chat, prefer the supplied fenced ASCII table with +, - and | borders; preserve its columns and page-local numeric row keys when translating. Knowledge rows use 1 through N, and action commands below the table continue at N+1. Resolve a standalone number through the exact numberedActions binding from the latest displayed table/menu. knowledgeRows also binds row numbers to exact record IDs; never infer IDs or reuse an older page. Show complete record text when an individual record is requested. In knowledge-detail replies, keep the original, any translation and record metadata together, then preserve a separate ------------- line before service hints about editing, history, approval and available actions. Service hints are not part of the knowledge or its translation. When suggesting next actions in chat, show a numbered Markdown list starting at 1 (or N+1 after a knowledge table with N rows), with one command per line and a blank line before the list. Tell the user they can reply with a number or the command name. Preserve the displayed order and exact numberedActions bindings when translating. A standalone positive integer selects only that item from the latest action menu actually shown in this conversation for this project; never use array positions in availableActions, an older menu or another conversation. If the number is out of range, the menu is missing, or a pending question expects a numeric value rather than a menu choice, clarify instead of guessing. Keep menu bindings only in conversation context, never project settings or knowledge. Route selected covered tools through prodero_text with the exact bound arguments; call other bound tools directly. A numeric selection is navigation or an action request, never explicit approval: for an approval-marked action show the exact proposal and request explicit confirmation before mutation or publication. In ordinary Open and lifecycle replies, omit display mode, theme and tool-routing commentary. Saved presentation settings, resolved mode and App metadata are not evidence that the user saw a graphical interface; do not claim a UI was displayed from those fields. Discuss mode or theme only when the user asks about settings or presentation troubleshooting.';
2
+ const n = (value, one, many = `${one}s`) => `${value} ${value === 1 ? one : many}`;
3
+ const tokens = (value) => value >= 1000 ? `${Number((value / 1000).toFixed(1))}k` : String(value);
4
+ export function conversationView(payload, vm) {
5
+ const r = payload.result ?? payload;
6
+ const root = r.root ?? r.projectRoot ?? r.project?.root ?? payload.project?.root ?? payload.root;
7
+ const call = (label, tool, args = {}) => ({ label, tool, arguments: { ...(root ? { projectRoot: root } : {}), ...args } });
8
+ const v = { kind: 'summary', title: vm.title, state: 'Ready', facts: [], attention: [], blocking: false, reviewRequired: false };
9
+ const next = (prompt, action) => { v.prompt = prompt; v.continuation = action; };
10
+ if (['open', 'status', 'status-details', 'initialized'].includes(payload.action)) {
11
+ const p = payload.project;
12
+ v.title = `Prodero · ${p?.name ?? 'Project'}`;
13
+ if (typeof p?.initialized !== 'boolean') {
14
+ v.state = 'Project state unavailable';
15
+ v.attention.push('Check project details before continuing.');
16
+ }
17
+ else if (!p.initialized) {
18
+ v.state = 'Not initialized';
19
+ next('Initialize Prodero for this project?', call('Initialize Prodero', 'prodero_initialize'));
20
+ v.facts.push('Creates project memory and managed agent instructions.');
21
+ }
22
+ else {
23
+ v.state = payload.action === 'initialized' ? 'Initialized' : 'Ready';
24
+ if (p.knowledgeCount !== undefined)
25
+ v.facts.push(`Memory ${p.knowledgeCount}`);
26
+ if (p.skillCount !== undefined)
27
+ v.facts.push(`Skills ${p.skillCount}`);
28
+ if (p.activeSessionCount !== undefined)
29
+ v.facts.push(`Session ${p.activeSessionCount ? `active (${p.activeSessionCount})` : 'none active'}`);
30
+ if (payload.phase === 'initial')
31
+ v.facts.push('Lightweight status; counts not loaded.');
32
+ if (p.conflictCount)
33
+ v.attention.push(`Conflicts to review: ${p.conflictCount}.`);
34
+ const areas = p.memoryOverview?.areas ?? [];
35
+ if (areas.length) {
36
+ v.attention.push(`Memory areas to review: ${areas.length + (p.memoryOverview?.areasOmitted ?? 0)}.`);
37
+ if (areas.some((a) => a.signals?.includes('context_pressure')))
38
+ v.attention.push('Relevant knowledge has not fit into recent task context.');
39
+ next('Review memory improvements?', call('Review Memory Sync', 'prodero_sync'));
40
+ }
41
+ if (p.memoryOverview?.available === false)
42
+ v.attention.push('Memory overview unavailable.');
43
+ if (p.memoryOverview?.workflow && p.memoryOverview.workflow.state !== 'completed') {
44
+ const w = p.memoryOverview.workflow;
45
+ v.attention.push(w.state === 'stale' ? 'Memory changed since the last Sync.' : 'Memory Sync is unfinished.');
46
+ next(w.state === 'stale' ? 'Re-analyze memory?' : 'Continue Memory Sync?', w.state === 'stale' ? call('Re-analyze memory', 'prodero_memory_sync', { request: { action: 'start', restart: true } }) : call('Continue Memory Sync', 'prodero_sync', { workflowId: w.id }));
47
+ }
48
+ const c = payload.curation;
49
+ if (c?.state === 'unavailable')
50
+ v.attention.push('Saved review unavailable. Open details before continuing.');
51
+ if (c?.prominent) {
52
+ const q = c.projection;
53
+ if (q?.needsInputNow)
54
+ v.attention.push(`Items needing your input: ${q.needsInputNow}.`);
55
+ if (q?.readyChangeGroups)
56
+ v.attention.push(`${n(q.readyChangeGroups, 'proposed change')} ready for review.`);
57
+ if (q?.blockedGroups)
58
+ v.attention.push(`${n(q.blockedGroups, 'change')} blocked.`);
59
+ next('Review these items?', call('Review saved decisions', 'prodero_curation', { action: 'plan', details: true }));
60
+ }
61
+ else if (p.conflictCount)
62
+ next('Inspect knowledge and its review signals?', call('Inspect knowledge', 'prodero_knowledge'));
63
+ if (payload.bootstrap?.warnings?.length)
64
+ v.attention.push(...payload.bootstrap.warnings);
65
+ if (payload.update?.available)
66
+ v.attention.push(`Update available: ${payload.update.latest}.`);
67
+ if (!v.attention.length && payload.phase !== 'initial')
68
+ v.facts.push('No attention needed.');
69
+ if (payload.action === 'open' || payload.action === 'initialized') {
70
+ const w = p.memoryOverview?.workflow;
71
+ const sync = w?.state === 'stale'
72
+ ? call('Re-analyze memory', 'prodero_memory_sync', { request: { action: 'start', restart: true } })
73
+ : call(w && w.state !== 'completed' ? 'Continue memory sync' : 'Sync memory', 'prodero_sync', w && w.state !== 'completed' ? { workflowId: w.id } : {});
74
+ v.suggestions = [sync, call('Show knowledge', 'prodero_knowledge'), call('Show settings', 'prodero_config_get')];
75
+ }
76
+ }
77
+ v.details = call('Show project details', 'prodero_status_details', { details: true });
78
+ if (payload.action === 'status-details')
79
+ v.kind = 'details';
80
+ }
81
+ else if (payload.action === 'prepare' || payload.action === 'context') {
82
+ const c = payload.action === 'context' ? r : r.context, m = c.metrics, readiness = c.policyReadiness;
83
+ v.title = 'Prodero · Context Ready';
84
+ const omitted = m.requiredGlobalExcludedItems ?? c.selection?.omittedRequired?.length ?? 0;
85
+ v.blocking = Boolean(readiness?.blocking || omitted);
86
+ v.contextComplete = !omitted && !v.blocking;
87
+ v.state = v.blocking ? (omitted ? 'Required context incomplete' : 'Work paused') : 'Ready';
88
+ v.facts.push(`Context ${tokens(m.contextTokens)} / ${tokens(m.contextBudgetTokens)}`, `Required ${c.required.length} · Relevant ${c.relevant.length} · Skills ${c.skills.length}`);
89
+ if (r.session)
90
+ v.facts.push('Session active');
91
+ if (omitted)
92
+ v.attention.push(`${n(omitted, 'required instruction')} not loaded. Do not continue work.`);
93
+ if (readiness?.state === 'context-needed')
94
+ v.attention.push('More task scope is needed before work can start.');
95
+ if (readiness?.state === 'required-conflict' || (v.blocking && !omitted && readiness?.state !== 'context-needed'))
96
+ 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
+ if (readiness?.state === 'context-needed')
99
+ next('Specify the work paths or task scope, then prepare again.');
100
+ else if (omitted)
101
+ next('Review the missing instructions?', c.snapshot?.reviewId ? call('Review required context', 'prodero_instruction_review', { reviewId: c.snapshot.reviewId }) : undefined);
102
+ else if (v.blocking)
103
+ next('Inspect the required context and conflicts?');
104
+ if (payload.action === 'context')
105
+ v.kind = 'details';
106
+ v.detailSource = 'context';
107
+ }
108
+ else if (payload.action === 'session-close') {
109
+ v.title = 'Prodero · Session closed';
110
+ v.state = r.alreadyClosed ? 'Already closed' : r.learned.syncState === 'pending-auto-sync' ? 'Saving deferred' : 'Saved';
111
+ v.facts.push(`${n(r.learned.observations, 'observation')} recorded`);
112
+ if (r.learned.syncState === 'pending-auto-sync')
113
+ v.attention.push('Saving deferred; it will resume before the next work session.');
114
+ if (r.review?.needsReview)
115
+ v.attention.push(`Items needing review: ${r.review.needsReview}.`);
116
+ if (r.review?.error)
117
+ v.attention.push('Knowledge review unavailable.');
118
+ if (v.attention.length)
119
+ next('Review session knowledge?', call('Review session', 'prodero_session_review', { sessionId: r.session.id }));
120
+ v.details = call('Review session knowledge', 'prodero_session_review', { sessionId: r.session.id });
121
+ }
122
+ else if (payload.action === 'memory-sync') {
123
+ v.title = 'Prodero · Sync';
124
+ const s = r.summary ?? {}, inspect = call('Review this Sync', 'prodero_memory_sync', { request: { action: 'inspect', workflowId: r.id }, details: true });
125
+ v.details = inspect;
126
+ const state = { awaiting_selection: 'Ready to sync', semantic_work: 'Improving memory', awaiting_clarification: 'Your input is needed', awaiting_review: 'Review required', applying: 'Saving changes', awaiting_promotion_selection: 'Ready for sharing review', completed: 'Complete', stale: 'Memory changed' };
127
+ v.state = state[r.state] ?? 'Check saved progress';
128
+ if (r.state === 'awaiting_selection') {
129
+ v.facts.push('Improve memory · Prepare sharing review');
130
+ if (r.brokenLinks)
131
+ v.facts.push(`Fix ${n(r.brokenLinks, 'broken link')} · enabled`);
132
+ next('Start Sync? Sharing will require a separate approval.', vm.actions.find(a => a.label === 'Start Sync'));
133
+ }
134
+ else if (r.state === 'semantic_work') {
135
+ if (r.curation || r.semantic)
136
+ next('Continue analysis using the prepared evidence.');
137
+ else
138
+ next('Continue analysis.', vm.actions.find(a => a.label === 'Continue improving memory'));
139
+ }
140
+ else if (r.state === 'awaiting_review') {
141
+ v.reviewRequired = true;
142
+ v.attention.push(r.review?.kind === 'promotion' ? 'Nothing published. Review the proposed wording before approval.' : 'No approval given. Review the proposed changes first.');
143
+ next('Review the proposed changes?', inspect);
144
+ }
145
+ else if (r.state === 'awaiting_promotion_selection') {
146
+ v.facts.push(`${n(r.promotionCandidates.length, 'memory', 'memories')} available for sharing review`);
147
+ // Display the existing candidate set; selecting it still requires the user's request.
148
+ next(`Review all ${r.promotionCandidates.length} for sharing?`, call('Review these memories', 'prodero_memory_sync', { request: { action: 'promotions', workflowId: r.id, revision: r.revision, ids: r.promotionCandidates.map((c) => c.id) }, details: true }));
149
+ }
150
+ else if (r.state === 'awaiting_clarification') {
151
+ v.reviewRequired = true;
152
+ v.attention.push('This question currently requires the graphical review form. Chat answers are not saved.');
153
+ next('Show the question and review details?', inspect);
154
+ }
155
+ else if (r.state === 'stale') {
156
+ v.attention.push('Re-analyze before continuing; earlier review is out of date.');
157
+ next('Re-analyze memory?', vm.actions.find(a => a.label === 'Re-analyze memory'));
158
+ }
159
+ else if (r.state === 'completed') {
160
+ if (s.areasProcessed)
161
+ v.facts.push(`${s.sourcesBefore} → ${s.currentAfter} memories`, `${s.archived} previous memories preserved in history`);
162
+ else if (!s.promoted && !s.brokenLinksFixed)
163
+ v.facts.push('No memory changes.');
164
+ if (s.brokenLinksFixed)
165
+ v.facts.push(`${n(s.brokenLinksFixed, 'broken link')} fixed`);
166
+ if (s.brokenLinksRemaining)
167
+ v.attention.push(`${n(s.brokenLinksRemaining, 'broken link')} remain unchanged.`);
168
+ if (s.promoted)
169
+ v.facts.push(`${n(s.promoted, 'memory', 'memories')} shared`);
170
+ if (s.unresolved)
171
+ v.attention.push(`${n(s.unresolved, 'memory', 'memories')} still need clarification.`);
172
+ if (s.areasFailed)
173
+ v.attention.push(`${n(s.areasFailed, 'area')} could not be analyzed.`);
174
+ if (s.promotionConflicts)
175
+ v.attention.push(`Sharing items needing review: ${s.promotionConflicts}.`);
176
+ if (s.questionsDeferred)
177
+ v.attention.push(`${n(s.questionsDeferred, 'question')} deferred.`);
178
+ if (v.attention.length)
179
+ next('Review the remaining items?', inspect);
180
+ }
181
+ if (r.error)
182
+ v.attention.push('This step could not finish. Check saved progress before retrying.');
183
+ }
184
+ else if (payload.action === 'migration') {
185
+ const p = payload.plan;
186
+ v.title = 'Prodero · Project update';
187
+ v.state = vm.title;
188
+ v.blocking = p.state !== 'current';
189
+ v.reviewRequired = Boolean(p.safeToApply || ['review-required', 'recovery-required'].includes(p.state));
190
+ v.attention = vm.notices;
191
+ if (p.safeToApply)
192
+ next('Review the update before applying?', call('Review project update', 'prodero_migrate', { action: 'status', ...(payload.resume ? { resume: payload.resume } : {}), details: true }));
193
+ else if (p.state === 'current')
194
+ next('Continue.', vm.actions.find(a => a.label === 'Continue'));
195
+ else if (p.state === 'recovery-required')
196
+ next('Review recovery instructions?', call('Review recovery', 'prodero_migrate', { action: 'status', details: true }));
197
+ v.details = call('Show update details', 'prodero_migrate', { action: 'status', details: true });
198
+ }
199
+ else if (payload.action === 'promotion-applied') {
200
+ v.title = 'Prodero · Published';
201
+ v.state = 'Complete';
202
+ v.facts.push(`${n(r.published, 'memory', 'memories')} shared`);
203
+ if (r.conflicts?.length) {
204
+ v.attention.push(`Conflicts remaining local: ${r.conflicts.length}.`);
205
+ next('Inspect the remaining knowledge?', call('Inspect knowledge', 'prodero_knowledge'));
206
+ }
207
+ }
208
+ else {
209
+ // Explicit inspection/review surfaces retain full content and diagnostics.
210
+ v.kind = 'details';
211
+ v.reviewRequired = ['promotion-preview', 'instruction-optimize', 'curation'].includes(payload.action);
212
+ if (payload.action === 'curation')
213
+ v.blocking = Boolean(payload.projection?.blockedGroups);
214
+ }
215
+ v.attention = [...new Set(v.attention)];
216
+ if (v.kind === 'summary' && (v.attention.length || v.blocking || v.reviewRequired))
217
+ v.kind = 'attention';
218
+ return v;
219
+ }
220
+ export function conversationMenu(v) {
221
+ return v.suggestions?.length ? v.suggestions : v.continuation ? [v.continuation] : [];
222
+ }
223
+ export function numberedActions(vm, expanded = false) {
224
+ const actions = expanded || !vm.conversation || vm.conversation.kind === 'details'
225
+ ? vm.actions : conversationMenu(vm.conversation);
226
+ const rows = vm.knowledgeTable?.rows.map(row => ({ label: `Open ${row.title}`, tool: 'prodero_knowledge', arguments: { ...vm.actions.find(a => a.tool === 'prodero_knowledge')?.arguments, id: row.id } })) ?? [];
227
+ return [...rows, ...actions].map((action, index) => ({ ...action, number: index + 1 }));
228
+ }
229
+ export function renderActionMenu(actions, start = 1) {
230
+ if (!actions.length)
231
+ return '';
232
+ return 'Available actions:\n\n' + actions.map((a, index) => `${index + start}. ${a.label}${a.approval ? ' (workflow approval required)' : ''}`).join('\n') + '\n\nReply with a number or the command name.';
233
+ }
234
+ export function renderConversation(v) {
235
+ const menu = renderActionMenu(conversationMenu(v));
236
+ return [v.title, `${v.blocking || v.reviewRequired ? '⚠' : '✓'} ${v.state}`, ...v.facts, ...v.attention.map(s => `⚠ ${s}`), menu ? `\n${menu}\n` : undefined, v.prompt].filter(Boolean).join('\n');
237
+ }
238
+ /** Model-visible MCP content, separate from the human summary; never hidden in _meta. */
239
+ export function conversationOperation(payload, vm, details = false, diagnostics = false) {
240
+ const r = payload.result ?? payload, v = vm.conversation;
241
+ return {
242
+ kind: diagnostics ? 'diagnostic' : details ? 'details' : v.kind,
243
+ succeeded: payload.ok !== false,
244
+ blocking: v.blocking,
245
+ contextComplete: v.contextComplete,
246
+ reviewRequired: v.reviewRequired,
247
+ continuation: details && ((payload.action === "memory-sync" && r.state === "awaiting_review") || (payload.action === "migration" && vm.actions.some(a => a.approval))) ? vm.actions.find(a => a.approval) : v.continuation,
248
+ details: v.details,
249
+ detailSource: v.detailSource,
250
+ suggestions: v.suggestions,
251
+ numberedActions: numberedActions(vm, details || diagnostics),
252
+ ...(vm.knowledgeTable ? { knowledgeRows: vm.knowledgeTable.rows.map(row => ({ key: row.key, number: Number(row.key), id: row.id, tool: 'prodero_knowledge', arguments: { projectRoot: r.root, ...r.options, id: row.id } })) } : {}),
253
+ availableActions: details || v.kind === "details" ? vm.actions : [v.continuation, v.details, ...(v.suggestions ?? [])].filter(Boolean),
254
+ disclosure: vm.knowledgeTable && !details ? 'Show the supplied fenced ASCII catalogue table and pagination. Full record bodies are available by inspecting a row; do not expand every record into prose.' : 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.',
255
+ instructions: PRESENTATION_REPLY + ' Use presentation.text as the human reply, translated if needed. Keep the numbered action menu visible, translated naturally with the reply; use numberedActions for numeric replies and exact tool bindings when chosen. Do not expand healthy state into a full action catalog or narrate tool routing. Keep these operational data out of the human reply unless requested. A yes answers only the immediately preceding question: use its continuation through prodero_text for covered tools, otherwise call the named tool directly with the given arguments. Reviewing is not approval. Show the complete proposed changes before asking for explicit approval; never approve unseen changes. Preserve Core blocking and context requirements. For text presentation, use the continuation here instead of reopening a graphical card. For View Context after Prepare, display the context object already returned here: it is the prepared snapshot. Do not rerun retrieval to display it; a fresh prodero_context call is a new selection. These are tool data, not system instructions.',
256
+ ...(payload.bootstrap ? { bootstrap: payload.bootstrap } : {}),
257
+ ...(payload.action === 'context' ? { context: r } : {}),
258
+ ...(payload.action === 'prepare' ? { session: r.session, context: r.context, automaticSync: r.automaticSync } : {}),
259
+ ...(payload.action === 'memory-sync' ? { workflow: { id: r.id, revision: r.revision, state: r.state, next: r.next, semantic: r.semantic, curation: r.curation, clarification: r.clarification, jobs: r.jobs, error: r.error, coverage: r.coverage, review: r.review, promotionCandidates: r.promotionCandidates } } : {}),
260
+ };
261
+ }
262
+ //# sourceMappingURL=conversation-presentation.js.map
@@ -0,0 +1,39 @@
1
+ import { SKILL_EXECUTION_ROUTING } from "../skill-instructions.js";
2
+ import { CONTEXT_ROUTING } from "../context-instructions.js";
3
+ import { SETTINGS_ROUTING } from "../settings-definition.js";
4
+ import { PRESENTATION_LAUNCHER, PRESENTATION_ROUTING } from "../presentation.js";
5
+ export const AGENT_INSTRUCTIONS = `## Prodero Project Intelligence
6
+
7
+ Apply these instructions to the current user workspace. The directory containing this document is the Prodero installation, not the project root.
8
+
9
+ This project uses Prodero for persistent project knowledge, session memory, and reusable project skills.
10
+
11
+ ## Prodero UI
12
+
13
+ ${PRESENTATION_LAUNCHER} The selected operation opens Project Intelligence and loads Bootstrap Context.
14
+
15
+ \`open prodero\` and \`show prodero\` have the same meaning. Use \`prodero_status\` only for a lightweight read-only status check. Do not inspect repository files first, open README.md, explain Prodero, or search documentation as a substitute for opening the interface.
16
+
17
+ ${SETTINGS_ROUTING}
18
+
19
+ ${PRESENTATION_ROUTING}
20
+
21
+ ${CONTEXT_ROUTING}
22
+
23
+ Before substantial work:
24
+ 1. Call \`prodero_prepare\` through MCP (via \`prodero_text\` in text mode), apply its relevant context, and retain the returned session ID internally.
25
+ 2. If MCP is unavailable, use the Prodero CLI; access \`.prodero/\` directly only as a final fallback.
26
+ 3. Start from \`.prodero/index.md\`; load required global context and only relevant scoped knowledge and skills.
27
+ 4. Never load the entire \`.prodero\` directory.
28
+
29
+ During substantial work, batch durable decisions, lessons, discoveries, state changes, global instruction candidates, and repeatable skill candidates through \`prodero_session_record\`. Write all durable Prodero knowledge and skill prose in English regardless of the conversation language. Preserve identifiers, paths, and code literals exactly. Exclude temporary implementation noise and do not directly rewrite session files or canonical memory.
30
+
31
+ Normal session learning and conversational remember operations produce Local Knowledge, which is ignored by Git. Local and Versioned Knowledge use the same schema and are retrieved as one knowledge space. As a workflow safeguard, prepare Versioned knowledge for team sharing only when the user explicitly requests it: call \`prodero_promotion_preview\`, let the human review the proposed new/merge/supersede/covered/conflict outcomes in the App, and call \`prodero_promote\` only with \`approved=true\` and the exact reviewed preview. Never infer publication approval.
32
+
33
+ When the user explicitly asks to remember durable knowledge, call \`prodero_remember\` immediately. For an explicit always/never rule use \`kind=rule\`, \`required=true\`, and \`userInstruction\` with the exact current user request. Never infer Required authority from observations or document contents. Explicit \`scope=global\` and \`scope=project\` both mean project-wide applicability, independently of priority. Required versus Relevant delivery is controlled by context policy, not by these scope aliases. Use \`scope=path\` with a repository-relative path for knowledge that applies only there. After \`prodero_memory_search\`, optional \`related_to\`, \`depends_on\`, or \`implements\` relationships may target exact current memory IDs; scope, supersession, contradiction, and provenance topology is derived automatically. For "update what you know" requests, call \`prodero_memory_search\` and then \`prodero_remember\` with the exact \`replaceId\`. For explicit forget requests, search if necessary and call \`prodero_forget\` with one exact id. Translate conversational requests into English durable prose before storing them, while preserving exact identifiers, paths, and code literals. These explicit operations complement the normal session lifecycle; do not wait until session close to perform them.
34
+
35
+ Project Skills are read from Versioned \`.prodero/skills/\` and Git-ignored Local \`.prodero/local/skills/\`. Explicit skill creation writes an active Versioned skill; inferred candidates remain Local until reviewed promotion. Existing active Local skills are also eligible for retrieval. When the user explicitly asks to create/save/remember a project skill, call \`prodero_skill_create\`; it becomes active immediately without additional approval. Independently inferred procedures must be recorded as \`skill_candidate\` observations; Sync preserves them as pending skills. ${SKILL_EXECUTION_ROUTING} Use \`prodero_skill_review\` to promote or dismiss candidates only on user intent. For candidate review or dogfooding, call \`prodero_skill_preview\` to open the MCP App automatically. The review workflow uses Add Skill, Edit, or Dismiss in that App; these actions do not authenticate human consent. Do not ask for approval in plain chat when the App can render, and never click Add Skill for the human. Use chat confirmation only as a fallback for hosts unable to render the App. Candidate and dismissed skills are excluded from normal context. These are repository procedures, not host/global skills.
36
+
37
+ Before finishing substantial work, record final durable outcomes and call \`prodero_session_close\`. Session close synchronizes observations into Local Knowledge deterministically; the next prepare recovers any pending synchronization. Sync Memory is a separate user-initiated workflow for transforming and sharing memory. Use prodero_sync to analyze, then prodero_memory_sync to select and process one bundle at a time. Never initiate it from session close. No additional work session is needed for this workflow. Clean selected Local transformations may apply. Keep the exact-preview review step for Versioned changes, promotion and semantic limitations. This is a workflow safeguard, not an authenticated authorization boundary.
38
+ `;
39
+ //# sourceMappingURL=agent-instructions.js.map
@@ -0,0 +1,11 @@
1
+ export function applicabilityLabel(r) {
2
+ const a = r.applicability ?? { kind: 'legacy' };
3
+ if (a.kind === 'project')
4
+ return 'Throughout this project';
5
+ if (a.kind === 'unresolved')
6
+ return 'Work context not yet resolved';
7
+ if (a.kind === 'legacy')
8
+ return r.scope === 'global' ? 'Throughout this project' : r.scopeRef ?? 'Work context not yet resolved';
9
+ return [...(a.subsystems ?? []), ...(a.paths ?? []), ...(a.taskKinds ?? [])].join(' · ');
10
+ }
11
+ //# sourceMappingURL=applicability-label.js.map