@prodero/curator 0.2.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/CHANGELOG.md +9 -3
- package/README.md +7 -7
- package/dist-ui/index.html +1 -1
- package/docs/COMPATIBILITY.md +17 -15
- package/docs/RELEASING.md +6 -6
- package/docs/hosts.md +4 -4
- package/docs/images/prodero-overview-cropped.png +0 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.2.
|
|
3
|
+
## 0.2.1 — 2026-10-25 (Public Preview)
|
|
4
4
|
|
|
5
|
-
|
|
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)
|
|
6
12
|
|
|
7
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.
|
|
8
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,7 +21,7 @@ Release notes finalized 2026-10-23. This is the preparation date; registry publi
|
|
|
15
21
|
- Incomplete provenance diagnostics no longer imply proven loss of history; no provenance backfill or canonical storage redesign is included.
|
|
16
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.
|
|
17
23
|
|
|
18
|
-
Project schema remains **8** and knowledge schema remains **3**.
|
|
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.
|
|
19
25
|
|
|
20
26
|
## 0.1.0 — 2026-10-15 (Public Preview)
|
|
21
27
|
|
package/README.md
CHANGED
|
@@ -2,18 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
**Project memory for Codex and Claude Code.**
|
|
4
4
|
|
|
5
|
-
> **0.2.0 release materials.** The npm command below requires 0.2.0 to be published. For review before publication, use the exact candidate tarball and isolated setup in [the release guide](docs/RELEASING.md). A checkout or local tarball does not establish registry availability. See [0.2.0 changes](CHANGELOG.md) and [verification limits](docs/COMPATIBILITY.md).
|
|
6
|
-
|
|
7
5
|
Keep project decisions, conventions, and lessons across sessions, right inside your coding assistant.
|
|
8
6
|
|
|
9
7
|
**Install in two commands → open Codex or Claude Code → type prodero.**
|
|
10
8
|
|
|
11
9
|
```sh
|
|
12
|
-
npm install --global @prodero/curator@0.2.
|
|
10
|
+
npm install --global @prodero/curator@0.2.1
|
|
13
11
|
prodero install
|
|
14
12
|
```
|
|
15
13
|
|
|
16
|
-
Requires **Node.js >=22.14.0 <23**, npm and Git. **v0.2.
|
|
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).
|
|
17
15
|
|
|
18
16
|
1. In the installation wizard, select **Codex** or **Claude Code**, confirm the setup and choose **Finish**.
|
|
19
17
|
2. Reopen Codex or Claude Code in your repository and type **`prodero`** in chat.
|
|
@@ -21,7 +19,9 @@ Requires **Node.js >=22.14.0 <23**, npm and Git. **v0.2.0 preview release.** Cod
|
|
|
21
19
|
|
|
22
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).
|
|
23
21
|
|
|
24
|
-

|
|
23
|
+
|
|
24
|
+
*Current Curator App with demonstration project data.*
|
|
25
25
|
|
|
26
26
|
## Relevant context, automatically
|
|
27
27
|
|
|
@@ -68,7 +68,7 @@ The generated `.prodero/index.md` can include active **Local skill titles and pa
|
|
|
68
68
|
|
|
69
69
|
## Compatibility and limitations
|
|
70
70
|
|
|
71
|
-
|
|
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).
|
|
72
72
|
|
|
73
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).
|
|
74
74
|
|
|
@@ -91,4 +91,4 @@ Curator is [MIT licensed](LICENSE).
|
|
|
91
91
|
|
|
92
92
|
### Updating the installed core
|
|
93
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. 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#
|
|
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-ui/index.html
CHANGED
|
@@ -83,7 +83,7 @@ Boolean requesting whether a visible border and background is provided by the ho
|
|
|
83
83
|
- omitted: host decides border`)});k({method:$("ui/request-display-mode"),params:k({mode:Yn.describe("The display mode being requested.")})});var mb=k({mode:Yn.describe("The display mode that was actually set. May differ from requested if not supported.")}).passthrough(),fb=ce([$("model"),$("app")]).describe("Tool visibility scope - who can access the tool.");k({resourceUri:b().optional(),visibility:G(fb).optional().describe(`Who can access this tool. Default: ["model", "app"]
|
|
84
84
|
- "model": Tool visible to and callable by the agent
|
|
85
85
|
- "app": Tool callable by the app from this server only`),csp:on().optional(),permissions:on().optional()});k({mimeTypes:G(b()).optional().describe('Array of supported MIME types for UI resources.\nMust include `"text/html;profile=mcp-app"` for MCP Apps support.')});k({method:$("ui/download-file"),params:k({contents:G(ce([Rm,Nm])).describe("Resource contents to download — embedded (inline data) or linked (host fetches). Uses standard MCP resource types.")})});k({method:$("ui/message"),params:k({role:$("user").describe('Message role, currently only "user" is supported.'),content:G(_r).describe("Message content blocks (text, image, etc.).")})});k({method:$("ui/notifications/sandbox-resource-ready"),params:k({html:b().describe("HTML content to load into the inner iframe."),sandbox:b().optional().describe("Optional override for the inner iframe's sandbox attribute."),csp:Ka.optional().describe("CSP configuration from resource metadata."),permissions:Ba.optional().describe("Sandbox permissions from resource metadata.")})});var hb=k({method:$("ui/notifications/tool-result"),params:Yi.describe("Standard MCP tool execution result.")}),Um=k({toolInfo:k({id:hr.optional().describe("JSON-RPC id of the tools/call request."),tool:Ha.describe("Tool definition including name, inputSchema, etc.")}).optional().describe("Metadata of the tool call that instantiated this App."),theme:Xy.optional().describe("Current color theme preference."),styles:lb.optional().describe("Style configuration for theming the app."),displayMode:Yn.optional().describe("How the UI is currently displayed."),availableDisplayModes:G(Yn).optional().describe("Display modes the host supports."),containerDimensions:ce([k({height:ie().describe("Fixed container height in pixels.")}),k({maxHeight:ce([ie(),Wn()]).optional().describe("Maximum container height in pixels.")})]).and(ce([k({width:ie().describe("Fixed container width in pixels.")}),k({maxWidth:ce([ie(),Wn()]).optional().describe("Maximum container width in pixels.")})])).optional().describe(`Container dimensions. Represents the dimensions of the iframe or other
|
|
86
|
-
container holding the app. Specify either width or maxWidth, and either height or maxHeight.`),locale:b().optional().describe("User's language and region preference in BCP 47 format."),timeZone:b().optional().describe("User's timezone in IANA format."),userAgent:b().optional().describe("Host application identifier."),platform:ce([$("web"),$("desktop"),$("mobile")]).optional().describe("Platform type for responsive design decisions."),deviceCapabilities:k({touch:xe().optional().describe("Whether the device supports touch input."),hover:xe().optional().describe("Whether the device supports hover interactions.")}).optional().describe("Device input capabilities."),safeAreaInsets:k({top:ie().describe("Top safe area inset in pixels."),right:ie().describe("Right safe area inset in pixels."),bottom:ie().describe("Bottom safe area inset in pixels."),left:ie().describe("Left safe area inset in pixels.")}).optional().describe("Mobile safe area boundaries in pixels.")}).passthrough(),gb=k({method:$("ui/notifications/host-context-changed"),params:Um.describe("Partial context update containing only changed fields.")});k({method:$("ui/update-model-context"),params:k({content:G(_r).optional().describe("Context content blocks (text, image, etc.)."),structuredContent:de(b(),Ie().describe("Structured content for machine-readable context data.")).optional().describe("Structured content for machine-readable context data.")})});k({method:$("ui/initialize"),params:k({appInfo:Gi.describe("App identification (name and version)."),appCapabilities:pb.describe("Features and capabilities this app provides."),protocolVersion:b().describe("Protocol version this app supports.")})});var vb=k({protocolVersion:b().describe('Negotiated protocol version string (e.g., "2025-11-21").'),hostInfo:Gi.describe("Host application identification and version."),hostCapabilities:db.describe("Features and capabilities provided by the host."),hostContext:Um.describe("Rich context about the host environment.")}).passthrough(),yb={target:"draft-2020-12"};async function Bc(e,t){let r=e["~standard"];if(r.jsonSchema)return r.jsonSchema[t](yb);if(r.vendor==="zod"){let{z:o}=await af(()=>Promise.resolve().then(()=>sv),void 0,import.meta.url);return o.toJSONSchema(e,{io:t})}throw Error(`Schema (vendor: ${r.vendor}) does not implement Standard JSON Schema (~standard.jsonSchema). Use a library that does (zod v4, ArkType, Valibot) or wrap your schema accordingly.`)}async function Jc(e,t,r=""){let o=await e["~standard"].validate(t);if(o.issues){let n=o.issues.map(i=>{var a;let s=(a=i.path)==null?void 0:a.map(c=>typeof c=="object"?c.key:c).join(".");return s?`${s}: ${i.message}`:i.message}).join("; ");throw Error(r+n)}return o.value}const Br=class Br extends Wy{constructor(r,o={},n={autoResize:!0}){super(n);be(this,"_appInfo");be(this,"_capabilities");be(this,"options");be(this,"_hostCapabilities");be(this,"_hostInfo");be(this,"_hostContext");be(this,"_registeredTools",{});be(this,"_initializedSent",!1);be(this,"eventSchemas",{toolinput:ob,toolinputpartial:sb,toolresult:hb,toolcancelled:ab,hostcontextchanged:gb});be(this,"_everHadListener",new Set);be(this,"_toolHandlersInitialized",!1);be(this,"_onteardown");be(this,"_oncalltool");be(this,"_onlisttools");be(this,"sendOpenLink",this.openLink);this._appInfo=r,this._capabilities=o,this.options=n,n.allowUnsafeEval||Ke({jitless:!0}),this.setRequestHandler(Qi,i=>(console.log("Received ping:",i.params),{})),this.setEventHandler("hostcontextchanged",void 0)}_assertInitialized(r){var n;if(this._initializedSent)return;let o=`[ext-apps] App.${r}() called before connect() completed the ui/initialize handshake. Await app.connect() before calling this method, or move data loading to an ontoolresult handler.`;if((n=this.options)!=null&&n.strict)throw Error(o);console.warn(`${o}. This will throw in a future release.`)}_assertHandlerTiming(r){var n;if(!Br.ONE_SHOT_EVENTS.has(r)||this._everHadListener.has(r)||(this._everHadListener.add(r),!this._initializedSent))return;let o=`[ext-apps] "${String(r)}" handler registered after connect() completed the ui/initialize handshake. The host may have already sent this notification. Register handlers before calling app.connect().`;if((n=this.options)!=null&&n.strict)throw Error(o);console.warn(o)}setEventHandler(r,o){o&&this._assertHandlerTiming(r),super.setEventHandler(r,o)}addEventListener(r,o){this._assertHandlerTiming(r),super.addEventListener(r,o)}onEventDispatch(r,o){r==="hostcontextchanged"&&(this._hostContext={...this._hostContext,...o})}registerCapabilities(r){if(this.transport)throw Error("Cannot register capabilities after transport is established");this._capabilities=Vy(this._capabilities,r)}registerTool(r,o,n){if(this._registeredTools[r])throw Error(`Tool ${r} is already registered`);let i=this,s=()=>{var l;i._initializedSent&&((l=i._capabilities.tools)!=null&&l.listChanged)&&i.sendToolListChanged()},a=o.inputSchema!==void 0,c={title:o.title,description:o.description,inputSchema:o.inputSchema,outputSchema:o.outputSchema,annotations:o.annotations,_meta:o._meta,enabled:!0,enable(){this.enabled=!0,s()},disable(){this.enabled=!1,s()},update(l){Object.assign(this,l),s()},remove(){i._registeredTools[r]===c&&(delete i._registeredTools[r],s())},handler:async(l,d)=>{if(!c.enabled)throw Error(`Tool ${r} is disabled`);let u;if(a){let m=c.inputSchema,h=m?await Jc(m,l??{},`Invalid input for tool ${r}: `):l??{};u=await n(h,d)}else u=await n(d);return c.outputSchema&&!u.isError&&(u.structuredContent=await Jc(c.outputSchema,u.structuredContent,`Invalid output for tool ${r}: `)),u}};return this._registeredTools[r]=c,!this._capabilities.tools&&!this.transport&&this.registerCapabilities({tools:{listChanged:!0}}),this.ensureToolHandlersInitialized(),s(),c}ensureToolHandlersInitialized(){this._toolHandlersInitialized||(this._toolHandlersInitialized=!0,this.oncalltool=async(r,o)=>{let n=this._registeredTools[r.name];if(!n)throw Error(`Tool ${r.name} not found`);return n.handler(r.arguments,o)},this.onlisttools=async(r,o)=>({tools:await Promise.all(Object.entries(this._registeredTools).filter(([n,i])=>i.enabled).map(async([n,i])=>{let s={name:n,title:i.title,description:i.description,inputSchema:i.inputSchema?await Bc(i.inputSchema,"input"):{type:"object",properties:{}}};return i.outputSchema&&(s.outputSchema=await Bc(i.outputSchema,"output")),i.annotations&&(s.annotations=i.annotations),i._meta&&(s._meta=i._meta),s}))}))}async sendToolListChanged(r={}){this._assertInitialized("sendToolListChanged"),await this.notification({method:"notifications/tools/list_changed",params:r})}getHostCapabilities(){return this._hostCapabilities}getHostVersion(){return this._hostInfo}getHostContext(){return this._hostContext}get ontoolinput(){return this.getEventHandler("toolinput")}set ontoolinput(r){this.setEventHandler("toolinput",r)}get ontoolinputpartial(){return this.getEventHandler("toolinputpartial")}set ontoolinputpartial(r){this.setEventHandler("toolinputpartial",r)}get ontoolresult(){return this.getEventHandler("toolresult")}set ontoolresult(r){this.setEventHandler("toolresult",r)}get ontoolcancelled(){return this.getEventHandler("toolcancelled")}set ontoolcancelled(r){this.setEventHandler("toolcancelled",r)}get onhostcontextchanged(){return this.getEventHandler("hostcontextchanged")}set onhostcontextchanged(r){this.setEventHandler("hostcontextchanged",r)}get onteardown(){return this._onteardown}set onteardown(r){this.warnIfRequestHandlerReplaced("onteardown",this._onteardown,r),this._onteardown=r,this.replaceRequestHandler(ub,(o,n)=>{if(!this._onteardown)throw Error("No onteardown handler set");return this._onteardown(o.params,n)})}get oncalltool(){return this._oncalltool}set oncalltool(r){this.warnIfRequestHandlerReplaced("oncalltool",this._oncalltool,r),this._oncalltool=r,this.replaceRequestHandler(Om,(o,n)=>{if(!this._oncalltool)throw Error("No oncalltool handler set");return this._oncalltool(o.params,n)})}get onlisttools(){return this._onlisttools}set onlisttools(r){this.warnIfRequestHandlerReplaced("onlisttools",this._onlisttools,r),this._onlisttools=r,this.replaceRequestHandler(Pm,(o,n)=>{if(!this._onlisttools)throw Error("No onlisttools handler set");return this._onlisttools(o.params,n)})}assertCapabilityForMethod(r){var o;switch(r){case"sampling/createMessage":if(!((o=this._hostCapabilities)!=null&&o.sampling))throw Error(`Host does not support sampling (required for ${r})`);break}}assertRequestHandlerCapability(r){switch(r){case"tools/call":case"tools/list":if(!this._capabilities.tools)throw Error(`Client does not support tool capability (required for ${r})`);return;case"ping":case"ui/resource-teardown":return;default:throw Error(`No handler for method ${r} registered`)}}assertNotificationCapability(r){}assertTaskCapability(r){throw Error("Tasks are not supported in MCP Apps")}assertTaskHandlerCapability(r){throw Error("Task handlers are not supported in MCP Apps")}async callServerTool(r,o){if(this._assertInitialized("callServerTool"),typeof r=="string")throw Error(`callServerTool() expects an object as its first argument, but received a string ("${r}"). Did you mean: callServerTool({ name: "${r}", arguments: { ... } })?`);return await this.request({method:"tools/call",params:r},Yi,{onprogress:()=>{},resetTimeoutOnProgress:!0,...o})}async readServerResource(r,o){return this._assertInitialized("readServerResource"),await this.request({method:"resources/read",params:r},Tm,o)}async listServerResources(r,o){return this._assertInitialized("listServerResources"),await this.request({method:"resources/list",params:r},zm,o)}async createSamplingMessage(r,o){this._assertInitialized("createSamplingMessage");let n=r.tools?Am:Em;return await this.request({method:"sampling/createMessage",params:r},n,o)}sendMessage(r,o){return this._assertInitialized("sendMessage"),this.request({method:"ui/message",params:r},ib,o)}sendLog(r){return this.notification({method:"notifications/message",params:r})}updateModelContext(r,o){return this._assertInitialized("updateModelContext"),this.request({method:"ui/update-model-context",params:r},Ta,o)}openLink(r,o){return this._assertInitialized("openLink"),this.request({method:"ui/open-link",params:r},nb,o)}downloadFile(r,o){return this._assertInitialized("downloadFile"),this.request({method:"ui/download-file",params:r},rb,o)}requestTeardown(r={}){return this.notification({method:"ui/notifications/request-teardown",params:r})}requestDisplayMode(r,o){return this._assertInitialized("requestDisplayMode"),this.request({method:"ui/request-display-mode",params:r},mb,o)}sendSizeChanged(r){return this.notification({method:"ui/notifications/size-changed",params:r})}setupSizeChangedNotifications(){let r=!1,o=0,n=0,i=()=>{r||(r=!0,requestAnimationFrame(()=>{r=!1;let a=document.documentElement,c=a.style.height;a.style.height="max-content";let l=Math.ceil(a.getBoundingClientRect().height);a.style.height=c;let d=Math.ceil(window.innerWidth);(d!==o||l!==n)&&(o=d,n=l,this.sendSizeChanged({width:d,height:l}))}))};i();let s=new ResizeObserver(i);return s.observe(document.documentElement),s.observe(document.body),()=>s.disconnect()}async connect(r=new Yy(window.parent,window.parent),o){var n;if(this.transport)throw Error("App is already connected. Call close() before connecting again.");this._initializedSent=!1,await super.connect(r);try{let i=await this.request({method:"ui/initialize",params:{appCapabilities:this._capabilities,appInfo:this._appInfo,protocolVersion:Gy}},vb,o);if(i===void 0)throw Error(`Server sent invalid initialize result: ${i}`);this._hostCapabilities=i.hostCapabilities,this._hostInfo=i.hostInfo,this._hostContext=i.hostContext,await this.notification({method:"ui/notifications/initialized"}),this._initializedSent=!0,(n=this.options)!=null&&n.autoResize&&this.setupSizeChangedNotifications()}catch(i){throw this.close(),i}}};be(Br,"ONE_SHOT_EVENTS",new Set(["toolinput","toolinputpartial","toolresult","toolcancelled"]));let So=Br;const pe={instructionsRead:"prodero_instructions_read",uiCardState:"prodero_ui_card_state",configGet:"prodero_config_get",configSet:"prodero_config_set",text:"prodero_text",plugins:"prodero_plugins",pluginAction:"prodero_plugin_action",open:"prodero_open",status:"prodero_status",statusDetails:"prodero_status_details",initialize:"prodero_initialize",migrate:"prodero_migrate",curation:"prodero_curation",curationReview:"prodero_curation_review",curationQuestion:"prodero_curation_question",curationReasoningPrepare:"prodero_curation_reasoning_prepare",curationReasoningPropose:"prodero_curation_reasoning_propose",curationApply:"prodero_curation_apply",prepare:"prodero_prepare",context:"prodero_context",recall:"prodero_recall",memoryTransformPrepare:"prodero_memory_transform_prepare",memoryTransformPropose:"prodero_memory_transform_propose",instructionReview:"prodero_instruction_review",instructionOptimize:"prodero_instruction_optimize",knowledge:"prodero_knowledge",knowledgeMutate:"prodero_knowledge_mutate",memorySearch:"prodero_memory_search",remember:"prodero_remember",forget:"prodero_forget",promotionPreview:"prodero_promotion_preview",promote:"prodero_promote",sessionRecord:"prodero_session_record",sessionClose:"prodero_session_close",sessionReview:"prodero_session_review",sessionReviewMutate:"prodero_session_review_mutate",sync:"prodero_sync",memorySync:"prodero_memory_sync",skillCreate:"prodero_skill_create",skills:"prodero_skills",skillsRead:"prodero_skills_read",skillPreview:"prodero_skill_preview",skillReview:"prodero_skill_review",checkUpdate:"prodero_check_update",update:"prodero_update"};function bb(e){var t;return!e||((t=e.snapshot)==null?void 0:t.version)!==1||!e.snapshot.sessionId?null:e}const $b=6e3,Fr=[{id:"prodero",label:"Current / Prodero",swatch:"#c6ff76",base:"#0b0d0c"},{id:"dark-neon",label:"Dark Neon",swatch:"#b6efff",base:"#020304"},{id:"pink-neon",label:"Pink Neon",swatch:"#ff63c5",base:"#090307"},{id:"blue-neon",label:"Blue Neon",swatch:"#55c9ff",base:"#020710"},{id:"purple-neon",label:"Purple Neon",swatch:"#b98aff",base:"#07030e"},{id:"light",label:"Light",swatch:"#3e6516",base:"#f7f9fc"},{id:"system",label:"System",swatch:"#a0adbd",base:"#f7f9fc"}],qm=Oo(["auto","ui","text"]),Zm=Oo(["prodero","dark-neon","pink-neon","blue-neon","purple-neon","light","system"]);Ef({mode:qm.optional(),theme:Zm.optional()}).passthrough();Cf().int().min(1).max(1e6);Oo(["presentation.mode","presentation.theme","context.max_tokens"]);function io(e){return Fr.some(t=>t.id===e)?e:"prodero"}function _b(e){var u,m;let t="prodero",r,o,n=0,i,s,a="default";const c=()=>a==="local override"?"Saved on this checkout.":a==="legacy project default"?"Using the legacy project default.":"Using the built-in default.";let l="Open a project to choose its theme.";const d=()=>{var w;const h=r??(e.media?e.media.matches?"dark":"light":void 0);e.root.dataset.proderoTheme=t==="system"?h==="light"?"light":h==="dark"?"dark-neon":"prodero":t,(w=e.changed)==null||w.call(e,t,l,a)};return(m=(u=e.media)==null?void 0:u.addEventListener)==null||m.call(u,"change",d),d(),{get selected(){return t},get project(){return o},setProject(h,w,f,g){n++,o=h,i=f,s=g==null?void 0:g.reset,a=(g==null?void 0:g.source)??"default",t=io(w),l=c()+" System follows host appearance when available."+(g!=null&&g.notice?" "+g.notice:""),d()},async select(h){if(!o||!i)return;const w=io(h),f=o,g=++n;l="Saving checkout theme…",d();try{if(await i(f,w),g!==n||f!==o)return;t=w,a="local override",l=c(),d()}catch(y){g===n&&f===o&&(l=y instanceof Error?y.message:"Could not save checkout theme.",d())}},async reset(){if(!o||!s||a!=="local override")return;const h=o,w=++n;l="Resetting checkout theme…",d();try{const f=await s(h);if(w!==n||h!==o)return;t=io(f.theme),a=f.source,l=c(),d()}catch(f){w===n&&h===o&&(l=f instanceof Error?f.message:"Could not reset checkout theme.",d())}},setHostTheme(h){(h==="light"||h==="dark")&&(r=h,d())},dispose(){var h,w;n++,(w=(h=e.media)==null?void 0:h.removeEventListener)==null||w.call(h,"change",d)}}}function wb(){var o;const e=document.querySelector("#theme-settings");if(!e)return;e.innerHTML=`<details class="theme-picker"><summary>Appearance <span id="theme-current"></span></summary><fieldset><legend>Theme on this checkout</legend><div class="theme-options">${Fr.map(n=>`<label style="--swatch:${n.swatch};--swatch-base:${n.base}"><input disabled type="radio" name="prodero-theme" value="${n.id}"><span class="theme-swatch" aria-hidden="true"></span><span>${n.label}</span></label>`).join("")}</div><p id="theme-persistence"></p><button type="button" id="theme-reset" hidden>Use project/default setting</button></fieldset></details>`;let t;try{t=(o=window.matchMedia)==null?void 0:o.call(window,"(prefers-color-scheme: dark)")}catch{}const r=_b({root:document.documentElement,media:t,changed(n,i,s){e.querySelector("#theme-current").textContent=Fr.find(l=>l.id===n).label;const a=i.startsWith("Saving")||i.startsWith("Resetting");e.querySelectorAll("input").forEach(l=>{l.checked=l.value===n,l.disabled=i.startsWith("Open a project")||a});const c=e.querySelector("#theme-reset");c.hidden=s!=="local override",c.disabled=a,e.querySelector("#theme-persistence").textContent=i}});return e.addEventListener("change",n=>{const i=n.target;i instanceof HTMLInputElement&&i.name==="prodero-theme"&&r.select(i.value)}),e.querySelector("#theme-reset").addEventListener("click",()=>void r.reset()),r}const Ct=wb();function kb(e){let t,r,o=0,n=!0,i=!0,s=0,a=!1,c=!1;const l=()=>{r!==void 0&&e.cancel(r),r=void 0},d=m=>{n=m,e.display(m)};async function u(m){if(!(m!==o||!t||i)){try{const h=await e.inspect(t,!a);if(m!==o)return;const w=!a;if(a=!0,s=0,!h.available){i=!0;return}if(h.superseded){i=!0,d(!0);return}w&&d(!1)}catch{if(m!==o)return;if(++s>=3){i=!0;return}}m===o&&!i&&e.visible()&&(r=e.schedule(()=>{r=void 0,u(m)},4e3*Math.max(1,s)))}}return{adopt(m){c&&t===m||(c=!0,l(),o++,t=m,i=!t,s=0,a=!1,d(!!t),u(o))},toggle(){c=!0,l(),o++,i=!0,d(!n)},visibilityChanged(){l(),o++,u(o)},dispose(){l(),o++,i=!0}}}function Sb(e,t){const r=document.querySelector("#card-disclosure"),o=document.querySelector("#card-toggle"),n=document.querySelector("#card-content"),i=document.querySelector("#card-title"),s=document.querySelector("#card-toggle-label");if(!r||!o||!n||!i||!s)return;const a=kb({inspect:async(u,m)=>{var w,f;const h=await e({name:pe.uiCardState,arguments:{cardId:u,activate:m}});if(h.isError||typeof((w=h.structuredContent)==null?void 0:w.available)!="boolean"||typeof((f=h.structuredContent)==null?void 0:f.superseded)!="boolean")throw new Error("Card state unavailable");return h.structuredContent},display(u){u&&n.contains(document.activeElement)&&o.focus({preventScroll:!0}),n.hidden=u,o.setAttribute("aria-expanded",String(!u)),s.textContent=u?"Expand":"Collapse",t&&t({height:Math.ceil((u?r:document.body).getBoundingClientRect().height)}).catch(()=>{})},schedule:(u,m)=>window.setTimeout(u,m),cancel:u=>window.clearTimeout(u),visible:()=>document.visibilityState!=="hidden"});o.addEventListener("click",()=>a.toggle()),document.addEventListener("visibilitychange",()=>a.visibilityChanged());const c=typeof MutationObserver>"u"?void 0:new MutationObserver(()=>{var m;const u=(m=n.querySelector("h1"))==null?void 0:m.textContent;u&&(i.textContent=u)});c==null||c.observe(n,{childList:!0,subtree:!0});const l=()=>{a.dispose(),c==null||c.disconnect()};window.addEventListener("pagehide",l);let d;return{present(u,m){var f,g,y;const h=((f=u==null?void 0:u.presentation)==null?void 0:f.resolved)==="text";if(r.hidden=h,i.textContent=m.replace(/^Prodero\s*·\s*/i,""),h){a.dispose(),n.hidden=!1;return}const w=(y=(g=u==null?void 0:u.presentation)==null?void 0:g.card)==null?void 0:y.id;typeof w=="string"&&w!==d?(d=w,a.adopt(w)):d||a.adopt(void 0)},dispose:l}}const D=document.querySelector("#app");let O=null,ae=null,ke=null,zt=null,Xn=!1,Le=null,We=null,Mn=!1,C=null,T="",oo=null,wt=!1,kt=null,Se=null,Pe=null,$t=!1,Q=null,Ja=null,er=!1,St=null,F=null,$e=null,On,Qt={query:"",offset:0,limit:12},it=null,Tt=null,mn=!1,zr=!1;const re=new So({name:"Prodero Project Intelligence",version:"0.2.0"}),yn=Sb(e=>re.callServerTool(e),e=>re.sendSizeChanged(e));re.onteardown=async()=>(yn==null||yn.dispose(),{});function Ue(e){var r,o;if(e!=null&&e.structuredContent)return e.structuredContent;const t=(o=(r=e==null?void 0:e.content)==null?void 0:r.find(n=>n.type==="text"))==null?void 0:o.text;if(!t)return null;try{return JSON.parse(t)}catch{return{message:t}}}function Va(e){var r,o;const t=e==null?void 0:e.projectSettings;t!=null&&t.root&&(Ct==null||Ct.setProject(t.root,t.presentation.theme,async(n,i)=>{var a,c;const s=await re.callServerTool({name:pe.configSet,arguments:{projectRoot:n,key:"presentation.theme",value:i}});if(s.isError)throw new Error(((c=(a=s.content)==null?void 0:a.find(l=>l.type==="text"))==null?void 0:c.text)??"Could not save project theme.")},{source:(r=t.presentationSources)==null?void 0:r.theme,notice:(o=t.diagnostics)==null?void 0:o.map(n=>`${n.code}: ${n.cause} ${n.recovery}`).join(" "),reset:async n=>{var a,c,l,d;const i=await re.callServerTool({name:pe.configSet,arguments:{projectRoot:n,key:"presentation.theme",reset:!0}});if(i.isError)throw new Error(((c=(a=i.content)==null?void 0:a.find(u=>u.type==="text"))==null?void 0:c.text)??"Could not reset checkout theme.");const s=(l=Ue(i))==null?void 0:l.projectSettings;if(!(s!=null&&s.presentation))throw new Error("Theme reset result unavailable. Refresh settings before retrying.");return{theme:s.presentation.theme,source:((d=s.presentationSources)==null?void 0:d.theme)??"default"}}}))}function p(e){return e.replace(/[&<>'"]/g,t=>({"&":"&","<":"<",">":">","'":"'",'"':"""})[t])}function pt(e,t,r){return`<div class="metric"><strong>${e}</strong><span>${t}</span>${r?`<small>${r}</small>`:""}</div>`}function xb(e,t,r){return pt(e===void 0?"—":e,t,r)}function st(e=0){return e>=1e3?`${(e/1e3).toFixed(e>=1e4?1:2).replace(/\.0$/,"")}K`:String(e)}function Dm(e=0){return`${(e*100).toFixed(e<.1?1:0)}%`}function xo(e){if(!e)return"Never";const t=new Date(e);return Number.isNaN(t.valueOf())?"Unknown":t.toLocaleString([],{dateStyle:"medium",timeStyle:"short"})}function tt(e,t,r="ready"){return`<div class="brand-row"><div class="mark ${r}" aria-hidden="true"><i></i><i></i><i></i><i></i><b></b></div><div><div class="eyebrow">PRODERO · ${p(t.toUpperCase())}</div><h1>${p(e)}</h1></div></div>`}function ct(e){return e.applicability?`Applies to: ${_n(e)}`:e.scopeRef?`${e.scope}: ${e.scopeRef}`:e.scope}function Ib(e){return`${e>=0?"+":""}${Number.isInteger(e)?e:e.toFixed(2)}`}function Wa(e=[]){return e.length?`<ul class="selection-signals">${e.map(t=>`<li><span>${p(t.label)}</span><em>${Ib(t.score)}</em></li>`).join("")}</ul>`:'<p class="context-muted">No query-ranking signals apply to required context.</p>'}function Xi(e){const t=[...new Set(e.sourceSessions??[])],r=[...new Set(e.derivedFrom??[])];return!t.length&&!r.length?"":`<details class="context-subdetail"><summary>Sources <span>${t.length} session${t.length===1?"":"s"} · ${r.length} observation${r.length===1?"":"s"}</span></summary><div class="source-list">${t.map(o=>`<code>${p(String(o))}</code>`).join("")}${r.map(o=>`<code>${p(String(o))}</code>`).join("")}</div></details>`}function jb(e,t,r){const o=`<label>Importance${r("priority",[["critical","Critical"],["important","Normal · important"],["normal","Normal"],["contextual","Normal · contextual"]],t.priority)}</label>`;return e.applicability&&e.applicability.kind!=="legacy"?`${o}<p>${p(ct(e))}</p>`:`${o}<label>Scope${r("scope",[["global","Global"],["module","Module / path"],["task","Task"]],t.scope)}</label><label>Scope reference<input name="scopeRef" maxlength="300" value="${p(t.scopeRef??"")}"></label><label>Scope kind${r("scopeKind",[["","Automatic"],["path","Repository path"],["topic","Topic"]],t.scopeKind??"")}</label>`}function Vc(e,t,r=!1){var o,n;return`<details class="context-item"><summary><span><b>${p(e.title)}</b><small>${p(e.category??"knowledge")} · ${p(ct(e))}</small></span><em>${st((t==null?void 0:t.estimatedTokens)??0)} est. tokens</em></summary><div class="context-item-body"><div class="context-content">${p(e.content??"").replace(/\n/g,"<br>")}</div>${t!=null&&t.applicability?`<p class="context-muted">${p(t.applicability.reasons.join("; "))}</p>`:""}${r?`<details class="context-subdetail"><summary>Why selected</summary>${Wa(t==null?void 0:t.signals)}<p class="context-muted">Retrieval score: ${((n=(o=t==null?void 0:t.rankScore)==null?void 0:o.toFixed)==null?void 0:n.call(o,2))??(t==null?void 0:t.score)??"—"}</p></details>`:""}${Xi(e)}</div></details>`}function zb(e){const t=(e.signals??[]).map(r=>({label:`${r.field==="description"?"Purpose":r.field}: ${r.matches.join(", ")}`,score:r.score}));return`<details class="context-item"><summary><span><b>${p(e.title)}</b><small>${p(e.category??"skill")} · ${p(e.scope??"project")}</small></span><em>${st(e.estimatedTokens)} est. tokens</em></summary><div class="context-item-body"><div class="context-content">${p(e.content??"").replace(/\n/g,"<br>")}</div><details class="context-subdetail"><summary>Why selected</summary>${Wa(t)}</details></div></details>`}function Fn(e){return e==="marginal-value"?"Limited additional information beyond the initial selection":e==="budget"?"Did not fit the context budget":"Item limit reached"}function Tb(e){const t=e.selection,r=(t==null?void 0:t.omittedRelevantByBudget)??0,o=(t==null?void 0:t.omittedRelevantByMarginalValue)??0,n=(t==null?void 0:t.omittedRelevantByItemLimit)??0,i=r+n+o;if(!i)return"";const s=[{reason:"marginal-value",count:o},{reason:"item-limit",count:n},{reason:"budget",count:r}].filter(l=>l.count>0).sort((l,d)=>d.count-l.count),a=s.filter(l=>l.count===s[0].count),c=t.omittedRelevant??[];return`<section class="context-saturation" aria-label="Additional matches"><h2>Additional matches · ${i}</h2><p>${i} knowledge item${i===1?" matched":"s matched"} retrieval signals but ${i===1?"was":"were"} not loaded.</p><p class="omission-primary"><span>Primary reason${a.length>1?"s":""}</span><b>${a.map(l=>Fn(l.reason)).join(" · ")}</b></p><details class="context-subdetail"><summary>Inspect matches${t.omittedRelevantDetailsTruncated?` <span>${c.length} of ${i} matches shown</span>`:""}</summary><p>${s.map(l=>`${Fn(l.reason)} · ${l.count}`).join("<br>")}</p><div class="omitted-list">${c.map(l=>`<details><summary><span>${p(l.title)}<small>${p(l.category)} · ${p(ct(l))}</small></span></summary><p class="context-muted">Retrieval score: ${l.rankScore.toFixed(2)}</p><h3>Why matched</h3>${Wa(l.signals)}<p class="omission-primary"><span>Not loaded</span><b>${Fn(l.reason)}${l.constraint?` · ${p(l.constraint)}`:""}</b></p></details>`).join("")}</div></details></section>`}function Lm(e){var n;const t=e.metrics??{},r=t.requiredCriticalOmitted??(((n=e.selection)==null?void 0:n.omittedRequired)??[]).filter(i=>i.priority==="critical").length,o=t.requiredGlobalExcludedItems??(t.requiredGlobalOmittedByItemLimit??0)+(t.requiredGlobalOmittedByBudget??0);return{critical:r,normal:t.requiredNormalOmitted??Math.max(0,o-r),total:o}}function dt(e,t,r){return`<button type="button" data-instruction-action="${e}"${r?` data-id="${p(r)}"`:""} ${C?"disabled":""}>${t}</button>`}function Ga(){D.querySelectorAll("button[data-instruction-action]").forEach(e=>e.addEventListener("click",()=>void Mm(e.dataset.instructionAction,e.dataset.id)))}function Rb(){var o,n,i,s,a;const e=ke,t=zt,r=c=>c.map(l=>`<article class="session-review-item"><header>${p(l.priority)} · ${p(ct(l))} · ${p(l.status)}</header><h3>${p(l.title)}</h3><p class="context-content">${p(l.content)}</p></article>`).join("");D.innerHTML=`<main class="shell lifecycle-shell"><section class="lifecycle-hero">${tt("Omitted instructions","context review")}<p class="lead compact">${((o=e.counts)==null?void 0:o.normal)??0} normal instructions omitted · ${((n=e.counts)==null?void 0:n.critical)??0} critical omitted</p></section><section class="panel"><div class="actions">${dt("back","Back to prepared context")}${dt("review","All omitted")}${(i=e.counts)!=null&&i.critical?dt("critical","Critical only"):""}${dt("optimize","Optimize")}${dt("refresh-prepare","Prepare again")}</div><p class="context-muted">Omission reasons and counts describe the original prepare. Content is loaded from current Knowledge. Changes affect subsequent preparation.</p>${T?`<p role="status" class="message">${p(T)}</p>`:""}
|
|
86
|
+
container holding the app. Specify either width or maxWidth, and either height or maxHeight.`),locale:b().optional().describe("User's language and region preference in BCP 47 format."),timeZone:b().optional().describe("User's timezone in IANA format."),userAgent:b().optional().describe("Host application identifier."),platform:ce([$("web"),$("desktop"),$("mobile")]).optional().describe("Platform type for responsive design decisions."),deviceCapabilities:k({touch:xe().optional().describe("Whether the device supports touch input."),hover:xe().optional().describe("Whether the device supports hover interactions.")}).optional().describe("Device input capabilities."),safeAreaInsets:k({top:ie().describe("Top safe area inset in pixels."),right:ie().describe("Right safe area inset in pixels."),bottom:ie().describe("Bottom safe area inset in pixels."),left:ie().describe("Left safe area inset in pixels.")}).optional().describe("Mobile safe area boundaries in pixels.")}).passthrough(),gb=k({method:$("ui/notifications/host-context-changed"),params:Um.describe("Partial context update containing only changed fields.")});k({method:$("ui/update-model-context"),params:k({content:G(_r).optional().describe("Context content blocks (text, image, etc.)."),structuredContent:de(b(),Ie().describe("Structured content for machine-readable context data.")).optional().describe("Structured content for machine-readable context data.")})});k({method:$("ui/initialize"),params:k({appInfo:Gi.describe("App identification (name and version)."),appCapabilities:pb.describe("Features and capabilities this app provides."),protocolVersion:b().describe("Protocol version this app supports.")})});var vb=k({protocolVersion:b().describe('Negotiated protocol version string (e.g., "2025-11-21").'),hostInfo:Gi.describe("Host application identification and version."),hostCapabilities:db.describe("Features and capabilities provided by the host."),hostContext:Um.describe("Rich context about the host environment.")}).passthrough(),yb={target:"draft-2020-12"};async function Bc(e,t){let r=e["~standard"];if(r.jsonSchema)return r.jsonSchema[t](yb);if(r.vendor==="zod"){let{z:o}=await af(()=>Promise.resolve().then(()=>sv),void 0,import.meta.url);return o.toJSONSchema(e,{io:t})}throw Error(`Schema (vendor: ${r.vendor}) does not implement Standard JSON Schema (~standard.jsonSchema). Use a library that does (zod v4, ArkType, Valibot) or wrap your schema accordingly.`)}async function Jc(e,t,r=""){let o=await e["~standard"].validate(t);if(o.issues){let n=o.issues.map(i=>{var a;let s=(a=i.path)==null?void 0:a.map(c=>typeof c=="object"?c.key:c).join(".");return s?`${s}: ${i.message}`:i.message}).join("; ");throw Error(r+n)}return o.value}const Br=class Br extends Wy{constructor(r,o={},n={autoResize:!0}){super(n);be(this,"_appInfo");be(this,"_capabilities");be(this,"options");be(this,"_hostCapabilities");be(this,"_hostInfo");be(this,"_hostContext");be(this,"_registeredTools",{});be(this,"_initializedSent",!1);be(this,"eventSchemas",{toolinput:ob,toolinputpartial:sb,toolresult:hb,toolcancelled:ab,hostcontextchanged:gb});be(this,"_everHadListener",new Set);be(this,"_toolHandlersInitialized",!1);be(this,"_onteardown");be(this,"_oncalltool");be(this,"_onlisttools");be(this,"sendOpenLink",this.openLink);this._appInfo=r,this._capabilities=o,this.options=n,n.allowUnsafeEval||Ke({jitless:!0}),this.setRequestHandler(Qi,i=>(console.log("Received ping:",i.params),{})),this.setEventHandler("hostcontextchanged",void 0)}_assertInitialized(r){var n;if(this._initializedSent)return;let o=`[ext-apps] App.${r}() called before connect() completed the ui/initialize handshake. Await app.connect() before calling this method, or move data loading to an ontoolresult handler.`;if((n=this.options)!=null&&n.strict)throw Error(o);console.warn(`${o}. This will throw in a future release.`)}_assertHandlerTiming(r){var n;if(!Br.ONE_SHOT_EVENTS.has(r)||this._everHadListener.has(r)||(this._everHadListener.add(r),!this._initializedSent))return;let o=`[ext-apps] "${String(r)}" handler registered after connect() completed the ui/initialize handshake. The host may have already sent this notification. Register handlers before calling app.connect().`;if((n=this.options)!=null&&n.strict)throw Error(o);console.warn(o)}setEventHandler(r,o){o&&this._assertHandlerTiming(r),super.setEventHandler(r,o)}addEventListener(r,o){this._assertHandlerTiming(r),super.addEventListener(r,o)}onEventDispatch(r,o){r==="hostcontextchanged"&&(this._hostContext={...this._hostContext,...o})}registerCapabilities(r){if(this.transport)throw Error("Cannot register capabilities after transport is established");this._capabilities=Vy(this._capabilities,r)}registerTool(r,o,n){if(this._registeredTools[r])throw Error(`Tool ${r} is already registered`);let i=this,s=()=>{var l;i._initializedSent&&((l=i._capabilities.tools)!=null&&l.listChanged)&&i.sendToolListChanged()},a=o.inputSchema!==void 0,c={title:o.title,description:o.description,inputSchema:o.inputSchema,outputSchema:o.outputSchema,annotations:o.annotations,_meta:o._meta,enabled:!0,enable(){this.enabled=!0,s()},disable(){this.enabled=!1,s()},update(l){Object.assign(this,l),s()},remove(){i._registeredTools[r]===c&&(delete i._registeredTools[r],s())},handler:async(l,d)=>{if(!c.enabled)throw Error(`Tool ${r} is disabled`);let u;if(a){let m=c.inputSchema,h=m?await Jc(m,l??{},`Invalid input for tool ${r}: `):l??{};u=await n(h,d)}else u=await n(d);return c.outputSchema&&!u.isError&&(u.structuredContent=await Jc(c.outputSchema,u.structuredContent,`Invalid output for tool ${r}: `)),u}};return this._registeredTools[r]=c,!this._capabilities.tools&&!this.transport&&this.registerCapabilities({tools:{listChanged:!0}}),this.ensureToolHandlersInitialized(),s(),c}ensureToolHandlersInitialized(){this._toolHandlersInitialized||(this._toolHandlersInitialized=!0,this.oncalltool=async(r,o)=>{let n=this._registeredTools[r.name];if(!n)throw Error(`Tool ${r.name} not found`);return n.handler(r.arguments,o)},this.onlisttools=async(r,o)=>({tools:await Promise.all(Object.entries(this._registeredTools).filter(([n,i])=>i.enabled).map(async([n,i])=>{let s={name:n,title:i.title,description:i.description,inputSchema:i.inputSchema?await Bc(i.inputSchema,"input"):{type:"object",properties:{}}};return i.outputSchema&&(s.outputSchema=await Bc(i.outputSchema,"output")),i.annotations&&(s.annotations=i.annotations),i._meta&&(s._meta=i._meta),s}))}))}async sendToolListChanged(r={}){this._assertInitialized("sendToolListChanged"),await this.notification({method:"notifications/tools/list_changed",params:r})}getHostCapabilities(){return this._hostCapabilities}getHostVersion(){return this._hostInfo}getHostContext(){return this._hostContext}get ontoolinput(){return this.getEventHandler("toolinput")}set ontoolinput(r){this.setEventHandler("toolinput",r)}get ontoolinputpartial(){return this.getEventHandler("toolinputpartial")}set ontoolinputpartial(r){this.setEventHandler("toolinputpartial",r)}get ontoolresult(){return this.getEventHandler("toolresult")}set ontoolresult(r){this.setEventHandler("toolresult",r)}get ontoolcancelled(){return this.getEventHandler("toolcancelled")}set ontoolcancelled(r){this.setEventHandler("toolcancelled",r)}get onhostcontextchanged(){return this.getEventHandler("hostcontextchanged")}set onhostcontextchanged(r){this.setEventHandler("hostcontextchanged",r)}get onteardown(){return this._onteardown}set onteardown(r){this.warnIfRequestHandlerReplaced("onteardown",this._onteardown,r),this._onteardown=r,this.replaceRequestHandler(ub,(o,n)=>{if(!this._onteardown)throw Error("No onteardown handler set");return this._onteardown(o.params,n)})}get oncalltool(){return this._oncalltool}set oncalltool(r){this.warnIfRequestHandlerReplaced("oncalltool",this._oncalltool,r),this._oncalltool=r,this.replaceRequestHandler(Om,(o,n)=>{if(!this._oncalltool)throw Error("No oncalltool handler set");return this._oncalltool(o.params,n)})}get onlisttools(){return this._onlisttools}set onlisttools(r){this.warnIfRequestHandlerReplaced("onlisttools",this._onlisttools,r),this._onlisttools=r,this.replaceRequestHandler(Pm,(o,n)=>{if(!this._onlisttools)throw Error("No onlisttools handler set");return this._onlisttools(o.params,n)})}assertCapabilityForMethod(r){var o;switch(r){case"sampling/createMessage":if(!((o=this._hostCapabilities)!=null&&o.sampling))throw Error(`Host does not support sampling (required for ${r})`);break}}assertRequestHandlerCapability(r){switch(r){case"tools/call":case"tools/list":if(!this._capabilities.tools)throw Error(`Client does not support tool capability (required for ${r})`);return;case"ping":case"ui/resource-teardown":return;default:throw Error(`No handler for method ${r} registered`)}}assertNotificationCapability(r){}assertTaskCapability(r){throw Error("Tasks are not supported in MCP Apps")}assertTaskHandlerCapability(r){throw Error("Task handlers are not supported in MCP Apps")}async callServerTool(r,o){if(this._assertInitialized("callServerTool"),typeof r=="string")throw Error(`callServerTool() expects an object as its first argument, but received a string ("${r}"). Did you mean: callServerTool({ name: "${r}", arguments: { ... } })?`);return await this.request({method:"tools/call",params:r},Yi,{onprogress:()=>{},resetTimeoutOnProgress:!0,...o})}async readServerResource(r,o){return this._assertInitialized("readServerResource"),await this.request({method:"resources/read",params:r},Tm,o)}async listServerResources(r,o){return this._assertInitialized("listServerResources"),await this.request({method:"resources/list",params:r},zm,o)}async createSamplingMessage(r,o){this._assertInitialized("createSamplingMessage");let n=r.tools?Am:Em;return await this.request({method:"sampling/createMessage",params:r},n,o)}sendMessage(r,o){return this._assertInitialized("sendMessage"),this.request({method:"ui/message",params:r},ib,o)}sendLog(r){return this.notification({method:"notifications/message",params:r})}updateModelContext(r,o){return this._assertInitialized("updateModelContext"),this.request({method:"ui/update-model-context",params:r},Ta,o)}openLink(r,o){return this._assertInitialized("openLink"),this.request({method:"ui/open-link",params:r},nb,o)}downloadFile(r,o){return this._assertInitialized("downloadFile"),this.request({method:"ui/download-file",params:r},rb,o)}requestTeardown(r={}){return this.notification({method:"ui/notifications/request-teardown",params:r})}requestDisplayMode(r,o){return this._assertInitialized("requestDisplayMode"),this.request({method:"ui/request-display-mode",params:r},mb,o)}sendSizeChanged(r){return this.notification({method:"ui/notifications/size-changed",params:r})}setupSizeChangedNotifications(){let r=!1,o=0,n=0,i=()=>{r||(r=!0,requestAnimationFrame(()=>{r=!1;let a=document.documentElement,c=a.style.height;a.style.height="max-content";let l=Math.ceil(a.getBoundingClientRect().height);a.style.height=c;let d=Math.ceil(window.innerWidth);(d!==o||l!==n)&&(o=d,n=l,this.sendSizeChanged({width:d,height:l}))}))};i();let s=new ResizeObserver(i);return s.observe(document.documentElement),s.observe(document.body),()=>s.disconnect()}async connect(r=new Yy(window.parent,window.parent),o){var n;if(this.transport)throw Error("App is already connected. Call close() before connecting again.");this._initializedSent=!1,await super.connect(r);try{let i=await this.request({method:"ui/initialize",params:{appCapabilities:this._capabilities,appInfo:this._appInfo,protocolVersion:Gy}},vb,o);if(i===void 0)throw Error(`Server sent invalid initialize result: ${i}`);this._hostCapabilities=i.hostCapabilities,this._hostInfo=i.hostInfo,this._hostContext=i.hostContext,await this.notification({method:"ui/notifications/initialized"}),this._initializedSent=!0,(n=this.options)!=null&&n.autoResize&&this.setupSizeChangedNotifications()}catch(i){throw this.close(),i}}};be(Br,"ONE_SHOT_EVENTS",new Set(["toolinput","toolinputpartial","toolresult","toolcancelled"]));let So=Br;const pe={instructionsRead:"prodero_instructions_read",uiCardState:"prodero_ui_card_state",configGet:"prodero_config_get",configSet:"prodero_config_set",text:"prodero_text",plugins:"prodero_plugins",pluginAction:"prodero_plugin_action",open:"prodero_open",status:"prodero_status",statusDetails:"prodero_status_details",initialize:"prodero_initialize",migrate:"prodero_migrate",curation:"prodero_curation",curationReview:"prodero_curation_review",curationQuestion:"prodero_curation_question",curationReasoningPrepare:"prodero_curation_reasoning_prepare",curationReasoningPropose:"prodero_curation_reasoning_propose",curationApply:"prodero_curation_apply",prepare:"prodero_prepare",context:"prodero_context",recall:"prodero_recall",memoryTransformPrepare:"prodero_memory_transform_prepare",memoryTransformPropose:"prodero_memory_transform_propose",instructionReview:"prodero_instruction_review",instructionOptimize:"prodero_instruction_optimize",knowledge:"prodero_knowledge",knowledgeMutate:"prodero_knowledge_mutate",memorySearch:"prodero_memory_search",remember:"prodero_remember",forget:"prodero_forget",promotionPreview:"prodero_promotion_preview",promote:"prodero_promote",sessionRecord:"prodero_session_record",sessionClose:"prodero_session_close",sessionReview:"prodero_session_review",sessionReviewMutate:"prodero_session_review_mutate",sync:"prodero_sync",memorySync:"prodero_memory_sync",skillCreate:"prodero_skill_create",skills:"prodero_skills",skillsRead:"prodero_skills_read",skillPreview:"prodero_skill_preview",skillReview:"prodero_skill_review",checkUpdate:"prodero_check_update",update:"prodero_update"};function bb(e){var t;return!e||((t=e.snapshot)==null?void 0:t.version)!==1||!e.snapshot.sessionId?null:e}const $b=6e3,Fr=[{id:"prodero",label:"Current / Prodero",swatch:"#c6ff76",base:"#0b0d0c"},{id:"dark-neon",label:"Dark Neon",swatch:"#b6efff",base:"#020304"},{id:"pink-neon",label:"Pink Neon",swatch:"#ff63c5",base:"#090307"},{id:"blue-neon",label:"Blue Neon",swatch:"#55c9ff",base:"#020710"},{id:"purple-neon",label:"Purple Neon",swatch:"#b98aff",base:"#07030e"},{id:"light",label:"Light",swatch:"#3e6516",base:"#f7f9fc"},{id:"system",label:"System",swatch:"#a0adbd",base:"#f7f9fc"}],qm=Oo(["auto","ui","text"]),Zm=Oo(["prodero","dark-neon","pink-neon","blue-neon","purple-neon","light","system"]);Ef({mode:qm.optional(),theme:Zm.optional()}).passthrough();Cf().int().min(1).max(1e6);Oo(["presentation.mode","presentation.theme","context.max_tokens"]);function io(e){return Fr.some(t=>t.id===e)?e:"prodero"}function _b(e){var u,m;let t="prodero",r,o,n=0,i,s,a="default";const c=()=>a==="local override"?"Saved on this checkout.":a==="legacy project default"?"Using the legacy project default.":"Using the built-in default.";let l="Open a project to choose its theme.";const d=()=>{var w;const h=r??(e.media?e.media.matches?"dark":"light":void 0);e.root.dataset.proderoTheme=t==="system"?h==="light"?"light":h==="dark"?"dark-neon":"prodero":t,(w=e.changed)==null||w.call(e,t,l,a)};return(m=(u=e.media)==null?void 0:u.addEventListener)==null||m.call(u,"change",d),d(),{get selected(){return t},get project(){return o},setProject(h,w,f,g){n++,o=h,i=f,s=g==null?void 0:g.reset,a=(g==null?void 0:g.source)??"default",t=io(w),l=c()+" System follows host appearance when available."+(g!=null&&g.notice?" "+g.notice:""),d()},async select(h){if(!o||!i)return;const w=io(h),f=o,g=++n;l="Saving checkout theme…",d();try{if(await i(f,w),g!==n||f!==o)return;t=w,a="local override",l=c(),d()}catch(y){g===n&&f===o&&(l=y instanceof Error?y.message:"Could not save checkout theme.",d())}},async reset(){if(!o||!s||a!=="local override")return;const h=o,w=++n;l="Resetting checkout theme…",d();try{const f=await s(h);if(w!==n||h!==o)return;t=io(f.theme),a=f.source,l=c(),d()}catch(f){w===n&&h===o&&(l=f instanceof Error?f.message:"Could not reset checkout theme.",d())}},setHostTheme(h){(h==="light"||h==="dark")&&(r=h,d())},dispose(){var h,w;n++,(w=(h=e.media)==null?void 0:h.removeEventListener)==null||w.call(h,"change",d)}}}function wb(){var o;const e=document.querySelector("#theme-settings");if(!e)return;e.innerHTML=`<details class="theme-picker"><summary>Appearance <span id="theme-current"></span></summary><fieldset><legend>Theme on this checkout</legend><div class="theme-options">${Fr.map(n=>`<label style="--swatch:${n.swatch};--swatch-base:${n.base}"><input disabled type="radio" name="prodero-theme" value="${n.id}"><span class="theme-swatch" aria-hidden="true"></span><span>${n.label}</span></label>`).join("")}</div><p id="theme-persistence"></p><button type="button" id="theme-reset" hidden>Use project/default setting</button></fieldset></details>`;let t;try{t=(o=window.matchMedia)==null?void 0:o.call(window,"(prefers-color-scheme: dark)")}catch{}const r=_b({root:document.documentElement,media:t,changed(n,i,s){e.querySelector("#theme-current").textContent=Fr.find(l=>l.id===n).label;const a=i.startsWith("Saving")||i.startsWith("Resetting");e.querySelectorAll("input").forEach(l=>{l.checked=l.value===n,l.disabled=i.startsWith("Open a project")||a});const c=e.querySelector("#theme-reset");c.hidden=s!=="local override",c.disabled=a,e.querySelector("#theme-persistence").textContent=i}});return e.addEventListener("change",n=>{const i=n.target;i instanceof HTMLInputElement&&i.name==="prodero-theme"&&r.select(i.value)}),e.querySelector("#theme-reset").addEventListener("click",()=>void r.reset()),r}const Ct=wb();function kb(e){let t,r,o=0,n=!0,i=!0,s=0,a=!1,c=!1;const l=()=>{r!==void 0&&e.cancel(r),r=void 0},d=m=>{n=m,e.display(m)};async function u(m){if(!(m!==o||!t||i)){try{const h=await e.inspect(t,!a);if(m!==o)return;const w=!a;if(a=!0,s=0,!h.available){i=!0;return}if(h.superseded){i=!0,d(!0);return}w&&d(!1)}catch{if(m!==o)return;if(++s>=3){i=!0;return}}m===o&&!i&&e.visible()&&(r=e.schedule(()=>{r=void 0,u(m)},4e3*Math.max(1,s)))}}return{adopt(m){c&&t===m||(c=!0,l(),o++,t=m,i=!t,s=0,a=!1,d(!!t),u(o))},toggle(){c=!0,l(),o++,i=!0,d(!n)},visibilityChanged(){l(),o++,u(o)},dispose(){l(),o++,i=!0}}}function Sb(e,t){const r=document.querySelector("#card-disclosure"),o=document.querySelector("#card-toggle"),n=document.querySelector("#card-content"),i=document.querySelector("#card-title"),s=document.querySelector("#card-toggle-label");if(!r||!o||!n||!i||!s)return;const a=kb({inspect:async(u,m)=>{var w,f;const h=await e({name:pe.uiCardState,arguments:{cardId:u,activate:m}});if(h.isError||typeof((w=h.structuredContent)==null?void 0:w.available)!="boolean"||typeof((f=h.structuredContent)==null?void 0:f.superseded)!="boolean")throw new Error("Card state unavailable");return h.structuredContent},display(u){u&&n.contains(document.activeElement)&&o.focus({preventScroll:!0}),n.hidden=u,o.setAttribute("aria-expanded",String(!u)),s.textContent=u?"Expand":"Collapse",t&&t({height:Math.ceil((u?r:document.body).getBoundingClientRect().height)}).catch(()=>{})},schedule:(u,m)=>window.setTimeout(u,m),cancel:u=>window.clearTimeout(u),visible:()=>document.visibilityState!=="hidden"});o.addEventListener("click",()=>a.toggle()),document.addEventListener("visibilitychange",()=>a.visibilityChanged());const c=typeof MutationObserver>"u"?void 0:new MutationObserver(()=>{var m;const u=(m=n.querySelector("h1"))==null?void 0:m.textContent;u&&(i.textContent=u)});c==null||c.observe(n,{childList:!0,subtree:!0});const l=()=>{a.dispose(),c==null||c.disconnect()};window.addEventListener("pagehide",l);let d;return{present(u,m){var f,g,y;const h=((f=u==null?void 0:u.presentation)==null?void 0:f.resolved)==="text";if(r.hidden=h,i.textContent=m.replace(/^Prodero\s*·\s*/i,""),h){a.dispose(),n.hidden=!1;return}const w=(y=(g=u==null?void 0:u.presentation)==null?void 0:g.card)==null?void 0:y.id;typeof w=="string"&&w!==d?(d=w,a.adopt(w)):d||a.adopt(void 0)},dispose:l}}const D=document.querySelector("#app");let O=null,ae=null,ke=null,zt=null,Xn=!1,Le=null,We=null,Mn=!1,C=null,T="",oo=null,wt=!1,kt=null,Se=null,Pe=null,$t=!1,Q=null,Ja=null,er=!1,St=null,F=null,$e=null,On,Qt={query:"",offset:0,limit:12},it=null,Tt=null,mn=!1,zr=!1;const re=new So({name:"Prodero Project Intelligence",version:"0.2.1"}),yn=Sb(e=>re.callServerTool(e),e=>re.sendSizeChanged(e));re.onteardown=async()=>(yn==null||yn.dispose(),{});function Ue(e){var r,o;if(e!=null&&e.structuredContent)return e.structuredContent;const t=(o=(r=e==null?void 0:e.content)==null?void 0:r.find(n=>n.type==="text"))==null?void 0:o.text;if(!t)return null;try{return JSON.parse(t)}catch{return{message:t}}}function Va(e){var r,o;const t=e==null?void 0:e.projectSettings;t!=null&&t.root&&(Ct==null||Ct.setProject(t.root,t.presentation.theme,async(n,i)=>{var a,c;const s=await re.callServerTool({name:pe.configSet,arguments:{projectRoot:n,key:"presentation.theme",value:i}});if(s.isError)throw new Error(((c=(a=s.content)==null?void 0:a.find(l=>l.type==="text"))==null?void 0:c.text)??"Could not save project theme.")},{source:(r=t.presentationSources)==null?void 0:r.theme,notice:(o=t.diagnostics)==null?void 0:o.map(n=>`${n.code}: ${n.cause} ${n.recovery}`).join(" "),reset:async n=>{var a,c,l,d;const i=await re.callServerTool({name:pe.configSet,arguments:{projectRoot:n,key:"presentation.theme",reset:!0}});if(i.isError)throw new Error(((c=(a=i.content)==null?void 0:a.find(u=>u.type==="text"))==null?void 0:c.text)??"Could not reset checkout theme.");const s=(l=Ue(i))==null?void 0:l.projectSettings;if(!(s!=null&&s.presentation))throw new Error("Theme reset result unavailable. Refresh settings before retrying.");return{theme:s.presentation.theme,source:((d=s.presentationSources)==null?void 0:d.theme)??"default"}}}))}function p(e){return e.replace(/[&<>'"]/g,t=>({"&":"&","<":"<",">":">","'":"'",'"':"""})[t])}function pt(e,t,r){return`<div class="metric"><strong>${e}</strong><span>${t}</span>${r?`<small>${r}</small>`:""}</div>`}function xb(e,t,r){return pt(e===void 0?"—":e,t,r)}function st(e=0){return e>=1e3?`${(e/1e3).toFixed(e>=1e4?1:2).replace(/\.0$/,"")}K`:String(e)}function Dm(e=0){return`${(e*100).toFixed(e<.1?1:0)}%`}function xo(e){if(!e)return"Never";const t=new Date(e);return Number.isNaN(t.valueOf())?"Unknown":t.toLocaleString([],{dateStyle:"medium",timeStyle:"short"})}function tt(e,t,r="ready"){return`<div class="brand-row"><div class="mark ${r}" aria-hidden="true"><i></i><i></i><i></i><i></i><b></b></div><div><div class="eyebrow">PRODERO · ${p(t.toUpperCase())}</div><h1>${p(e)}</h1></div></div>`}function ct(e){return e.applicability?`Applies to: ${_n(e)}`:e.scopeRef?`${e.scope}: ${e.scopeRef}`:e.scope}function Ib(e){return`${e>=0?"+":""}${Number.isInteger(e)?e:e.toFixed(2)}`}function Wa(e=[]){return e.length?`<ul class="selection-signals">${e.map(t=>`<li><span>${p(t.label)}</span><em>${Ib(t.score)}</em></li>`).join("")}</ul>`:'<p class="context-muted">No query-ranking signals apply to required context.</p>'}function Xi(e){const t=[...new Set(e.sourceSessions??[])],r=[...new Set(e.derivedFrom??[])];return!t.length&&!r.length?"":`<details class="context-subdetail"><summary>Sources <span>${t.length} session${t.length===1?"":"s"} · ${r.length} observation${r.length===1?"":"s"}</span></summary><div class="source-list">${t.map(o=>`<code>${p(String(o))}</code>`).join("")}${r.map(o=>`<code>${p(String(o))}</code>`).join("")}</div></details>`}function jb(e,t,r){const o=`<label>Importance${r("priority",[["critical","Critical"],["important","Normal · important"],["normal","Normal"],["contextual","Normal · contextual"]],t.priority)}</label>`;return e.applicability&&e.applicability.kind!=="legacy"?`${o}<p>${p(ct(e))}</p>`:`${o}<label>Scope${r("scope",[["global","Global"],["module","Module / path"],["task","Task"]],t.scope)}</label><label>Scope reference<input name="scopeRef" maxlength="300" value="${p(t.scopeRef??"")}"></label><label>Scope kind${r("scopeKind",[["","Automatic"],["path","Repository path"],["topic","Topic"]],t.scopeKind??"")}</label>`}function Vc(e,t,r=!1){var o,n;return`<details class="context-item"><summary><span><b>${p(e.title)}</b><small>${p(e.category??"knowledge")} · ${p(ct(e))}</small></span><em>${st((t==null?void 0:t.estimatedTokens)??0)} est. tokens</em></summary><div class="context-item-body"><div class="context-content">${p(e.content??"").replace(/\n/g,"<br>")}</div>${t!=null&&t.applicability?`<p class="context-muted">${p(t.applicability.reasons.join("; "))}</p>`:""}${r?`<details class="context-subdetail"><summary>Why selected</summary>${Wa(t==null?void 0:t.signals)}<p class="context-muted">Retrieval score: ${((n=(o=t==null?void 0:t.rankScore)==null?void 0:o.toFixed)==null?void 0:n.call(o,2))??(t==null?void 0:t.score)??"—"}</p></details>`:""}${Xi(e)}</div></details>`}function zb(e){const t=(e.signals??[]).map(r=>({label:`${r.field==="description"?"Purpose":r.field}: ${r.matches.join(", ")}`,score:r.score}));return`<details class="context-item"><summary><span><b>${p(e.title)}</b><small>${p(e.category??"skill")} · ${p(e.scope??"project")}</small></span><em>${st(e.estimatedTokens)} est. tokens</em></summary><div class="context-item-body"><div class="context-content">${p(e.content??"").replace(/\n/g,"<br>")}</div><details class="context-subdetail"><summary>Why selected</summary>${Wa(t)}</details></div></details>`}function Fn(e){return e==="marginal-value"?"Limited additional information beyond the initial selection":e==="budget"?"Did not fit the context budget":"Item limit reached"}function Tb(e){const t=e.selection,r=(t==null?void 0:t.omittedRelevantByBudget)??0,o=(t==null?void 0:t.omittedRelevantByMarginalValue)??0,n=(t==null?void 0:t.omittedRelevantByItemLimit)??0,i=r+n+o;if(!i)return"";const s=[{reason:"marginal-value",count:o},{reason:"item-limit",count:n},{reason:"budget",count:r}].filter(l=>l.count>0).sort((l,d)=>d.count-l.count),a=s.filter(l=>l.count===s[0].count),c=t.omittedRelevant??[];return`<section class="context-saturation" aria-label="Additional matches"><h2>Additional matches · ${i}</h2><p>${i} knowledge item${i===1?" matched":"s matched"} retrieval signals but ${i===1?"was":"were"} not loaded.</p><p class="omission-primary"><span>Primary reason${a.length>1?"s":""}</span><b>${a.map(l=>Fn(l.reason)).join(" · ")}</b></p><details class="context-subdetail"><summary>Inspect matches${t.omittedRelevantDetailsTruncated?` <span>${c.length} of ${i} matches shown</span>`:""}</summary><p>${s.map(l=>`${Fn(l.reason)} · ${l.count}`).join("<br>")}</p><div class="omitted-list">${c.map(l=>`<details><summary><span>${p(l.title)}<small>${p(l.category)} · ${p(ct(l))}</small></span></summary><p class="context-muted">Retrieval score: ${l.rankScore.toFixed(2)}</p><h3>Why matched</h3>${Wa(l.signals)}<p class="omission-primary"><span>Not loaded</span><b>${Fn(l.reason)}${l.constraint?` · ${p(l.constraint)}`:""}</b></p></details>`).join("")}</div></details></section>`}function Lm(e){var n;const t=e.metrics??{},r=t.requiredCriticalOmitted??(((n=e.selection)==null?void 0:n.omittedRequired)??[]).filter(i=>i.priority==="critical").length,o=t.requiredGlobalExcludedItems??(t.requiredGlobalOmittedByItemLimit??0)+(t.requiredGlobalOmittedByBudget??0);return{critical:r,normal:t.requiredNormalOmitted??Math.max(0,o-r),total:o}}function dt(e,t,r){return`<button type="button" data-instruction-action="${e}"${r?` data-id="${p(r)}"`:""} ${C?"disabled":""}>${t}</button>`}function Ga(){D.querySelectorAll("button[data-instruction-action]").forEach(e=>e.addEventListener("click",()=>void Mm(e.dataset.instructionAction,e.dataset.id)))}function Rb(){var o,n,i,s,a;const e=ke,t=zt,r=c=>c.map(l=>`<article class="session-review-item"><header>${p(l.priority)} · ${p(ct(l))} · ${p(l.status)}</header><h3>${p(l.title)}</h3><p class="context-content">${p(l.content)}</p></article>`).join("");D.innerHTML=`<main class="shell lifecycle-shell"><section class="lifecycle-hero">${tt("Omitted instructions","context review")}<p class="lead compact">${((o=e.counts)==null?void 0:o.normal)??0} normal instructions omitted · ${((n=e.counts)==null?void 0:n.critical)??0} critical omitted</p></section><section class="panel"><div class="actions">${dt("back","Back to prepared context")}${dt("review","All omitted")}${(i=e.counts)!=null&&i.critical?dt("critical","Critical only"):""}${dt("optimize","Optimize")}${dt("refresh-prepare","Prepare again")}</div><p class="context-muted">Omission reasons and counts describe the original prepare. Content is loaded from current Knowledge. Changes affect subsequent preparation.</p>${T?`<p role="status" class="message">${p(T)}</p>`:""}
|
|
87
87
|
${t?`<section><h2>Review optimization</h2><p>${p(t.notice??"Optimization applied. Prepare again to load the updated policies.")}</p>${(s=t.before)!=null&&s.length?`<p>${t.reducedBy} fewer instructions · ${t.beforeTokens} → ${t.afterTokens} est. tokens</p><div class="knowledge-comparison"><section><h3>Before</h3><details class="context-subdetail"><summary>Inspect ${t.before.length} original instructions</summary>${r(t.before)}</details></section><section><h3>After</h3>${r(t.after.filter(c=>c.status==="active"))}<p class="context-muted">${t.after.filter(c=>c.status!=="active").length} source records retained in history.</p></section></div><p>${t.repository?"This changes Git-tracked Versioned Knowledge.":"This changes Local Knowledge."} Source bodies and checkpoint history are preserved.</p>${dt("apply-optimization",t.repository?"Apply repository consolidation":"Apply consolidation")}`:""}<details><summary>Optimization details</summary><p>${t.inspected??0} instructions inspected · ${t.remaining??0} outside this bounded area · ${p(t.mode??"")}</p></details>${dt("cancel-optimization","Close optimization")}</section>`:`<div class="session-review-list">${(e.items??[]).map(c=>{const l=c.item,d=c.selection;return`<article class="session-review-item${d.priority==="critical"?" needs-review":""}"><header><span>${d.priority==="critical"?"Critical":"Normal"} at prepare · ${p(ct(d))}</span><span>${st(d.estimatedTokens)} est. tokens</span></header><h2>${p((l==null?void 0:l.title)??d.title)}</h2>${l?`<p class="context-content">${p(l.content)}</p><p class="context-muted">Current: ${p(l.priority)} · ${p(ct(l))} · ${p(l.status)} · ${l.layer==="local"?"Local":"Versioned"}</p>`:`<p class="context-muted">${c.missing?"The original record is no longer available.":"Open Knowledge to load the full record from this older snapshot."}</p>`}<p>Not selected: ${Fn(d.reason)}</p>${c.missing?"":dt("knowledge","Edit / classify / remove",d.id)}</article>`}).join("")}</div><div class="actions">${e.offset?dt("previous","Previous"):""}${e.nextOffset!==null&&e.nextOffset!==void 0?dt("next","Next"):""}</div><p class="context-muted">${e.total??((a=e.items)==null?void 0:a.length)??0} omitted instructions${e.legacy?" · limited metadata from an older prepare":""}</p>`}</section></main>`,Ga()}async function Mm(e,t){var i,s,a,c,l;if(C)return;if(e==="back"){ke=null,zt=null,T="",L();return}if(e==="cancel-optimization"){zt=null,T="",L();return}const r=(i=ae==null?void 0:ae.result)==null?void 0:i.context,o=(ke==null?void 0:ke.root)??(r==null?void 0:r.projectRoot),n=(ke==null?void 0:ke.reviewId)??((s=r==null?void 0:r.snapshot)==null?void 0:s.reviewId);C="instruction-review",T="",L();try{const d=async(u,m)=>{var f;const h=await re.callServerTool({name:u,arguments:{projectRoot:o,...m}}),w=Ue(h);if(h.isError||!(w!=null&&w.ok))throw Error((w==null?void 0:w.message)??((f=h.content)==null?void 0:f.map(g=>g.type==="text"?g.text:"").join(" "))??"Instruction operation failed.");return w};if(e==="knowledge"){const u=await d(pe.knowledge,{id:t});$e=u.result,On=o,Qt=u.result.options,Xn=!0}else if(e==="refresh-prepare")ae=await d(pe.prepare,{sessionId:(ke==null?void 0:ke.sessionId)??((a=r==null?void 0:r.snapshot)==null?void 0:a.sessionId),task:(ke==null?void 0:ke.task)??(r==null?void 0:r.query)??void 0}),ke=null,zt=null,wt=!1;else if(n)if(e==="optimize"||e==="apply-optimization"){ke||(ke=(await d(pe.instructionReview,{reviewId:n})).result);const u=await d(pe.instructionOptimize,{reviewId:n,action:e==="optimize"?"preview":"apply",...e==="apply-optimization"?{previewId:zt.previewId,approved:!0}:{}});zt=u.result,u.result.applied&&(T="Consolidation saved. Prepare again to load the updated policies.")}else{const u=e==="next"?ke.nextOffset:e==="previous"?Math.max(0,ke.offset-12):e==="reload-review"?ke.offset??0:0;ke=(await d(pe.instructionReview,{reviewId:n,offset:u,criticalOnly:e==="critical"||["next","previous","reload-review"].includes(e)&&ke.criticalOnly})).result,zt=null}else{if(e==="optimize")throw Error("Prepare again to create an exact review snapshot before optimizing.");const u=((c=r==null?void 0:r.selection)==null?void 0:c.omittedRequired)??[],m=Lm(r??{});ke={root:o,sessionId:(l=r==null?void 0:r.snapshot)==null?void 0:l.sessionId,task:r==null?void 0:r.query,counts:m,items:u.filter(h=>e!=="critical"||h.priority==="critical").map(h=>({selection:h,item:null})),legacy:!0}}}catch(d){T=d instanceof Error?d.message:String(d)}finally{C=null,L()}}function Fm(e){var o;const t=Lm(e),r=e.metrics??{};return t.total?`<section class="context-boundary-note${t.critical?" attention-message":""}"><b>${e.allocation?"Required context incomplete":t.critical?"Review recommended":"Context optimized"}</b><span>${t.normal} normal instructions omitted</span><span>${t.critical} critical omitted${t.critical?" · could not be loaded":""}</span><div class="actions">${dt(t.critical?"critical":"review",t.critical?"Review critical":"Review")}${dt("optimize","Optimize")}</div><details class="context-subdetail"><summary>Selection details</summary><p>${r.requiredGlobalOmittedByBudget??0} exceeded ${e.allocation?"total capacity or the Required safety ceiling":"the reserved token budget"}; ${r.requiredGlobalOmittedByItemLimit??0} exceeded the ${((o=e.limits)==null?void 0:o.maxRequiredItems)??16}-item safety cap. Instructions are ranked by criticality, relevance and scope.</p></details>${T?`<p role="status">${p(T)}</p>`:""}</section>`:""}function Nb(e){var r;const t=((r=e.selection)==null?void 0:r.omittedRequired)??[];return t.length?`<section class="context-saturation" aria-label="Omitted required instructions"><h2>Required instructions not loaded · ${t.length}</h2><details class="context-subdetail"><summary>Inspect required instructions</summary><div class="omitted-list">${t.map(o=>`<details><summary><span>${p(o.title)}<small>${p(o.category)} · ${p(ct(o))}</small></span><em>${st(o.estimatedTokens)} est. tokens</em></summary><p class="omission-primary"><span>Not loaded</span><b>${Fn(o.reason)}${o.constraint?` · ${p(o.constraint)}`:""}</b></p></details>`).join("")}</div></details></section>`:""}function bn(e,t,r,o){const n=o===void 0?"":`<p class="context-group-summary">${t.length} ${e==="Skills"?t.length===1?"skill":"skills":t.length===1?"item":"items"} · ${st(o)} est. tokens</p>`;return`<section class="context-group"><h2>${p(e)}${o===void 0?` <span>${t.length}</span>`:""}</h2>${n}${t.length?t.map(r).join(""):'<p class="context-muted">None supplied.</p>'}</section>`}function Pb(e){const t=e.allocation;return t?`<details class="context-subdetail"><summary>Allocation details</summary><p>Required: ${t.required.selectedItems} / ${t.required.demandItems} records · ${t.required.selectedTokens} / ${t.required.demandTokens} est. tokens · ${t.required.complete?"complete":"incomplete"}</p><p>Reserve: ${t.required.reserveTokens} · borrowed: ${t.required.borrowedTokens} · safety ceilings: ${t.required.hardTokens} tokens / ${t.required.hardItems} records</p><p>Relevant: ${t.relevant.selected} / ${t.relevant.candidates} · ${t.relevant.beyondTarget} beyond target ${t.relevant.softTarget} · stopped: ${p(t.relevant.stopReason)}</p><p>Skills: ${t.skills.selected} / ${t.skills.candidates} · ${t.skills.tokens} tokens · ${t.skills.protectedTokens} allocated before Relevant</p>${t.skills.omitted.map(r=>`<p>${p(r.id)}: ${p(r.reason)}</p>`).join("")}<p>Unused capacity: ${t.unusedTokens} est. tokens</p></details>`:""}function Hm(e){const t=bb(e);if(!t)return'<section class="context-inspector unavailable"><p>Exact prepared context is unavailable. The snapshot may come from an older runtime or missing disposable state. Retrieval was not rerun.</p></section>';const r=t.metrics,n=`<section class="context-provided" aria-label="Provided to agent"><h3>Provided to agent</h3><p class="provided-counts">${t.required.length+t.relevant.length} knowledge · ${t.skills.length} skill${t.skills.length===1?"":"s"}</p><p class="provided-tokens">${st(r.contextTokens)} / ${st(r.contextBudgetTokens)} est. tokens</p><dl>${[["Required",t.required.length],["Relevant",t.relevant.length],["Skills",t.skills.length]].map(([i,s])=>`<div><dt>${i}</dt><dd>${s}</dd></div>`).join("")}</dl></section>`;return`<section class="context-inspector" aria-label="Prepared context"><div class="context-inspector-head"><div><h2>Prepared context</h2><small>Session ${p(t.snapshot.sessionId)}</small></div><button data-action="close-context">Close</button></div>${n}${Pb(t)}${bn("Required",t.required,i=>Vc(i,t.selection.required[i.id]),r.requiredGlobalTokens)}${Nb(t)}${bn("Relevant",t.relevant,i=>Vc(i,t.selection.relevant[i.id],!0),r.selectedContextualTokens??0)}${bn("Skills",t.skills,zb,r.selectedSkillsTokens??0)}${Tb(t)}${t.applicability?`<details class="context-subdetail"><summary>Applicability details</summary>${Object.entries(t.applicability.decisions).map(([i,s])=>`<p><b>${p(i)}</b> · ${p(s.state.replaceAll("_"," "))}<br>${p(s.reasons.join("; "))}</p>`).join("")}${t.applicability.truncated?`<p>${t.applicability.truncated} further unresolved policies. Inspect Knowledge for details.</p>`:""}</details>`:""}</section>`}function Ob(e){const r=e.result.context,o=r.metrics,n=Jr(e),i=Number(n.metrics.find(s=>s.label==="Synced").value);D.innerHTML=`<main class="shell lifecycle-shell">
|
|
88
88
|
<section class="lifecycle-hero">
|
|
89
89
|
${tt("Context Ready","context ready")}
|
package/docs/COMPATIBILITY.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Compatibility and verification
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Curator **0.2.1 Public Preview** is a documentation-only patch for 0.2.0. Application behavior, runtime requirements, host support and project/knowledge schemas are unchanged; users already running 0.2.0 do not need an urgent upgrade. The runtime and host checks below describe 0.2.0. See the [changelog](../CHANGELOG.md) for release changes.
|
|
4
4
|
|
|
5
5
|
> Contract: Local/Versioned describe Git storage and sharing, not a security boundary against the connected agent. Review and approval are workflow safeguards, not authenticated human consent. The agent may create, promote and maintain Versioned files within current authorization. Curator tools do not execute Git commit or push; coding-agent Git actions follow current user scope and host approval controls. See [Privacy](PRIVACY.md).
|
|
6
6
|
|
|
@@ -9,22 +9,22 @@ Supported runtime target: **Node 22.14.0–22.x**, npm and Git. Node 22.14.0 is
|
|
|
9
9
|
| Environment | Status |
|
|
10
10
|
| --- | --- |
|
|
11
11
|
| macOS ARM64, Node 22.14.0 | Tested locally: full tests and isolated release gate |
|
|
12
|
-
| macOS / Ubuntu, Node 22.14.0 and 22.23.3 | Full four-job
|
|
13
|
-
| Native Windows | Not supported
|
|
12
|
+
| macOS / Ubuntu, Node 22.14.0 and 22.23.3 | Full four-job release matrix passed on the 0.2.0 release commit; see the verification results below |
|
|
13
|
+
| Native Windows | Not supported; filesystem/Git fixtures and process behavior are not verified |
|
|
14
14
|
| Node 20, 24 or other majors; WSL | Not verified / outside the initial runtime contract |
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
The built-in terminal updater additionally requires **npm 10.9.x** and an ordinary same-user global npm installation. Other installation layouts or toolchains need their package manager; see [updates](hosts.md#updates-and-advanced-project-commands).
|
|
17
17
|
|
|
18
18
|
## Hosts
|
|
19
19
|
|
|
20
20
|
| Host | Status / boundary |
|
|
21
21
|
| --- | --- |
|
|
22
22
|
| Codex CLI | Native 0.144.4 on macOS ARM64 passed installed 0.2.0 text lifecycle, persistent retrieval, Local maintenance and promotion preview. No Apps rendering claim from a CLI test. |
|
|
23
|
-
| Codex desktop |
|
|
23
|
+
| Codex desktop | Successful manual check reported by the maintainer on 2026-10-23; detailed build and per-case Apps results were not recorded. |
|
|
24
24
|
| Claude Code | Experimental adapter. Native 2.1.302 on macOS ARM64 passed installed 0.2.0 text lifecycle, persistent retrieval, Local maintenance and promotion preview. This does not certify Claude Desktop or Apps rendering. |
|
|
25
25
|
| Claude Desktop | No installer adapter; not verified. |
|
|
26
|
-
| Codex mobile / iPad |
|
|
27
|
-
| Cursor |
|
|
26
|
+
| Codex mobile / iPad | Successful manual check reported on 2026-10-23, with earlier iPad Context Ready / Session Complete acceptance. |
|
|
27
|
+
| Cursor | Detection-only; workspace and Apps workflows are not verified. |
|
|
28
28
|
| Other MCP hosts | Experimental; require standard stdio tools, optional roots and optional Apps/sampling. |
|
|
29
29
|
|
|
30
30
|
Use `prodero install` for one global machine integration. New workspaces initialize directly through MCP. Negotiated host roots authorize project selection; Claude's captured host project directory selects the primary root, and supported local Codex stdio launches supply the workspace through their launch directory. `projectRoot` is a checked selector, not authority. Missing supported context fails closed; no manual allowlist, per-project registration or CLI initialization is required. Explicit `--root` remains an optional hard boundary. Both integrations use the absolute public `prodero` executable: `mcp` for the installed package and `mcp --dev` for the saved Curator checkout. The public executable captures workspace context before loading development code. Update old global integration once and reconnect; `npm --prefix` is not a supported outer launcher. Managed PATH resolves the shebang to the verified Node installation. See [host integration](hosts.md) and [workspace trust contract](PRIVACY.md).
|
|
@@ -35,11 +35,11 @@ Historical machine-integration verification used isolated HOME and the native gl
|
|
|
35
35
|
|
|
36
36
|
Claude Code does not automatically read project `AGENTS.md`. Initialization remains unchanged; experimental Claude users need the host's documented project `CLAUDE.md` import of `@AGENTS.md` for the existing project lifecycle instructions. The installer does not create that project file or move lifecycle instructions into the global launcher. See [host integration](hosts.md). Restart hosts after package updates.
|
|
37
37
|
|
|
38
|
-
##
|
|
38
|
+
## Release verification
|
|
39
39
|
|
|
40
|
-
The [release gate](RELEASING.md) checks a clean installed artifact, stdio lifecycle, Local storage, reviewed synthetic sharing, restart and synthetic patch upgrade preservation. Synthetic upgrades do not certify future releases or arbitrary schema downgrades.
|
|
40
|
+
The [release gate](RELEASING.md) checks a clean installed artifact, stdio lifecycle, Local storage, reviewed synthetic sharing, restart and synthetic patch upgrade preservation. Synthetic upgrades do not certify future releases or arbitrary schema downgrades.
|
|
41
41
|
|
|
42
|
-
###
|
|
42
|
+
### Native text checks — 2026-10-23
|
|
43
43
|
|
|
44
44
|
The runtime candidate was commit `4f14a196b5325cf08c67ebeac40d21f5edb6e89f`. Its [fast CI](https://github.com/Prodero/curator/actions/runs/39653486240) passed 1,446 ordinary tests; its [full CI](https://github.com/Prodero/curator/actions/runs/39653523638) passed all four macOS/Ubuntu × Node 22.14.0/22.23.3 jobs, each with 1,453 tests and 16 installed-artifact smoke groups. These counts overlap and are not additive. The reviewed full-CI tarball SHA-256 was `c6bb29869c6fdcdff139799d01626a3f7ec57598005e5ab5d14437a76fbe9a12`.
|
|
45
45
|
|
|
@@ -47,15 +47,17 @@ On 2026-10-23 both native clients connected only to that installed 0.2.0 candida
|
|
|
47
47
|
|
|
48
48
|
Single-session maintenance visibly delivered Context Ready and Saved once in each client. In the batched two-session scenario each client omitted some intermediate receipts; persistence and closure still succeeded. This is an observed agent-relay limitation, not demonstrated knowledge loss. Curator supplies lifecycle text but does not guarantee model/client delivery. Apps rendering, host sampling and physical approval interaction were not independently verified by these CLI runs. Separate deterministic fixtures cover publication mechanics without claiming human UI approval.
|
|
49
49
|
|
|
50
|
-
###
|
|
50
|
+
### Manual host checks
|
|
51
51
|
|
|
52
|
-
On 2026-10-23 the
|
|
52
|
+
On 2026-10-23 the maintainer reported successful manual checks in **Codex Desktop, Claude CLI and Codex Mobile**. Client build versions, exact artifact identity and individual case traces were not recorded. These reports are separate from the versioned native CLI runs above and do not establish per-case Apps coverage for Apply replay, stale reviews or tool filtering. The earlier iPad lifecycle check also passed by user confirmation. Claude Code remains experimental.
|
|
53
53
|
|
|
54
|
-
###
|
|
54
|
+
### Published 0.2.0 identity
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
Published on **2026-10-25**, the 0.2.0 package and [v0.2.0 tag](https://github.com/Prodero/curator/releases/tag/v0.2.0) identify commit **`d180a58017b9e2e32731689411b420fa899aa884`**. Its [full release matrix](https://github.com/Prodero/curator/actions/runs/39999946126) passed all four macOS/Ubuntu × Node 22.14.0/22.23.3 jobs, each with **1,453 tests and 16 installed-artifact smoke groups**. [Post-main CI](https://github.com/Prodero/curator/actions/runs/40132635896) and the [tag matrix](https://github.com/Prodero/curator/actions/runs/40175313983) also passed on that same SHA. Counts overlap and are not additive.
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
All four release-matrix archives were identical. The public npm archive and GitHub Release asset match their **SHA-256 `54e95138e2807c27927b219b0049f0af1a9992005fda4815dd01f941067ca548`**. A clean public-registry installation reported CLI **0.2.0**, a current update check and byte-identical contents for all **148** package files.
|
|
59
|
+
|
|
60
|
+
Compared with the native-tested runtime candidate above, the published artifact changes four Markdown files; the other 144 payload files, including runtime, App, plugin and instruction assets, are identical. This preserves the scope of those native checks without treating the two archive hashes as interchangeable. The frozen tag and archive describe the published package even when documentation on `main` is updated later. CI does not expand the supported Node/OS or host Apps coverage listed here.
|
|
59
61
|
|
|
60
62
|
Codex setup and per-tool configuration reference: [official configuration reference](https://developers.openai.com/codex/config-reference).
|
|
61
63
|
|
package/docs/RELEASING.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Releasing Curator
|
|
2
2
|
|
|
3
3
|
From a clean checkout on Node 22.14+ (22.x):
|
|
4
4
|
|
|
@@ -73,10 +73,10 @@ A protocol runner is not a real host. Independently connect a primary host to th
|
|
|
73
73
|
|
|
74
74
|
## Install the artifact for review
|
|
75
75
|
|
|
76
|
-
For an unpublished candidate, install
|
|
76
|
+
For an unpublished release candidate, install its reviewed tarball in an isolated prefix. Keep this installation separate from your working MCP setup. Replace `X.Y.Z` and the example paths below with the intended release version and artifact locations:
|
|
77
77
|
|
|
78
78
|
```sh
|
|
79
|
-
npm install --global --prefix /absolute/isolated/prefix --omit=dev --ignore-scripts /absolute/path/prodero-curator-
|
|
79
|
+
npm install --global --prefix /absolute/isolated/prefix --omit=dev --ignore-scripts /absolute/path/prodero-curator-X.Y.Z.tgz
|
|
80
80
|
```
|
|
81
81
|
|
|
82
82
|
Use the isolated host environment described above for automated verification. For a deliberate real-host check, review the installer’s configuration changes and restart the selected coding agent. Open a synthetic project and type `prodero`. The tarball includes the compiled server, Apps and plugin resources; no source checkout or development dependencies are needed.
|
|
@@ -87,9 +87,9 @@ Use the isolated host environment described above for automated verification. Fo
|
|
|
87
87
|
2. Review the intended public Git tree **and history** for private content. Ignoring runtime files today does not remove old commits. Decide explicitly what history to publish; never rewrite it automatically.
|
|
88
88
|
3. Confirm ownership of npm scope `@prodero`, package/repository identity `@prodero/curator` / `prodero/curator`, and permission to release. A registry 404 does not establish scope ownership.
|
|
89
89
|
4. Create/configure the intended public repository only with explicit approval. Enable Issues and private vulnerability reporting; verify the links and update any identity/channel changes in docs and package metadata.
|
|
90
|
-
5. Confirm
|
|
91
|
-
6. Authenticate npm with the account's required 2FA/provenance policy. Publish the **reviewed tarball**, not an unreviewed rebuild: `npm publish /absolute/path/prodero-curator-
|
|
92
|
-
7. Verify external `npm install --global @prodero/curator@
|
|
90
|
+
5. Confirm the intended version, MIT license, final changelog date, preview limitations, README installation example and exact artifact contents. If any edit is still needed, return to step 1 and certify the new artifact. Obtain explicit approval for publication.
|
|
91
|
+
6. Authenticate npm with the account's required 2FA/provenance policy. Publish the **reviewed tarball**, not an unreviewed rebuild: `npm publish /absolute/path/prodero-curator-X.Y.Z.tgz --access public`.
|
|
92
|
+
7. Verify external `npm install --global @prodero/curator@X.Y.Z`, `prodero --version` and `prodero check-update`. Only with separate approval create/push the matching `vX.Y.Z` tag and release notes or announcements.
|
|
93
93
|
|
|
94
94
|
The automated gate does not publish or push and does not change the source repository history. It creates an isolated disposable test commit in its temporary checkout. Package upgrades do not move project knowledge. Back up the full `.prodero` directory before preview upgrades; `.cache` is disposable, migration recovery backups are not.
|
|
95
95
|
|
package/docs/hosts.md
CHANGED
|
@@ -121,17 +121,17 @@ prodero status --json
|
|
|
121
121
|
prodero status --root /absolute/path/to/project --json
|
|
122
122
|
prodero check-update
|
|
123
123
|
prodero update
|
|
124
|
-
prodero update 0.2.
|
|
124
|
+
prodero update 0.2.1 --yes
|
|
125
125
|
prodero install
|
|
126
126
|
```
|
|
127
127
|
|
|
128
128
|
`check-update` reports the installed and public latest npm version when reachable, availability and the terminal command `prodero update`. An unpublished, disabled or unreachable registry is unavailable, not current. In Codex/Claude the update indicator only opens these instructions. The compatibility MCP tool `prodero_update` is read-only for every release source; it does not install, rebuild, stage or refresh project integration.
|
|
129
129
|
|
|
130
|
-
`prodero update`
|
|
130
|
+
`prodero update` updates the installed package from a terminal. The built-in updater supports **Node 22.14–22.x with npm 10.9.x** and an ordinary same-user global npm installation. It verifies that installation, previews an exact stable newer version and unchanged prefix, asks you to finish active work and close Codex/Claude, then requires explicit confirmation. `prodero update VERSION` selects an exact stable target; ranges/tags/URLs/downgrades are rejected and an already-current target is a no-op. There is no automatic process discovery or host termination. Do not launch another consumer or package-manager operation during installation. Restart your hosts afterward.
|
|
131
131
|
|
|
132
|
-
For non-interactive use, provide both an exact target and explicit acknowledgment: `prodero update VERSION --yes`. The flag acknowledges that active work has ended and hosts are closed; the updater does not verify this. Without both, a non-TTY command refuses instead of waiting or silently agreeing.
|
|
132
|
+
For non-interactive use, provide both an exact target and explicit acknowledgment: `prodero update VERSION --yes`. Replace VERSION with the published version you want to install. The flag acknowledges that active work has ended and hosts are closed; the updater does not verify this. Without both, a non-TTY command refuses instead of waiting or silently agreeing.
|
|
133
133
|
|
|
134
|
-
The CLI waits for npm and checks the resulting installed version/public command. Failure exits nonzero with repair guidance; npm can leave a partial installation and there is no atomic rollback or hot activation. Source checkouts, linked/alternate package-manager layouts, mismatched installs and inadequate permissions are unsupported.
|
|
134
|
+
The CLI waits for npm and checks the resulting installed version/public command. Failure exits nonzero with repair guidance; npm can leave a partial installation and there is no atomic rollback or hot activation. Source checkouts, linked/alternate package-manager layouts, other npm versions, mismatched installs and inadequate permissions are unsupported by this updater; use the installation's package manager instead. Follow the reported package-manager/path guidance without using sudo or changing ownership to bypass a refusal. Ordinary npm dependency resolution remains in effect: the top-level artifact is verified, but the transitive dependency tree is not promised to be frozen or available offline. Prebuilt packages are installed with lifecycle scripts disabled.
|
|
135
135
|
|
|
136
136
|
Package update does not migrate projects, rewrite host settings/receipts/preferences or switch dev mode. A host saved in dev mode continues to load its existing checkout: updated package is distinct from active dev runtime. After restart, Open/Prepare separately present required project/knowledge migration for review; CLI `migrate` explicitly applies a permitted update. Back up the whole `.prodero` directory before preview migrations and do not downgrade to a runtime unable to read its schema.
|
|
137
137
|
|
|
Binary file
|