rewritable 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rewritable",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "CLI for re-writeable: emit and import single-file rwa documents.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -2326,13 +2326,22 @@ async function renderActionsModePanel(panel) {
2326
2326
  // recommended model (intelligence/0.2 I-A). A verified role can be activated; unverified cannot.
2327
2327
  const agentList = (typeof runtimeListAgents === 'function') ? runtimeListAgents() : [];
2328
2328
  const activeRole = (runtimeAgentActive() || {}).role || null;
2329
+ const advisorSet = (typeof runtimeListAdvisors === 'function') ? runtimeListAdvisors() : [];
2330
+ const advisorFull = advisorSet.length >= 3;
2329
2331
  const agentRows = agentList.length ? agentList.map(a => {
2330
2332
  const isActive = a.role === activeRole;
2331
- const meta = (a.verified ? 'verified' : 'unverified') + (isActive ? ' · active' : '');
2332
- const btn = !a.verified ? '' : (isActive
2333
- ? '<button type="button" data-agent-off="1">Deactivate</button>'
2334
- : '<button type="button" data-agent-on="' + escRuntimeHtml(a.role) + '">Activate</button>');
2335
- return '<div class="rwa-mode-row"><div><div class="rwa-mode-title">' + escRuntimeHtml(a.role) + '</div><div class="rwa-mode-meta">' + escRuntimeHtml('intelligence · ' + meta) + '</div></div>' + btn + '</div>';
2333
+ const isAdvisor = advisorSet.indexOf(a.role) >= 0;
2334
+ const state = isActive ? 'primary' : (isAdvisor ? 'advisor' : '');
2335
+ const meta = (a.verified ? 'verified' : 'unverified') + (state ? ' · ' + state : '');
2336
+ let btns = '';
2337
+ if (a.verified) {
2338
+ const r = escRuntimeHtml(a.role);
2339
+ if (isActive) btns = '<button type="button" data-agent-off="1">Deactivate</button>';
2340
+ else if (isAdvisor) btns = '<button type="button" data-agent-advoff="' + r + '">Remove advisor</button>';
2341
+ else btns = '<button type="button" data-agent-on="' + r + '">Activate</button>'
2342
+ + (advisorFull ? '<button type="button" disabled title="advisor limit reached">Add advisor</button>' : '<button type="button" data-agent-advon="' + r + '">Add advisor</button>');
2343
+ }
2344
+ return '<div class="rwa-mode-row"><div><div class="rwa-mode-title">' + escRuntimeHtml(a.role) + '</div><div class="rwa-mode-meta">' + escRuntimeHtml('intelligence · ' + meta) + '</div></div>' + btns + '</div>';
2336
2345
  }).join('') : '<div class="rwa-mode-empty">No intelligences installed.</div>';
2337
2346
  panel.innerHTML = [
2338
2347
  '<div class="rwa-mode-section">',
@@ -2372,6 +2381,12 @@ async function renderActionsModePanel(panel) {
2372
2381
  }));
2373
2382
  const agentOff = panel.querySelector('[data-agent-off]');
2374
2383
  if (agentOff) agentOff.addEventListener('click', () => { runtimeSetActiveAgent(null); renderActionsModePanel(panel); });
2384
+ panel.querySelectorAll('[data-agent-advon]').forEach(btn => btn.addEventListener('click', () => {
2385
+ try { runtimeAddAdvisor(btn.getAttribute('data-agent-advon')); } // I-E: layer an advisory lens
2386
+ catch (e) { if (typeof setStatus === 'function') setStatus('err', '✗ ' + (e && (e.code || e.message))); }
2387
+ renderActionsModePanel(panel);
2388
+ }));
2389
+ panel.querySelectorAll('[data-agent-advoff]').forEach(btn => btn.addEventListener('click', () => { runtimeRemoveAdvisor(btn.getAttribute('data-agent-advoff')); renderActionsModePanel(panel); }));
2375
2390
  }
2376
2391
 
2377
2392
  // ─── Agent (rwa-edit/1) ─────────────────────────────────────────────
@@ -5613,11 +5628,26 @@ function getActiveActor() {
5613
5628
  // system_prompt swaps the per-kind FRAMING; the shared SYSTEM_PROMPT_RULES (tool protocol, frozen-
5614
5629
  // zone rules, data-rwa-id) are always appended so editing still works. No agent → the singleton.
5615
5630
  function resolveSystemPrompt() {
5631
+ let base = SYSTEM_PROMPT;
5616
5632
  if (activeAgentRole) {
5617
5633
  const rec = Array.from(installedAgents.values()).find(a => a.role === activeAgentRole && a.verified);
5618
- if (rec && typeof rec.manifest.system_prompt === 'string') return rec.manifest.system_prompt + '\n' + SYSTEM_PROMPT_RULES;
5634
+ if (rec && typeof rec.manifest.system_prompt === 'string') base = rec.manifest.system_prompt + '\n' + SYSTEM_PROMPT_RULES;
5635
+ }
5636
+ return base + _agAdvisorBlock(); // I-E: append any advisory lenses (secondary; empty → byte-identical)
5637
+ }
5638
+ // I-E (intelligence/0.2 §6) — blended overlays. The PRIMARY is activeAgentRole (framing/actor/vault,
5639
+ // unchanged). advisorRoles add advisory PROSE only — never capabilities, so the vault gate
5640
+ // (_agVaultAllowed, keyed on the active record) stays primary-only by construction. Verified-only,
5641
+ // ephemeral (never serialized), capped. Block is omitted when empty (single-role prompt unchanged).
5642
+ function _agAdvisorBlock() {
5643
+ if (!advisorRoles.size) return '';
5644
+ const lines = [];
5645
+ for (const role of advisorRoles) {
5646
+ if (role === activeAgentRole) continue; // a role is primary XOR advisor, never both
5647
+ const rec = Array.from(installedAgents.values()).find(a => a.role === role && a.verified);
5648
+ if (rec && typeof rec.manifest.system_prompt === 'string') lines.push('- ' + role + ': ' + rec.manifest.system_prompt);
5619
5649
  }
5620
- return SYSTEM_PROMPT;
5650
+ return lines.length ? '\n\nAdditional advisory lenses (secondary — apply only where they don\'t conflict with the above):\n' + lines.join('\n') : '';
5621
5651
  }
5622
5652
  // I12 — the role-scoped vault gate: exact vault:<ns> membership in the agent's vault_namespace_set
5623
5653
  // (mirrors _skVaultAllowed against the agent record instead of the skill's permissions).
@@ -6832,6 +6862,10 @@ const installedSkills = new Map();
6832
6862
  // starts with no agent active per §12).
6833
6863
  const installedAgents = new Map();
6834
6864
  let activeAgentRole = null;
6865
+ // I-E — advisory roles layered atop the primary (in-memory, ephemeral, never serialized — like the
6866
+ // active role). Capped for prompt coherence/size. Advisors contribute prose only (see _agAdvisorBlock).
6867
+ const advisorRoles = new Set();
6868
+ const ADVISOR_CAP = 3;
6835
6869
  // I8 (v0.9 §9) — hook firing state. activeHooks holds skillIds currently executing (re-entrancy
6836
6870
  // guard, Inv 23); _lastHookMode tracks the prior mode for on-mode-change's `previous`; _hookSeq
6837
6871
  // makes rwa_hook_log keys unique within a millisecond.
@@ -7826,6 +7860,19 @@ function runtimeSetActiveAgent(role) {
7826
7860
  if (!rec.verified) throw new RwaEditError('unverified_agent', null, { role });
7827
7861
  activeAgentRole = role;
7828
7862
  }
7863
+ // I-E — add/remove an advisory role. Verified-only (its prompt drives modify), not-the-primary,
7864
+ // capped. Checks order so unverified/not-found beat the cap. Returns the current advisor list.
7865
+ function runtimeAddAdvisor(role) {
7866
+ const rec = Array.from(installedAgents.values()).find(a => a.role === role);
7867
+ if (!rec) throw new RwaEditError('agent_not_found', null, { role });
7868
+ if (!rec.verified) throw new RwaEditError('unverified_agent', null, { role });
7869
+ if (role === activeAgentRole || advisorRoles.has(role)) return Array.from(advisorRoles); // primary / already → no-op
7870
+ if (advisorRoles.size >= ADVISOR_CAP) throw new RwaEditError('advisor_cap_reached', null, { cap: ADVISOR_CAP });
7871
+ advisorRoles.add(role);
7872
+ return Array.from(advisorRoles);
7873
+ }
7874
+ function runtimeRemoveAdvisor(role) { advisorRoles.delete(role); return Array.from(advisorRoles); }
7875
+ function runtimeListAdvisors() { return Array.from(advisorRoles); }
7829
7876
  // §12 — validate + verify + register an agent, then persist the #rwa-agents zone (same discipline as
7830
7877
  // runtimeInstallSkill: rollback the in-memory map on a persist failure). A signed-but-unverified
7831
7878
  // agent registers (verified:false) but can't activate.
@@ -7851,6 +7898,7 @@ async function runtimeUninstallAgent(agentId) {
7851
7898
  if (!prev) return { ok: false, errors: ['not_installed'] };
7852
7899
  installedAgents.delete(agentId);
7853
7900
  if (activeAgentRole && prev.role === activeAgentRole && !Array.from(installedAgents.values()).some(a => a.role === activeAgentRole)) activeAgentRole = null;
7901
+ if (prev.role && !Array.from(installedAgents.values()).some(a => a.role === prev.role)) advisorRoles.delete(prev.role); // I-E: drop a removed role from advisors
7854
7902
  try {
7855
7903
  await runtimeRegionCommit({ regions: [_agAgentsRegion()], actor: 'agent:uninstall', reachability: 'frozen' });
7856
7904
  } catch (e) {
@@ -8161,6 +8209,8 @@ window.__rwaGetRecommendation = getRecommendation;
8161
8209
  window.__rwaApplyRecommendation = applyRecommendation;
8162
8210
  window.__rwaOfferRecommendedModel = offerRecommendedModel;
8163
8211
  window.__rwaActivateAgent = runtimeActivateAgent;
8212
+ window.__rwaResolveSystemPrompt = resolveSystemPrompt; // I-E test hook — the assembled modify() prompt
8213
+ window.__rwaGetActiveActor = getActiveActor;
8164
8214
 
8165
8215
  // §4/§5a — does a network: host pattern admit a host? Mirror of cli/src/skill-manifest.mjs
8166
8216
  // matchNetworkOrigin (keep in step). The bridge's per-call origin check.
@@ -9694,7 +9744,7 @@ document.addEventListener('keydown', e => {
9694
9744
  discoverSkills: runtimeDiscoverSkills, // v0.9 §11 (I6) — GET the marketplace index (opt-in network)
9695
9745
  fetchSkillFromIndex: runtimeFetchSkillFromIndex, // v0.9 §11 (I6) — fetch + client-side-verify an indexed skill
9696
9746
  vault: { get: runtimeVaultGet, set: runtimeVaultSet, has: runtimeVaultHas, namespaces: runtimeVaultNamespaces, unlock: runtimeVaultUnlock, lock: runtimeVaultLock, isLocked: runtimeVaultIsLocked, export: runtimeVaultExport, import: runtimeVaultImport }, // v0.8 §6 + v0.9 §14 (I13) portable export/import
9697
- agents: { list: runtimeListAgents, active: runtimeAgentActive, setActive: runtimeSetActiveAgent, activate: runtimeActivateAgent, install: runtimeInstallAgent, uninstall: runtimeUninstallAgent, message: runtimeAgentMessage, showInstallDialog: showAgentInstallDialog, offerModel: offerRecommendedModel }, // v0.9 §12 — multi-agent roles; `activate` = setActive + offer recommended model (intelligence/0.2 I-A)
9747
+ agents: { list: runtimeListAgents, active: runtimeAgentActive, setActive: runtimeSetActiveAgent, activate: runtimeActivateAgent, install: runtimeInstallAgent, uninstall: runtimeUninstallAgent, message: runtimeAgentMessage, showInstallDialog: showAgentInstallDialog, offerModel: offerRecommendedModel, addAdvisor: runtimeAddAdvisor, removeAdvisor: runtimeRemoveAdvisor, advisors: runtimeListAdvisors }, // v0.9 §12 — multi-agent roles; `activate` = setActive + offer recommended model (I-A); addAdvisor/removeAdvisor/advisors = blended overlays (I-E)
9698
9748
  hookLog: runtimeHookLog, // v0.9 §9 — the hook audit trail (rwa_hook_log)
9699
9749
  };
9700
9750
  // `status` is a getter so each read returns a fresh snapshot of