@pellux/goodvibes-agent 1.5.0 → 1.5.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 CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  Product-facing release notes for GoodVibes Agent.
4
4
 
5
+ ## 1.5.1 - 2026-06-14
6
+
7
+ - v1.5.1 is a patch on the 1.5 line. The fullscreen Agent workspace, Agent-local behavior, isolated Agent Knowledge, connected-host operator integration, and explicit side-effect boundaries all stay in force; this release restores the inline shell escape and refreshes release verification.
8
+ - Restored the inline shell escape in the prompt: type an exclamation mark followed by a command (for example, exclamation-mark git status) to run it in your working directory without leaving Agent. The command output appears inline, and the result is carried into your next message as context so you can run something and immediately ask about it. The composer already showed this as shell mode, but the command never actually ran since the workspace fork; it executes again now.
9
+ - The exclamation-hash memory pin is unchanged and still takes precedence, so pinning a note keeps working exactly as before.
10
+ - Release hygiene: regenerated the strict live-verification attestation against the running connected host so the published package carries current evidence.
11
+ - Test suite: 7931 pass / 0 fail / 2 skip across 554 files.
12
+
5
13
  ## 1.5.0 - 2026-06-11
6
14
 
7
15
  - v1.5.0 opens the 1.5 minor line: the fullscreen Agent workspace remains the primary user surface, Agent-local behavior, isolated Agent Knowledge, connected-host operator integration, explicit side-effect boundaries, and release hardening from 1.3.x and 1.4.x all stay in force. This release replaces the split-pane panel system with the Activity sidebar, rebuilds first-run onboarding around readiness, and adds local calendar, direct email, hardware-aware model recommendations, and skill import/export.
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # GoodVibes Agent
2
2
 
3
3
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
4
- [![Version: 1.5.0](https://img.shields.io/badge/version-1.5.0-blue.svg)](#install)
4
+ [![Version: 1.5.0](https://img.shields.io/badge/version-1.5.1-blue.svg)](#install)
5
5
 
6
6
  GoodVibes Agent is the installable autonomous operator assistant for GoodVibes. It keeps the existing terminal renderer and workspace bones, but the product goal is different from a vibecoding harness: the user should experience one assistant that can chat, plan, remember, research, schedule, send, generate, run visible agents, and operate the GoodVibes daemon contract with clear confirmation gates.
7
7
 
@@ -69,7 +69,52 @@ Press `/` inside the workspace to search actions by name, category, command, or
69
69
 
70
70
  The main Agent model can inspect and operate the Agent-controlled harness through Agent-owned tools. The important first-run entrypoint is `setup`; the detailed catalog entrypoint is `agent_harness`.
71
71
 
72
- `route action:"plan" query:"..."` is the first stop when a plain user task could map to several GoodVibes surfaces. It returns the preferred visible route, alternatives, missing fields, confirmation boundary, workspace matches, and harness mode matches without running tools; host/daemon health or doctor wording routes to `host action:"status"`, normal settings/configuration wording routes to `settings action:"list"`, model provider/local-cookbook/smoke/route-fit wording routes to `models action:"provider|local|smoke|route"`, Personal Ops briefing/queue/fresh-read/connector wording routes to `personal_ops action:"briefing|queue|intake|lane"`, direct reminders/schedule lifecycle wording routes to `schedule action:"list"` and confirmed schedule actions, command-shaped background work routes to `execution action:"processes"` and the first-class `terminal`/`process` UX, interactive PTY/stdin/sudo wording routes to `execution action:"process_capabilities"` before any start or credential effect, external memory-provider/backend/sync/import/export wording routes to `memory action:"provider"` or the provider contract checklist, browser-backed research runner wording routes to `research action:"runner"`, visual research report rendering routes to `research action:"plan"` plus report artifacts, voice workflow and TTS-provider wording routes to `device action:"voice|provider"`, browser cockpit/PWA wording routes to `computer action:"browser"` before any visible open handoff, channel setup/triage/delivery-receipt/send wording routes to `channels action:"setup|triage|deliveries|channel"` before confirmed external delivery, security permission/status/finding/blocked-action wording routes to `security action:"status|finding|explain"` before policy changes or risky work, support-bundle wording routes to `support action:"status|bundle"` before bundle export/import/share effects, saved-session/bookmark/continuity wording routes to `sessions action:"list|get"` before session lifecycle effects, release readiness/evidence/audit wording routes to `audit action:"readiness|evidence|item|artifact"`, file undo/redo/recovery wording routes to `execution action:"recovery"`, media generation wording routes to provider readiness plus confirmed `agent_media_generate` artifacts, and screenshot, browser-navigation/control, screen-observation, and desktop-control wording routes to `computer action:"plan"` before any live UI tool is considered. `setup action:"repair"` is the first stop for setup or host fix requests; it chooses the safest next token repair, connected-host status, services.status receipt, user-run bootstrap, or no-action route without executing it. `agent_harness mode:"summary"` is compact by default. It returns counts, status, and a short mode guide. `mode:"modes"` searches every harness mode by task, family, effect type, id, alias, or parameter name; `mode:"mode"` inspects one mode contract, and `mode:"route_decision"` remains the lower-level compatibility route for the same user-task planner. Plural catalog modes are also compact by default: they return ids, labels, counts, safe state, effect class, and short route hints. Workspace, command, UI, shortcut, and keybinding discovery should normally use `workspace action:"status|actions|action|run|surfaces|surface|open|commands|command|run_command|shortcuts|keybindings|keybinding"`, while lower-level harness modes remain for compatibility/detail inspection. Connected-host posture/status/capability and operator/audit rows include compact `modelRoute` or `modelAccess` hints so the model can choose the right first-class tool or confirmed harness route without expanding every row. Use `settings action:"list|get|set|reset|import"` for normal configuration work and `host action:"status|capabilities|capability|services|service|methods|method"` for normal connected-host/daemon diagnostics. Use `includeParameters:true` or a singular inspect mode when the model needs schemas, detailed route hints, full policy blocks, redacted log tail, operator/audit artifact data, or editor field definitions.
72
+ ### Route planning
73
+
74
+ `route action:"plan" query:"..."` is the first stop when a plain user task could map to several GoodVibes surfaces. It returns the preferred visible route, alternatives, missing fields, confirmation boundary, workspace matches, and harness mode matches without running any tools.
75
+
76
+ The planner maps task wording to a preferred route:
77
+
78
+ | When the task sounds like… | Preferred route |
79
+ | --- | --- |
80
+ | Host/daemon health or doctor | `host action:"status"` |
81
+ | Normal settings/configuration | `settings action:"list"` |
82
+ | Model provider, local cookbook, smoke, or route-fit | `models action:"provider\|local\|smoke\|route"` |
83
+ | Personal Ops briefing, queue, fresh-read, or connector | `personal_ops action:"briefing\|queue\|intake\|lane"` |
84
+ | Direct reminders or schedule lifecycle | `schedule action:"list"` + confirmed schedule actions |
85
+ | Command-shaped background work | `execution action:"processes"` + first-class `terminal`/`process` UX |
86
+ | Interactive PTY/stdin/sudo | `execution action:"process_capabilities"` before any start or credential effect |
87
+ | External memory provider, backend, sync, import, or export | `memory action:"provider"` or the provider contract checklist |
88
+ | Browser-backed research runner | `research action:"runner"` |
89
+ | Visual research report rendering | `research action:"plan"` + report artifacts |
90
+ | Voice workflow or TTS provider | `device action:"voice\|provider"` |
91
+ | Browser cockpit/PWA | `computer action:"browser"` before any visible open handoff |
92
+ | Channel setup, triage, delivery receipt, or send | `channels action:"setup\|triage\|deliveries\|channel"` before confirmed external delivery |
93
+ | Security permission, status, finding, or blocked action | `security action:"status\|finding\|explain"` before policy changes or risky work |
94
+ | Support bundle | `support action:"status\|bundle"` before bundle export/import/share effects |
95
+ | Saved session, bookmark, or continuity | `sessions action:"list\|get"` before session lifecycle effects |
96
+ | Release readiness, evidence, or audit | `audit action:"readiness\|evidence\|item\|artifact"` |
97
+ | File undo/redo/recovery | `execution action:"recovery"` |
98
+ | Media generation | provider readiness + confirmed `agent_media_generate` artifacts |
99
+ | Screenshot, browser navigation/control, screen observation, or desktop control | `computer action:"plan"` before any live UI tool is considered |
100
+
101
+ `setup action:"repair"` is the first stop for setup or host fix requests. It chooses the safest next route — token repair, connected-host status, services.status receipt, user-run bootstrap, or no action — without executing it.
102
+
103
+ ### Inspecting the harness
104
+
105
+ - `agent_harness mode:"summary"` — compact by default; returns counts, status, and a short mode guide.
106
+ - `mode:"modes"` — searches every harness mode by task, family, effect type, id, alias, or parameter name.
107
+ - `mode:"mode"` — inspects one mode contract.
108
+ - `mode:"route_decision"` — lower-level compatibility route for the same user-task planner.
109
+ - Plural catalog modes are compact by default: they return ids, labels, counts, safe state, effect class, and short route hints.
110
+
111
+ For everyday discovery and diagnostics, prefer the first-class tools over raw harness modes:
112
+
113
+ - Workspace, command, UI, shortcut, and keybinding discovery: `workspace action:"status|actions|action|run|surfaces|surface|open|commands|command|run_command|shortcuts|keybindings|keybinding"`.
114
+ - Normal configuration: `settings action:"list|get|set|reset|import"`.
115
+ - Connected-host/daemon diagnostics: `host action:"status|capabilities|capability|services|service|methods|method"`.
116
+
117
+ Connected-host posture/status/capability and operator/audit rows include compact `modelRoute` or `modelAccess` hints, so the model can pick the right first-class tool or confirmed harness route without expanding every row. Pass `includeParameters:true` or use a singular inspect mode when you need schemas, detailed route hints, full policy blocks, a redacted log tail, operator/audit artifact data, or editor field definitions.
73
118
 
74
119
  High-value `agent_harness` mode groups:
75
120
 
@@ -817034,7 +817034,7 @@ var createStyledCell = (char, overrides = {}) => ({
817034
817034
  // src/version.ts
817035
817035
  import { readFileSync } from "fs";
817036
817036
  import { join } from "path";
817037
- var _version = "1.5.0";
817037
+ var _version = "1.5.1";
817038
817038
  try {
817039
817039
  const pkg = JSON.parse(readFileSync(join(import.meta.dir, "..", "package.json"), "utf-8"));
817040
817040
  _version = typeof pkg.version === "string" ? pkg.version : _version;
@@ -869763,13 +869763,13 @@ init_state3();
869763
869763
 
869764
869764
  // src/input/commands/recall-shared.ts
869765
869765
  var VALID_CLASSES = ["decision", "constraint", "incident", "pattern", "fact", "risk", "runbook", "architecture", "ownership"];
869766
- var VALID_SCOPES2 = ["session", "project", "team"];
869766
+ var VALID_SCOPES = ["session", "project", "team"];
869767
869767
  var VALID_REVIEW_STATES = ["fresh", "reviewed", "stale", "contradicted"];
869768
869768
  function isValidClass(s4) {
869769
869769
  return VALID_CLASSES.includes(s4);
869770
869770
  }
869771
869771
  function isValidScope(s4) {
869772
- return VALID_SCOPES2.includes(s4);
869772
+ return VALID_SCOPES.includes(s4);
869773
869773
  }
869774
869774
  function isValidReviewState(s4) {
869775
869775
  return VALID_REVIEW_STATES.includes(s4);
@@ -869812,7 +869812,7 @@ function handleRecallSearch(args2, context) {
869812
869812
  if (isValidScope(scope))
869813
869813
  filter.scope = scope;
869814
869814
  else {
869815
- context.print(`[memory] Unknown scope "${scope}". Valid values ${VALID_SCOPES2.join(", ")}.`);
869815
+ context.print(`[memory] Unknown scope "${scope}". Valid values ${VALID_SCOPES.join(", ")}.`);
869816
869816
  return;
869817
869817
  }
869818
869818
  }
@@ -869987,7 +869987,7 @@ function handleRecallList(args2, context) {
869987
869987
  if (scopeIdx !== -1 && args2[scopeIdx + 1]) {
869988
869988
  const scope = args2[scopeIdx + 1];
869989
869989
  if (!isValidScope(scope)) {
869990
- context.print(`[memory] Unknown scope "${scope}". Valid values ${VALID_SCOPES2.join(", ")}.`);
869990
+ context.print(`[memory] Unknown scope "${scope}". Valid values ${VALID_SCOPES.join(", ")}.`);
869991
869991
  return;
869992
869992
  }
869993
869993
  filter.scope = scope;
@@ -870037,7 +870037,7 @@ async function handleRecallAdd(args2, context) {
870037
870037
  const tags = tagsRaw ? tagsRaw.split(",").map((token) => token.trim()).filter(Boolean) : [];
870038
870038
  const scope = scopeRaw && isValidScope(scopeRaw) ? scopeRaw : "project";
870039
870039
  if (scopeRaw && !isValidScope(scopeRaw)) {
870040
- context.print(`[memory] Invalid scope "${scopeRaw}". Valid values ${VALID_SCOPES2.join(", ")}.`);
870040
+ context.print(`[memory] Invalid scope "${scopeRaw}". Valid values ${VALID_SCOPES.join(", ")}.`);
870041
870041
  return;
870042
870042
  }
870043
870043
  const provenance = [];
@@ -870171,7 +870171,7 @@ function handleRecallExport(args2, context) {
870171
870171
  if (scopeIdx !== -1 && commandArgs[scopeIdx + 1]) {
870172
870172
  const scope = commandArgs[scopeIdx + 1];
870173
870173
  if (!isValidScope(scope)) {
870174
- context.print(`[memory] Unknown scope "${scope}". Valid values ${VALID_SCOPES2.join(", ")}.`);
870174
+ context.print(`[memory] Unknown scope "${scope}". Valid values ${VALID_SCOPES.join(", ")}.`);
870175
870175
  return;
870176
870176
  }
870177
870177
  filter.scope = scope;
@@ -870250,7 +870250,7 @@ function handleRecallHandoffExport(args2, context) {
870250
870250
  const scopeIdx = commandArgs.indexOf("--scope");
870251
870251
  const scopeRaw = scopeIdx !== -1 ? commandArgs[scopeIdx + 1] : "team";
870252
870252
  if (!scopeRaw || !isValidScope(scopeRaw)) {
870253
- context.print(`[memory] Unknown scope "${scopeRaw ?? ""}". Valid values ${VALID_SCOPES2.join(", ")}.`);
870253
+ context.print(`[memory] Unknown scope "${scopeRaw ?? ""}". Valid values ${VALID_SCOPES.join(", ")}.`);
870254
870254
  return;
870255
870255
  }
870256
870256
  const bundle = memory.exportBundle({ scope: scopeRaw });
@@ -870366,7 +870366,7 @@ function handleRecallPromote(args2, context) {
870366
870366
  const id = parsed.rest[0];
870367
870367
  const scope = parsed.rest[1];
870368
870368
  if (!id || !scope || !isValidScope(scope)) {
870369
- context.print(`[memory] Usage: /memory promote <id> <${VALID_SCOPES2.join("|")}> --yes`);
870369
+ context.print(`[memory] Usage: /memory promote <id> <${VALID_SCOPES.join("|")}> --yes`);
870370
870370
  return;
870371
870371
  }
870372
870372
  if (!parsed.yes) {
@@ -883582,7 +883582,7 @@ import { mkdirSync as mkdirSync75, readFileSync as readFileSync98, writeFileSync
883582
883582
  import { dirname as dirname74, resolve as resolve42 } from "path";
883583
883583
  init_state3();
883584
883584
  var VALID_CLASSES2 = ["decision", "constraint", "incident", "pattern", "fact", "risk", "runbook", "architecture", "ownership"];
883585
- var VALID_SCOPES4 = ["session", "project", "team"];
883585
+ var VALID_SCOPES3 = ["session", "project", "team"];
883586
883586
  var VALID_REVIEW_STATES3 = ["fresh", "reviewed", "stale", "contradicted"];
883587
883587
  var VALID_PROVENANCE_KINDS = ["session", "turn", "task", "event", "file"];
883588
883588
  var VALUE_OPTIONS = new Set([
@@ -883682,7 +883682,7 @@ function isMemoryClass2(value) {
883682
883682
  return VALID_CLASSES2.includes(value);
883683
883683
  }
883684
883684
  function isMemoryScope2(value) {
883685
- return VALID_SCOPES4.includes(value);
883685
+ return VALID_SCOPES3.includes(value);
883686
883686
  }
883687
883687
  function isReviewState(value) {
883688
883688
  return VALID_REVIEW_STATES3.includes(value);
@@ -883697,7 +883697,7 @@ function requireClass(value) {
883697
883697
  }
883698
883698
  function requireScope(value) {
883699
883699
  if (!value || !isMemoryScope2(value))
883700
- throw new Error(`Invalid memory scope "${value ?? ""}". Valid values ${VALID_SCOPES4.join(", ")}`);
883700
+ throw new Error(`Invalid memory scope "${value ?? ""}". Valid values ${VALID_SCOPES3.join(", ")}`);
883701
883701
  return value;
883702
883702
  }
883703
883703
  function optionalScope(value) {
@@ -944101,6 +944101,48 @@ function renderSettingsModal(modal, width, viewportHeight = 24) {
944101
944101
  });
944102
944102
  }
944103
944103
 
944104
+ // src/input/shell-passthrough.ts
944105
+ var MAX_SHELL_OUTPUT = 16000;
944106
+ var SHELL_USAGE_HINT = "[Shell] Usage: !<command> \u2014 runs a shell command; its output is shown and added as context for your next message.";
944107
+
944108
+ class ShellPassthrough {
944109
+ pending = [];
944110
+ async run(command8, cwd) {
944111
+ const proc = Bun.spawn(["bash", "-c", command8], { cwd, stdout: "pipe", stderr: "pipe" });
944112
+ const [out2, err2] = await Promise.all([
944113
+ new Response(proc.stdout).text(),
944114
+ new Response(proc.stderr).text()
944115
+ ]);
944116
+ const exitCode2 = await proc.exited;
944117
+ const combined = [out2, err2].filter((s4) => s4.trim().length > 0).join(`
944118
+ `).trimEnd();
944119
+ const truncated = combined.length > MAX_SHELL_OUTPUT ? `${combined.slice(0, MAX_SHELL_OUTPUT)}
944120
+ \u2026 [truncated ${combined.length - MAX_SHELL_OUTPUT} chars]` : combined;
944121
+ const body2 = truncated.length > 0 ? truncated : "(no output)";
944122
+ const result2 = {
944123
+ display: `[Shell] ${body2}
944124
+ (exit ${exitCode2})`,
944125
+ context: `The user ran a shell command via the \`!\` prefix:
944126
+ $ ${command8}
944127
+ --- output (exit ${exitCode2}) ---
944128
+ ${body2}`
944129
+ };
944130
+ this.pending.push(result2.context);
944131
+ return result2;
944132
+ }
944133
+ consumeContext(text) {
944134
+ if (this.pending.length === 0)
944135
+ return text;
944136
+ const context = this.pending.join(`
944137
+
944138
+ `);
944139
+ this.pending = [];
944140
+ return text ? `${context}
944141
+
944142
+ ${text}` : context;
944143
+ }
944144
+ }
944145
+
944104
944146
  // src/renderer/layout-engine.ts
944105
944147
  function clamp7(value, min2, max2) {
944106
944148
  return Math.max(min2, Math.min(max2, value));
@@ -948713,6 +948755,7 @@ async function main() {
948713
948755
  let streamTokenSpeed = 0;
948714
948756
  let scrollTop = 0;
948715
948757
  let scrollLocked = true;
948758
+ const shellPassthrough = new ShellPassthrough;
948716
948759
  const autonomy = createAutonomySurfacing({
948717
948760
  shellPaths: ctx.services.shellPaths,
948718
948761
  listAutomationJobs: () => ctx.services.automationManager.listJobs(),
@@ -948866,14 +948909,26 @@ async function main() {
948866
948909
  systemMessageRouter.high(`[Memory] Pinned: "${memoryText}" (${memId})`);
948867
948910
  processedText = memoryText;
948868
948911
  }
948912
+ } else if (processedText.startsWith("!")) {
948913
+ const command8 = processedText.slice(1).trim();
948914
+ if (!command8) {
948915
+ systemMessageRouter.high(SHELL_USAGE_HINT);
948916
+ render();
948917
+ return;
948918
+ }
948919
+ systemMessageRouter.high(`[Shell] $ ${command8}`);
948920
+ render();
948921
+ shellPassthrough.run(command8, workingDir).then((result2) => systemMessageRouter.high(result2.display)).catch((shellErr) => systemMessageRouter.high(`[Shell] Failed to run: ${summarizeError(shellErr)}`)).finally(() => render());
948922
+ return;
948869
948923
  }
948870
948924
  if (processedText || content) {
948871
948925
  (async () => {
948872
948926
  const inputOptions = options.spokenOutput ? createSpokenTurnInputOptions() : undefined;
948927
+ const outgoing = shellPassthrough.consumeContext(processedText);
948873
948928
  if (options.spokenOutput && processedText) {
948874
948929
  spokenTurns.submitNextTurn(processedText);
948875
948930
  }
948876
- orchestrator.handleUserInput(processedText, content, inputOptions).catch((err2) => {
948931
+ orchestrator.handleUserInput(outgoing, content, inputOptions).catch((err2) => {
948877
948932
  logger.debug("handleUserInput safety catch (already handled by runTurn)", { error: summarizeError(err2) });
948878
948933
  });
948879
948934
  })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pellux/goodvibes-agent",
3
- "version": "1.5.0",
3
+ "version": "1.5.1",
4
4
  "private": false,
5
5
  "description": "GoodVibes personal operator assistant TUI with a proactive Agent product brain, isolated Agent Knowledge, local profiles, routines, skills, personas, and explicit build delegation.",
6
6
  "type": "module",
@@ -1,5 +1,5 @@
1
1
  {
2
- "generatedAt": "2026-06-04T11:02:12.690Z",
2
+ "generatedAt": "2026-06-14T21:34:04.442Z",
3
3
  "homeDir": "[goodvibes-home]",
4
4
  "binaryPath": "[agent-binary]",
5
5
  "connectedHostBaseUrl": "http://127.0.0.1:3421",
@@ -9,8 +9,8 @@
9
9
  "id": "verification-ledger",
10
10
  "title": "Verification inventory ledger",
11
11
  "status": "pass",
12
- "summary": "100% local verification signal across 761 inventory items.",
13
- "detail": "87.4% local behavior verified; 96 item(s) require external outcomes."
12
+ "summary": "99.5% local verification signal across 806 inventory items.",
13
+ "detail": "83.9% local behavior verified; 96 item(s) require external outcomes."
14
14
  },
15
15
  {
16
16
  "id": "compiled-cli-present",
@@ -23,7 +23,7 @@
23
23
  "title": "Agent CLI version command",
24
24
  "status": "pass",
25
25
  "summary": "Agent CLI version returned successfully.",
26
- "detail": "goodvibes-agent 1.0.35"
26
+ "detail": "goodvibes-agent 1.5.0"
27
27
  },
28
28
  {
29
29
  "id": "cli-status-json",
@@ -37,14 +37,14 @@
37
37
  "title": "Agent CLI compatibility JSON command",
38
38
  "status": "pass",
39
39
  "summary": "Agent CLI compatibility returned parseable JSON.",
40
- "detail": "{\n \"ok\": true,\n \"packageVersion\": \"1.0.35\",\n \"connectedHost\": {\n \"baseUrl\": \"http://127.0.0.1:3421\",\n \"status\": 200,\n \"reachable\": true,\n \"compatible\": true\n },\n \"auth\": {\n \"tokenPresent\": true,\n \"tokenPath\": \"env:GOODVIBES_CONNECTED_HOST_TOKEN\"\n },\n \"agentKnowledge\": {\n \"route\": \"/api/goodvibes-agent/knowledge/status\",\n \"ready\": true,\n \"kind\": \"ok\"\n }\n}"
40
+ "detail": "{\n \"ok\": true,\n \"packageVersion\": \"1.5.0\",\n \"connectedHost\": {\n \"baseUrl\": \"http://127.0.0.1:3421\",\n \"status\": 200,\n \"reachable\": true,\n \"compatible\": true\n },\n \"auth\": {\n \"tokenPresent\": true,\n \"tokenPath\": \"env:GOODVIBES_CONNECTED_HOST_TOKEN\"\n },\n \"agentKnowledge\": {\n \"route\": \"/api/goodvibes-agent/knowledge/status\",\n \"ready\": true,\n \"kind\": \"ok\"\n }\n}"
41
41
  },
42
42
  {
43
43
  "id": "cli-agent-knowledge-status",
44
44
  "title": "Agent Knowledge CLI status command",
45
45
  "status": "pass",
46
46
  "summary": "Agent Knowledge status returned parseable JSON.",
47
- "detail": "{\n \"ok\": true,\n \"kind\": \"agentKnowledge.status\",\n \"route\": \"/api/goodvibes-agent/knowledge/status\",\n \"data\": {\n \"ready\": true,\n \"storagePath\": \"[goodvibes-home]/tui/knowledge-agent.sqlite\",\n \"sourceCount\": 0,\n \"nodeCount\": 12,\n \"edgeCount\": 0,\n \"issueCount\": 0,\n \"extractionCount\": 0,\n \"jobRunCount\": 35,\n \"refinementTaskCount\": 0,\n \"usageCount\": 0,\n \"candidateCount\": 0,\n \"reportCount\": 2,\n \"scheduleCount\": 3,\n \"note\": \"Structured knowledge uses SQL-backed sources, nodes, edges, issues, extractions, and job runs. Markdown is an optional projection, not the source of truth.\"\n }\n}"
47
+ "detail": "{\n \"ok\": true,\n \"kind\": \"agentKnowledge.status\",\n \"route\": \"/api/goodvibes-agent/knowledge/status\",\n \"data\": {\n \"ready\": true,\n \"storagePath\": \"[goodvibes-home]/tui/knowledge-agent.sqlite\",\n \"sourceCount\": 0,\n \"nodeCount\": 0,\n \"edgeCount\": 0,\n \"issueCount\": 0,\n \"extractionCount\": 0,\n \"jobRunCount\": 0,\n \"refinementTaskCount\": 0,\n \"usageCount\": 0,\n \"candidateCount\": 0,\n \"reportCount\": 0,\n \"scheduleCount\": 3,\n \"note\": \"Structured knowledge uses SQL-backed sources, nodes, edges, issues, extractions, and job runs. Markdown is an optional projection, not the source of truth.\"\n }\n}"
48
48
  },
49
49
  {
50
50
  "id": "cli-providers",
@@ -65,28 +65,28 @@
65
65
  "title": "Authenticated connected-host /status",
66
66
  "status": "pass",
67
67
  "summary": "/status returned 200 with parseable JSON.",
68
- "detail": "{\"status\":\"running\"}"
68
+ "detail": "{\"status\":\"running\",\"version\":\"0.33.36\"}"
69
69
  },
70
70
  {
71
71
  "id": "connected-host-health",
72
72
  "title": "Authenticated connected-host /api/health",
73
73
  "status": "pass",
74
74
  "summary": "Health overall=healthy.",
75
- "detail": "{\"overall\":\"healthy\",\"degradedDomains\":[],\"providerProblems\":[],\"mcpProblems\":{\"degraded\":[],\"quarantined\":[]},\"integrationProblems\":[],\"network\":{\"controlPlane\":{\"surface\":\"controlPlane\",\"host\":\"0.0.0.0\",\"port\":3421,\"mode\":\"off\",\"scheme\":\"http\",\"trustProxy\":false,\"usingDefaultPaths\":false,\"ready\":true,\"errors\":[]},\"httpListener\":{\"surface\":\"httpListener\",\"host\":\"0.0.0.0\",\"port\":3422,\"mode\":\"off\",\"scheme\":\"http\",\"trustProxy\":false,\"usingDefaultPaths\":false,\"ready\":true,\"errors\":[]},\"outbound\":{\"mode\":\"bundled\",\"allowInsecureLocalhost\":false,\"customCaEntryCount\":0,\"effectiveCaStrategy\":\"bun-default\",\"errors\":[]}}}"
75
+ "detail": "{\"overall\":\"healthy\",\"degradedDomains\":[],\"providerProblems\":[],\"mcpProblems\":{\"degraded\":[],\"quarantined\":[]},\"integrationProblems\":[],\"network\":{\"controlPlane\":{\"surface\":\"controlPlane\",\"host\":\"127.0.0.1\",\"port\":3421,\"mode\":\"off\",\"scheme\":\"http\",\"trustProxy\":false,\"usingDefaultPaths\":false,\"ready\":true,\"errors\":[]},\"httpListener\":{\"surface\":\"httpListener\",\"host\":\"127.0.0.1\",\"port\":3422,\"mode\":\"off\",\"scheme\":\"http\",\"trustProxy\":false,\"usingDefaultPaths\":false,\"ready\":true,\"errors\":[]},\"outbound\":{\"mode\":\"bundled\",\"allowInsecureLocalhost\":false,\"customCaEntryCount\":0,\"effectiveCaStrategy\":\"bun-default\",\"errors\":[]}}}"
76
76
  },
77
77
  {
78
78
  "id": "openai-compatible-models",
79
79
  "title": "OpenAI-compatible /v1/models route",
80
80
  "status": "pass",
81
- "summary": "/v1/models returned 11 model(s).",
82
- "detail": "/v1/models returned 11 model(s); model identifiers omitted from release artifact."
81
+ "summary": "/v1/models returned 175 model(s).",
82
+ "detail": "/v1/models returned 175 model(s); model identifiers omitted from release artifact."
83
83
  },
84
84
  {
85
85
  "id": "agent-knowledge-status",
86
86
  "title": "Agent Knowledge isolated /status",
87
87
  "status": "pass",
88
88
  "summary": "Agent Knowledge status route returned parseable isolated JSON.",
89
- "detail": "{\"ready\":true,\"storagePath\":\"[goodvibes-home]/tui/knowledge-agent.sqlite\",\"sourceCount\":0,\"nodeCount\":12,\"edgeCount\":0,\"issueCount\":0,\"extractionCount\":0,\"jobRunCount\":35,\"refinementTaskCount\":0,\"usageCount\":0,\"candidateCount\":0,\"reportCount\":2,\"scheduleCount\":3,\"note\":\"Structured knowledge uses SQL-backed sources, nodes, edges, issues, extractions, and job runs. Markdown is an optional projection, not the source of truth.\"}"
89
+ "detail": "{\"ready\":true,\"storagePath\":\"[goodvibes-home]/tui/knowledge-agent.sqlite\",\"sourceCount\":0,\"nodeCount\":0,\"edgeCount\":0,\"issueCount\":0,\"extractionCount\":0,\"jobRunCount\":0,\"refinementTaskCount\":0,\"usageCount\":0,\"candidateCount\":0,\"reportCount\":0,\"scheduleCount\":3,\"note\":\"Structured knowledge uses SQL-backed sources, nodes, edges, issues, extractions, and job runs. Markdown is an optional projection, not the source of truth.\"}"
90
90
  },
91
91
  {
92
92
  "id": "agent-knowledge-ask-isolated",
@@ -114,7 +114,7 @@
114
114
  "title": "Agent Knowledge isolated nodes list",
115
115
  "status": "pass",
116
116
  "summary": "Agent Knowledge isolated nodes list stayed on the isolated Agent route.",
117
- "detail": "{\"nodes\":[{\"id\":\"node-38d4924f\",\"kind\":\"topic\",\"slug\":\"linked-to-26-graph-relation-s\",\"title\":\"linked to 26 graph relation(s)\",\"summary\":\"Topic tag linked to 26 graph relation(s).\",\"aliases\":[\"linked to 26 graph relation(s)\"],\"status\":\"active\",\"confidence\":70,\"metadata\":{\"tag\":\"linked to 26 graph relation(s)\",\"knowledgeSpaceId\":\"goodvibes-agent:default\",\"namespace\":\"goodvibes-agent:default\"},\"createdAt\":1780489632675,\"updatedAt\":1780489632928},{\"id\":\"node-4014fce2\",\"kind\":\"topic\",\"slug\":\"observed-via-2-usage-pattern-s\",\"title\":\"observed via 2 usage pattern(s)\",\"summary\":\"Topic tag observed via 2 usage pattern(s).\",\"aliases\":[\"observed via 2 usage pattern(s)\"],\"status\":\"active\",\"confidence\":70,\"metadata\":{\"tag\":\"observed via 2 usage pattern(s)\",\"knowledgeSpaceId\":\"goodvibes-agent:default\",\"namespace\":\"goodvibes-agent:default\"},\"createdAt\":1780489632666,\"updatedAt\":17804896... [truncated]"
117
+ "detail": "{\"nodes\":[]}"
118
118
  },
119
119
  {
120
120
  "id": "agent-knowledge-issues-isolated",
@@ -128,7 +128,7 @@
128
128
  "title": "Agent Knowledge isolated map",
129
129
  "status": "pass",
130
130
  "summary": "Agent Knowledge isolated map stayed on the isolated Agent route.",
131
- "detail": "{\"ok\":true,\"title\":\"Knowledge Map\",\"generatedAt\":1780570932688,\"width\":1280,\"height\":920,\"nodeCount\":12,\"edgeCount\":0,\"totalNodeCount\":12,\"totalEdgeCount\":0,\"facets\":{\"recordKinds\":[{\"value\":\"node\",\"count\":12}],\"nodeKinds\":[{\"value\":\"topic\",\"count\":12}],\"sourceTypes\":[],\"sourceStatuses\":[],\"nodeStatuses\":[{\"value\":\"active\",\"count\":12}],\"issueCodes\":[],\"issueStatuses\":[],\"issueSeverities\":[],\"edgeRelations\":[],\"tags\":[]},\"nodes\":[{\"id\":\"node-d2a534ae\",\"recordKind\":\"node\",\"kind\":\"topic\",\"title\":\"linked to 19 graph relation(s)\",\"summary\":\"Topic tag linked to 19 graph relation(s).\",\"x\":720,\"y\":277,\"radius\":23,\"metadata\":{\"tag\":\"linked to 19 graph relation(s)\",\"knowledgeSpaceId\":\"goodvibes-agent:default\",\"namespace\":\"goodvibes-agent:default\"}},{\"id\":\"node-0cc2f686\",\"recordKind\":\"node\",\"kind\":\"topic\",\"title\":\"linked to 20 graph relation(s)\",\"summary\":\"Topic tag linked to 20 gra... [truncated]"
131
+ "detail": "{\"ok\":true,\"title\":\"Knowledge Map\",\"generatedAt\":1781472844439,\"width\":1280,\"height\":920,\"nodeCount\":0,\"edgeCount\":0,\"totalNodeCount\":0,\"totalEdgeCount\":0,\"facets\":{\"recordKinds\":[],\"nodeKinds\":[],\"sourceTypes\":[],\"sourceStatuses\":[],\"nodeStatuses\":[],\"issueCodes\":[],\"issueStatuses\":[],\"issueSeverities\":[],\"edgeRelations\":[],\"tags\":[]},\"nodes\":[],\"edges\":[],\"svg\":\"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"1280\\\" height=\\\"920\\\" viewBox=\\\"0 0 1280 920\\\" role=\\\"img\\\" aria-label=\\\"Knowledge Map\\\">\\n<defs>\\n <radialGradient id=\\\"knowledgeMapBg\\\" cx=\\\"50%\\\" cy=\\\"46%\\\" r=\\\"70%\\\">\\n <stop offset=\\\"0%\\\" stop-color=\\\"#f7f4ec\\\" />\\n <stop offset=\\\"60%\\\" stop-color=\\\"#e9eef0\\\" />\\n <stop offset=\\\"100%\\\" stop-color=\\\"#dde6df\\\" />\\n </radialGradient>\\n <filter id=\\\"softShadow\\\" x=\\\"-20%\\\" y=\\\"-20%\\\" width=\\\"140%\\\" height=\\\"140%\\\">\\n <feDropShadow dx=\\\"0\\\" dy=\\\"6\\... [truncated]"
132
132
  },
133
133
  {
134
134
  "id": "agent-knowledge-connectors-isolated",
@@ -1,6 +1,6 @@
1
1
  # GoodVibes Agent Live Verification
2
2
 
3
- Generated: 2026-06-04T11:02:12.690Z
3
+ Generated: 2026-06-14T21:34:04.442Z
4
4
  Home: `[goodvibes-home]`
5
5
  Binary: `[agent-binary]`
6
6
  Connected host: `http://127.0.0.1:3421`
@@ -14,7 +14,7 @@ Connected host: `http://127.0.0.1:3421`
14
14
 
15
15
  | Check | Status | Summary |
16
16
  |---|---|---|
17
- | Verification inventory ledger | pass | 100% local verification signal across 761 inventory items. |
17
+ | Verification inventory ledger | pass | 99.5% local verification signal across 806 inventory items. |
18
18
  | Compiled GoodVibes Agent CLI binary | pass | Found [agent-binary]. |
19
19
  | Agent CLI version command | pass | Agent CLI version returned successfully. |
20
20
  | Agent CLI status JSON command | pass | Agent CLI status returned parseable JSON. |
@@ -24,7 +24,7 @@ Connected host: `http://127.0.0.1:3421`
24
24
  | CLI doctor command | pass | Doctor completed without findings. |
25
25
  | Authenticated connected-host /status | pass | /status returned 200 with parseable JSON. |
26
26
  | Authenticated connected-host /api/health | pass | Health overall=healthy. |
27
- | OpenAI-compatible /v1/models route | pass | /v1/models returned 11 model(s). |
27
+ | OpenAI-compatible /v1/models route | pass | /v1/models returned 175 model(s). |
28
28
  | Agent Knowledge isolated /status | pass | Agent Knowledge status route returned parseable isolated JSON. |
29
29
  | Agent Knowledge isolated ask | pass | Agent Knowledge ask stayed on the isolated Agent route. |
30
30
  | Agent Knowledge isolated search | pass | Agent Knowledge search stayed on the isolated Agent route. |
@@ -39,13 +39,13 @@ Connected host: `http://127.0.0.1:3421`
39
39
  ### Verification inventory ledger
40
40
 
41
41
  ```text
42
- 87.4% local behavior verified; 96 item(s) require external outcomes.
42
+ 83.9% local behavior verified; 96 item(s) require external outcomes.
43
43
  ```
44
44
 
45
45
  ### Agent CLI version command
46
46
 
47
47
  ```text
48
- goodvibes-agent 1.0.35
48
+ goodvibes-agent 1.5.0
49
49
  ```
50
50
 
51
51
  ### Agent CLI status JSON command
@@ -59,7 +59,7 @@ Status JSON command completed; provider/model identifiers omitted from release a
59
59
  ```text
60
60
  {
61
61
  "ok": true,
62
- "packageVersion": "1.0.35",
62
+ "packageVersion": "1.5.0",
63
63
  "connectedHost": {
64
64
  "baseUrl": "http://127.0.0.1:3421",
65
65
  "status": 200,
@@ -89,15 +89,15 @@ Status JSON command completed; provider/model identifiers omitted from release a
89
89
  "ready": true,
90
90
  "storagePath": "[goodvibes-home]/tui/knowledge-agent.sqlite",
91
91
  "sourceCount": 0,
92
- "nodeCount": 12,
92
+ "nodeCount": 0,
93
93
  "edgeCount": 0,
94
94
  "issueCount": 0,
95
95
  "extractionCount": 0,
96
- "jobRunCount": 35,
96
+ "jobRunCount": 0,
97
97
  "refinementTaskCount": 0,
98
98
  "usageCount": 0,
99
99
  "candidateCount": 0,
100
- "reportCount": 2,
100
+ "reportCount": 0,
101
101
  "scheduleCount": 3,
102
102
  "note": "Structured knowledge uses SQL-backed sources, nodes, edges, issues, extractions, and job runs. Markdown is an optional projection, not the source of truth."
103
103
  }
@@ -119,25 +119,25 @@ Doctor command completed without findings; provider/model identifiers and creden
119
119
  ### Authenticated connected-host /status
120
120
 
121
121
  ```text
122
- {"status":"running"}
122
+ {"status":"running","version":"0.33.36"}
123
123
  ```
124
124
 
125
125
  ### Authenticated connected-host /api/health
126
126
 
127
127
  ```text
128
- {"overall":"healthy","degradedDomains":[],"providerProblems":[],"mcpProblems":{"degraded":[],"quarantined":[]},"integrationProblems":[],"network":{"controlPlane":{"surface":"controlPlane","host":"0.0.0.0","port":3421,"mode":"off","scheme":"http","trustProxy":false,"usingDefaultPaths":false,"ready":true,"errors":[]},"httpListener":{"surface":"httpListener","host":"0.0.0.0","port":3422,"mode":"off","scheme":"http","trustProxy":false,"usingDefaultPaths":false,"ready":true,"errors":[]},"outbound":{"mode":"bundled","allowInsecureLocalhost":false,"customCaEntryCount":0,"effectiveCaStrategy":"bun-default","errors":[]}}}
128
+ {"overall":"healthy","degradedDomains":[],"providerProblems":[],"mcpProblems":{"degraded":[],"quarantined":[]},"integrationProblems":[],"network":{"controlPlane":{"surface":"controlPlane","host":"127.0.0.1","port":3421,"mode":"off","scheme":"http","trustProxy":false,"usingDefaultPaths":false,"ready":true,"errors":[]},"httpListener":{"surface":"httpListener","host":"127.0.0.1","port":3422,"mode":"off","scheme":"http","trustProxy":false,"usingDefaultPaths":false,"ready":true,"errors":[]},"outbound":{"mode":"bundled","allowInsecureLocalhost":false,"customCaEntryCount":0,"effectiveCaStrategy":"bun-default","errors":[]}}}
129
129
  ```
130
130
 
131
131
  ### OpenAI-compatible /v1/models route
132
132
 
133
133
  ```text
134
- /v1/models returned 11 model(s); model identifiers omitted from release artifact.
134
+ /v1/models returned 175 model(s); model identifiers omitted from release artifact.
135
135
  ```
136
136
 
137
137
  ### Agent Knowledge isolated /status
138
138
 
139
139
  ```text
140
- {"ready":true,"storagePath":"[goodvibes-home]/tui/knowledge-agent.sqlite","sourceCount":0,"nodeCount":12,"edgeCount":0,"issueCount":0,"extractionCount":0,"jobRunCount":35,"refinementTaskCount":0,"usageCount":0,"candidateCount":0,"reportCount":2,"scheduleCount":3,"note":"Structured knowledge uses SQL-backed sources, nodes, edges, issues, extractions, and job runs. Markdown is an optional projection, not the source of truth."}
140
+ {"ready":true,"storagePath":"[goodvibes-home]/tui/knowledge-agent.sqlite","sourceCount":0,"nodeCount":0,"edgeCount":0,"issueCount":0,"extractionCount":0,"jobRunCount":0,"refinementTaskCount":0,"usageCount":0,"candidateCount":0,"reportCount":0,"scheduleCount":3,"note":"Structured knowledge uses SQL-backed sources, nodes, edges, issues, extractions, and job runs. Markdown is an optional projection, not the source of truth."}
141
141
  ```
142
142
 
143
143
  ### Agent Knowledge isolated ask
@@ -161,7 +161,7 @@ Doctor command completed without findings; provider/model identifiers and creden
161
161
  ### Agent Knowledge isolated nodes list
162
162
 
163
163
  ```text
164
- {"nodes":[{"id":"node-38d4924f","kind":"topic","slug":"linked-to-26-graph-relation-s","title":"linked to 26 graph relation(s)","summary":"Topic tag linked to 26 graph relation(s).","aliases":["linked to 26 graph relation(s)"],"status":"active","confidence":70,"metadata":{"tag":"linked to 26 graph relation(s)","knowledgeSpaceId":"goodvibes-agent:default","namespace":"goodvibes-agent:default"},"createdAt":1780489632675,"updatedAt":1780489632928},{"id":"node-4014fce2","kind":"topic","slug":"observed-via-2-usage-pattern-s","title":"observed via 2 usage pattern(s)","summary":"Topic tag observed via 2 usage pattern(s).","aliases":["observed via 2 usage pattern(s)"],"status":"active","confidence":70,"metadata":{"tag":"observed via 2 usage pattern(s)","knowledgeSpaceId":"goodvibes-agent:default","namespace":"goodvibes-agent:default"},"createdAt":1780489632666,"updatedAt":17804896... [truncated]
164
+ {"nodes":[]}
165
165
  ```
166
166
 
167
167
  ### Agent Knowledge isolated issues list
@@ -173,7 +173,7 @@ Doctor command completed without findings; provider/model identifiers and creden
173
173
  ### Agent Knowledge isolated map
174
174
 
175
175
  ```text
176
- {"ok":true,"title":"Knowledge Map","generatedAt":1780570932688,"width":1280,"height":920,"nodeCount":12,"edgeCount":0,"totalNodeCount":12,"totalEdgeCount":0,"facets":{"recordKinds":[{"value":"node","count":12}],"nodeKinds":[{"value":"topic","count":12}],"sourceTypes":[],"sourceStatuses":[],"nodeStatuses":[{"value":"active","count":12}],"issueCodes":[],"issueStatuses":[],"issueSeverities":[],"edgeRelations":[],"tags":[]},"nodes":[{"id":"node-d2a534ae","recordKind":"node","kind":"topic","title":"linked to 19 graph relation(s)","summary":"Topic tag linked to 19 graph relation(s).","x":720,"y":277,"radius":23,"metadata":{"tag":"linked to 19 graph relation(s)","knowledgeSpaceId":"goodvibes-agent:default","namespace":"goodvibes-agent:default"}},{"id":"node-0cc2f686","recordKind":"node","kind":"topic","title":"linked to 20 graph relation(s)","summary":"Topic tag linked to 20 gra... [truncated]
176
+ {"ok":true,"title":"Knowledge Map","generatedAt":1781472844439,"width":1280,"height":920,"nodeCount":0,"edgeCount":0,"totalNodeCount":0,"totalEdgeCount":0,"facets":{"recordKinds":[],"nodeKinds":[],"sourceTypes":[],"sourceStatuses":[],"nodeStatuses":[],"issueCodes":[],"issueStatuses":[],"issueSeverities":[],"edgeRelations":[],"tags":[]},"nodes":[],"edges":[],"svg":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1280\" height=\"920\" viewBox=\"0 0 1280 920\" role=\"img\" aria-label=\"Knowledge Map\">\n<defs>\n <radialGradient id=\"knowledgeMapBg\" cx=\"50%\" cy=\"46%\" r=\"70%\">\n <stop offset=\"0%\" stop-color=\"#f7f4ec\" />\n <stop offset=\"60%\" stop-color=\"#e9eef0\" />\n <stop offset=\"100%\" stop-color=\"#dde6df\" />\n </radialGradient>\n <filter id=\"softShadow\" x=\"-20%\" y=\"-20%\" width=\"140%\" height=\"140%\">\n <feDropShadow dx=\"0\" dy=\"6\... [truncated]
177
177
  ```
178
178
 
179
179
  ### Agent Knowledge isolated connectors list
@@ -1,11 +1,5 @@
1
- - v1.5.0 opens the 1.5 minor line: the fullscreen Agent workspace remains the primary user surface, Agent-local behavior, isolated Agent Knowledge, connected-host operator integration, explicit side-effect boundaries, and release hardening from 1.3.x and 1.4.x all stay in force. This release replaces the split-pane panel system with the Activity sidebar, rebuilds first-run onboarding around readiness, and adds local calendar, direct email, hardware-aware model recommendations, and skill import/export.
2
- - Replaced the 21-panel split-pane system with a single Activity sidebar. Live activity, process output, and runtime state now surface in one consistent lane instead of stacked panels; the footer was slimmed and tool calls show human-readable labels.
3
- - Rewrote the workspace Home as plain-language lanes and merged duplicate categories. The slash-command long tail moved behind /commands so the prompt surface stays focused on what users actually run.
4
- - Added a While you were away digest on return plus a live Coming up sidebar fed by the local calendar, so upcoming commitments stay visible without asking.
5
- - Rebuilt first-run onboarding around a readiness model: setup steps sequence themselves by what is actually configured, the flow can be resumed midway, and a completion recap shows what was set up. The first screen leads with a working path, the first-run model picker opens with a hardware-fit recommendation, and a plain-language hint appears in conversation while setup is incomplete.
6
- - Competitive parity wave: local calendar support, direct email send and read over SMTP and IMAP with TLS or STARTTLS, hardware-aware model recommendations, and automatic skill drafts.
7
- - Skills now import and export in the open skill standard. Exports are lossless, and skills discovered from imports stay disabled until explicitly enabled.
8
- - Hardened the email and calendar surfaces: SMTP and IMAP commands validate addresses and reject control characters, STARTTLS upgrades verify no data arrives before negotiation completes, and calendar parsing is stricter about malformed input.
9
- - Reliability fixes across the TUI: closed a text-wrap hang, made wide-character rendering consistent, fixed webhook notifier reuse, routed the benchmark editor to its real action, and made command failures surface user-visible errors everywhere.
10
- - Release and verification hygiene: the operator token is redacted from release artifacts, the coverage ledger reports honest numbers, release evidence is checked for existence, and operator-facing copy passes a plain-language gate.
1
+ - v1.5.1 is a patch on the 1.5 line. The fullscreen Agent workspace, Agent-local behavior, isolated Agent Knowledge, connected-host operator integration, and explicit side-effect boundaries all stay in force; this release restores the inline shell escape and refreshes release verification.
2
+ - Restored the inline shell escape in the prompt: type an exclamation mark followed by a command (for example, exclamation-mark git status) to run it in your working directory without leaving Agent. The command output appears inline, and the result is carried into your next message as context so you can run something and immediately ask about it. The composer already showed this as shell mode, but the command never actually ran since the workspace fork; it executes again now.
3
+ - The exclamation-hash memory pin is unchanged and still takes precedence, so pinning a note keeps working exactly as before.
4
+ - Release hygiene: regenerated the strict live-verification attestation against the running connected host so the published package carries current evidence.
11
5
  - Test suite: 7931 pass / 0 fail / 2 skip across 554 files.
@@ -0,0 +1,58 @@
1
+ /**
2
+ * ShellPassthrough — runs user-typed `!<command>` shell escapes.
3
+ *
4
+ * The composer routes a leading `!` to "shell" mode; this runs the command
5
+ * directly (a user-initiated terminal escape, not an agent tool call), shows
6
+ * its output, and buffers a context block that is prepended to the user's next
7
+ * real message — making the result visible to the model on the next turn
8
+ * without triggering a turn of its own.
9
+ *
10
+ * A buffer is used rather than appending a conversation message because the
11
+ * SDK drops `system` messages from the LLM view and does not merge consecutive
12
+ * `user` messages (which would trip a consecutive-user-message API error).
13
+ */
14
+
15
+ const MAX_SHELL_OUTPUT = 16_000;
16
+
17
+ export const SHELL_USAGE_HINT =
18
+ '[Shell] Usage: !<command> — runs a shell command; its output is shown and added as context for your next message.';
19
+
20
+ export interface ShellRunResult {
21
+ /** Formatted output for the conversation/activity feed. */
22
+ readonly display: string;
23
+ /** Context block buffered for the user's next turn. */
24
+ readonly context: string;
25
+ }
26
+
27
+ export class ShellPassthrough {
28
+ private pending: string[] = [];
29
+
30
+ /** Run `command` in `cwd`, returning display + model-context renderings. */
31
+ async run(command: string, cwd: string): Promise<ShellRunResult> {
32
+ const proc = Bun.spawn(['bash', '-c', command], { cwd, stdout: 'pipe', stderr: 'pipe' });
33
+ const [out, err] = await Promise.all([
34
+ new Response(proc.stdout).text(),
35
+ new Response(proc.stderr).text(),
36
+ ]);
37
+ const exitCode = await proc.exited;
38
+ const combined = [out, err].filter((s) => s.trim().length > 0).join('\n').trimEnd();
39
+ const truncated = combined.length > MAX_SHELL_OUTPUT
40
+ ? `${combined.slice(0, MAX_SHELL_OUTPUT)}\n… [truncated ${combined.length - MAX_SHELL_OUTPUT} chars]`
41
+ : combined;
42
+ const body = truncated.length > 0 ? truncated : '(no output)';
43
+ const result: ShellRunResult = {
44
+ display: `[Shell] ${body}\n(exit ${exitCode})`,
45
+ context: `The user ran a shell command via the \`!\` prefix:\n$ ${command}\n--- output (exit ${exitCode}) ---\n${body}`,
46
+ };
47
+ this.pending.push(result.context);
48
+ return result;
49
+ }
50
+
51
+ /** Prepend (and clear) any buffered shell context onto an outgoing message. */
52
+ consumeContext(text: string): string {
53
+ if (this.pending.length === 0) return text;
54
+ const context = this.pending.join('\n\n');
55
+ this.pending = [];
56
+ return text ? `${context}\n\n${text}` : context;
57
+ }
58
+ }
package/src/main.ts CHANGED
@@ -20,6 +20,7 @@ import { renderSettingsModal } from './renderer/settings-modal.ts';
20
20
  import { registerBuiltinCommands } from './input/commands.ts';
21
21
  import { ScheduleManager } from '@pellux/goodvibes-sdk/platform/tools';
22
22
  import { InputHistory } from './input/input-history.ts';
23
+ import { ShellPassthrough, SHELL_USAGE_HINT } from './input/shell-passthrough.ts';
23
24
  import { getTierPromptSupplement, getTierForContextWindow } from '@pellux/goodvibes-sdk/platform/providers';
24
25
  import { createShellLayout } from './renderer/layout-engine.ts';
25
26
  import { buildShellFooter, estimateShellFooterHeight } from './renderer/shell-surface.ts';
@@ -156,6 +157,8 @@ async function main() {
156
157
  let scrollTop = 0;
157
158
  let scrollLocked = true;
158
159
 
160
+ const shellPassthrough = new ShellPassthrough();
161
+
159
162
  // Ambient autonomy surfacing: away digest at launch + sidebar Coming up.
160
163
  const autonomy = createAutonomySurfacing({
161
164
  shellPaths: ctx.services.shellPaths,
@@ -315,14 +318,28 @@ async function main() {
315
318
  systemMessageRouter.high(`[Memory] Pinned: "${memoryText}" (${memId})`);
316
319
  processedText = memoryText;
317
320
  }
321
+ } else if (processedText.startsWith('!')) {
322
+ const command = processedText.slice(1).trim();
323
+ if (!command) {
324
+ systemMessageRouter.high(SHELL_USAGE_HINT);
325
+ render();
326
+ return;
327
+ }
328
+ systemMessageRouter.high(`[Shell] $ ${command}`); render();
329
+ void shellPassthrough.run(command, workingDir)
330
+ .then((result) => systemMessageRouter.high(result.display))
331
+ .catch((shellErr: unknown) => systemMessageRouter.high(`[Shell] Failed to run: ${summarizeError(shellErr)}`))
332
+ .finally(() => render());
333
+ return;
318
334
  }
319
335
  if (processedText || content) {
320
336
  void (async () => {
321
337
  const inputOptions = options.spokenOutput ? createSpokenTurnInputOptions() : undefined;
338
+ const outgoing = shellPassthrough.consumeContext(processedText);
322
339
  if (options.spokenOutput && processedText) {
323
340
  spokenTurns.submitNextTurn(processedText);
324
341
  }
325
- orchestrator.handleUserInput(processedText, content, inputOptions).catch((err: unknown) => {
342
+ orchestrator.handleUserInput(outgoing, content, inputOptions).catch((err: unknown) => {
326
343
  logger.debug('handleUserInput safety catch (already handled by runTurn)', { error: summarizeError(err) });
327
344
  });
328
345
  })();
package/src/version.ts CHANGED
@@ -6,7 +6,7 @@ import { join } from 'node:path';
6
6
  // The prebuild script updates the fallback value before compilation.
7
7
  // Uses import.meta.dir (Bun) to locate package.json relative to this file,
8
8
  // which is correct regardless of the process working directory.
9
- let _version = '1.5.0';
9
+ let _version = '1.5.1';
10
10
  try {
11
11
  const pkg = JSON.parse(readFileSync(join(import.meta.dir, '..', 'package.json'), 'utf-8')) as {
12
12
  readonly version?: unknown;