@pellux/goodvibes-agent 1.5.7 → 1.5.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/CHANGELOG.md +9 -3
  2. package/README.md +1 -1
  3. package/dist/package/main.js +28 -89
  4. package/package.json +1 -1
  5. package/src/agent/memory-prompt.ts +3 -3
  6. package/src/agent/operator-actions.ts +1 -1
  7. package/src/agent/prompt-context-receipts.ts +3 -3
  8. package/src/agent/session-registration.ts +1 -1
  9. package/src/agent/vibe-file.ts +5 -5
  10. package/src/cli/local-library-command-shared.ts +1 -1
  11. package/src/cli/memory-command.ts +9 -6
  12. package/src/cli/resume-relaunch-notice.ts +1 -1
  13. package/src/cli/tui-startup.ts +1 -1
  14. package/src/config/credential-status.ts +1 -1
  15. package/src/config/index.ts +1 -1
  16. package/src/config/secrets.ts +1 -1
  17. package/src/core/conversation-rendering.ts +2 -2
  18. package/src/core/system-message-noise.ts +3 -3
  19. package/src/core/thinking-overlay.ts +1 -1
  20. package/src/input/agent-workspace-basic-command-editor-submission.ts +1 -1
  21. package/src/input/agent-workspace-basic-command-editors.ts +1 -1
  22. package/src/input/agent-workspace-calendar-connect-editor.ts +1 -1
  23. package/src/input/agent-workspace-calendar-oauth-editor.ts +1 -1
  24. package/src/input/agent-workspace-calendar-subscribe-editor.ts +1 -1
  25. package/src/input/agent-workspace-command-editor-engine.ts +2 -2
  26. package/src/input/agent-workspace-direct-editor-submission.ts +1 -1
  27. package/src/input/agent-workspace-email-connect-editor.ts +1 -1
  28. package/src/input/agent-workspace-live-counters.ts +1 -1
  29. package/src/input/agent-workspace-settings.ts +1 -1
  30. package/src/input/agent-workspace-snapshot-builders.ts +2 -2
  31. package/src/input/agent-workspace-snapshot-config.ts +1 -1
  32. package/src/input/agent-workspace-snapshot.ts +9 -9
  33. package/src/input/agent-workspace-types.ts +4 -4
  34. package/src/input/agent-workspace.ts +1 -1
  35. package/src/input/commands/calendar-connect-runtime.ts +1 -1
  36. package/src/input/commands/calendar-subscription-runtime.ts +2 -2
  37. package/src/input/commands/operator-actions-runtime.ts +1 -1
  38. package/src/input/commands/session-content.ts +1 -1
  39. package/src/input/commands/session-workflow.ts +1 -1
  40. package/src/input/feed-context-factory.ts +4 -4
  41. package/src/input/handler-feed.ts +9 -9
  42. package/src/input/handler.ts +1 -1
  43. package/src/input/panel-paste-flood-guard.ts +3 -3
  44. package/src/input/settings-modal.ts +1 -1
  45. package/src/main.ts +4 -4
  46. package/src/renderer/agent-workspace-context-lines.ts +1 -1
  47. package/src/renderer/startup-theme-probe.ts +1 -1
  48. package/src/renderer/status-glyphs.ts +2 -2
  49. package/src/renderer/terminal-bg-probe.ts +1 -1
  50. package/src/renderer/terminal-escapes.ts +3 -2
  51. package/src/renderer/theme-mode-config.ts +2 -2
  52. package/src/renderer/theme.ts +4 -4
  53. package/src/renderer/thinking.ts +1 -1
  54. package/src/renderer/ui-factory.ts +1 -1
  55. package/src/renderer/ui-primitives.ts +2 -2
  56. package/src/runtime/bootstrap-core.ts +2 -2
  57. package/src/runtime/bootstrap.ts +3 -3
  58. package/src/runtime/calendar-boot-refresh.ts +1 -1
  59. package/src/runtime/lan-scan-consent.ts +1 -1
  60. package/src/runtime/services.ts +7 -7
  61. package/src/runtime/terminal-output-guard.ts +1 -1
  62. package/src/runtime/ui-services.ts +1 -1
  63. package/src/shell/agent-workspace-fullscreen.ts +1 -1
  64. package/src/shell/terminal-focus-mode.ts +9 -9
  65. package/src/shell/ui-openers.ts +1 -1
  66. package/src/tools/agent-harness-operator-methods.ts +1 -1
  67. package/src/tools/agent-harness-personal-ops-discovery.ts +2 -2
  68. package/src/tools/agent-harness-personal-ops-lanes.ts +1 -1
  69. package/src/tools/agent-harness-personal-ops-types.ts +1 -1
  70. package/src/tools/agent-harness-prompt-context.ts +3 -3
  71. package/src/tools/agent-local-registry-memory.ts +1 -1
  72. package/src/tools/agent-operator-method-tool.ts +1 -1
  73. package/src/version.ts +1 -1
package/CHANGELOG.md CHANGED
@@ -2,11 +2,17 @@
2
2
 
3
3
  Product-facing release notes for GoodVibes Agent.
4
4
 
5
+ ## 1.5.8 - 2026-07-06
6
+
7
+ - The `memory` CLI command (`goodvibes-agent memory ...`) now writes to the same shared cross-surface memory store that the runtime, the terminal UI, and the SDK already read and write. Previously the CLI opened its own private database, so a memory added from the CLI was invisible everywhere else; a memory added from the CLI is now visible in the Agent runtime, the TUI, and the SDK, and vice versa.
8
+ - Memory records written by older CLI versions are not lost: the runtime's existing startup memory merge already reads from the exact path the old CLI wrote to, so those older records are folded into the shared store automatically the next time the runtime starts. No manual migration step is needed.
9
+ - Documentation and code-comment hygiene: internal planning shorthand was replaced with plain language in comments, test names, and past changelog entries. No behavior change.
10
+
5
11
  ## 1.5.7 - 2026-07-06
6
12
 
7
- - v1.5.7 is a patch on the 1.5 line that COMPLETES the Wave-6 platform-SDK adoption started in 1.5.6. The fullscreen Agent workspace, Agent-local behavior, isolated Agent Knowledge, connected-host operator integration, and explicit side-effect boundaries all stay in force; the bundled 1.0.0 GoodVibes platform SDK is unchanged.
8
- - Adopted the platform's shared credential-status read (W6-C1). When the Agent acts as a client of a connected GoodVibes host, it now reads credential *status* — whether each shared-store credential is configured and usable — over the daemon's `credentials.get` route, and renders it honestly: a host with no shared credential store, an older host that does not serve the route yet, or an unreachable host all report a plain "status unavailable" reason. It never shows a fabricated "configured" and never carries a secret value over the wire. Secret *resolution* for provider auth is unchanged and stays local; API keys remain environment-only and are never persisted.
9
- - Completed the memory-unification boot follow-ups (W6-C2). At startup the Agent now folds any legacy per-surface memory into the single cross-surface store and shows the fold report (nothing is silently dropped), migrates existing VIBE.md personality files into durable persona records exactly once — guarded by a persisted marker so the same file is never re-imported into near-duplicate records — and builds the VIBE prompt as a projection of those persona records. The projection preserves the precedence rule verbatim: these vibe instructions are followed only when they do not conflict with explicit user instructions, safety policy, tool contracts, confirmation requirements, or secret-handling rules.
13
+ - v1.5.7 is a patch on the 1.5 line that completes the platform-SDK adoption started in 1.5.6. The fullscreen Agent workspace, Agent-local behavior, isolated Agent Knowledge, connected-host operator integration, and explicit side-effect boundaries all stay in force; the bundled 1.0.0 GoodVibes platform SDK is unchanged.
14
+ - Adopted the platform's shared credential-status read. When the Agent acts as a client of a connected GoodVibes host, it now reads credential *status* — whether each shared-store credential is configured and usable — over the daemon's `credentials.get` route, and renders it honestly: a host with no shared credential store, an older host that does not serve the route yet, or an unreachable host all report a plain "status unavailable" reason. It never shows a fabricated "configured" and never carries a secret value over the wire. Secret *resolution* for provider auth is unchanged and stays local; API keys remain environment-only and are never persisted.
15
+ - Completed the memory-unification boot follow-ups. At startup the Agent now folds any legacy per-surface memory into the single cross-surface store and shows the fold report (nothing is silently dropped), migrates existing VIBE.md personality files into durable persona records exactly once — guarded by a persisted marker so the same file is never re-imported into near-duplicate records — and builds the VIBE prompt as a projection of those persona records. The projection preserves the precedence rule verbatim: these vibe instructions are followed only when they do not conflict with explicit user instructions, safety policy, tool contracts, confirmation requirements, or secret-handling rules.
10
16
  - No change to your conversations, skills, routines, or operator confirmation gates beyond the visibility and memory adoption above.
11
17
 
12
18
  ## 1.5.6 - 2026-07-06
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.3](https://img.shields.io/badge/version-1.5.7-blue.svg)](#install)
4
+ [![Version: 1.5.3](https://img.shields.io/badge/version-1.5.8-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
 
@@ -459642,23 +459642,6 @@ function createSchema2(db) {
459642
459642
  `);
459643
459643
  db.run(`CREATE INDEX IF NOT EXISTS idx_knowledge_schedules_job_id ON knowledge_schedules(job_id)`);
459644
459644
  }
459645
- function getKnowledgeSchemaStatements() {
459646
- const statements = [];
459647
- createSchema2({
459648
- run(sql) {
459649
- const normalized = sql.trim();
459650
- if (normalized.length > 0)
459651
- statements.push(normalized);
459652
- }
459653
- });
459654
- return statements;
459655
- }
459656
- function renderKnowledgeSchemaSql() {
459657
- return `${getKnowledgeSchemaStatements().map((statement) => statement.endsWith(";") ? statement : `${statement};`).join(`
459658
-
459659
- `)}
459660
- `;
459661
- }
459662
459645
  function rowObject(columns, values2) {
459663
459646
  return Object.fromEntries(columns.map((column, index) => [column, values2[index]]));
459664
459647
  }
@@ -772974,9 +772957,6 @@ var init_ingest = __esm(() => {
772974
772957
  // node_modules/@pellux/goodvibes-sdk/dist/platform/knowledge/browser-history/index.js
772975
772958
  var init_browser_history = __esm(() => {
772976
772959
  init_ingest();
772977
- init_discover();
772978
- init_readers();
772979
- init_paths2();
772980
772960
  });
772981
772961
 
772982
772962
  // node_modules/graphql/jsutils/devAssert.mjs
@@ -790559,7 +790539,6 @@ var init_semantic = __esm(() => {
790559
790539
  init_llm();
790560
790540
  init_gap_repair();
790561
790541
  init_service4();
790562
- init_self_improvement();
790563
790542
  });
790564
790543
 
790565
790544
  // node_modules/@pellux/goodvibes-sdk/dist/platform/knowledge/home-graph/helpers.js
@@ -794528,40 +794507,8 @@ var init_map_view = __esm(() => {
794528
794507
  });
794529
794508
 
794530
794509
  // node_modules/@pellux/goodvibes-sdk/dist/platform/knowledge/home-graph/types.js
794531
- var HOME_GRAPH_NODE_KINDS, HOME_GRAPH_RELATIONS, HOME_GRAPH_CAPABILITIES;
794510
+ var HOME_GRAPH_CAPABILITIES;
794532
794511
  var init_types15 = __esm(() => {
794533
- HOME_GRAPH_NODE_KINDS = [
794534
- "ha_home",
794535
- "ha_entity",
794536
- "ha_device",
794537
- "ha_area",
794538
- "ha_automation",
794539
- "ha_script",
794540
- "ha_scene",
794541
- "ha_label",
794542
- "ha_integration",
794543
- "ha_room",
794544
- "ha_device_passport",
794545
- "ha_maintenance_item",
794546
- "ha_troubleshooting_case",
794547
- "ha_purchase",
794548
- "ha_network_node"
794549
- ];
794550
- HOME_GRAPH_RELATIONS = [
794551
- "controls",
794552
- "located_in",
794553
- "belongs_to_device",
794554
- "has_manual",
794555
- "has_receipt",
794556
- "has_warranty",
794557
- "has_issue",
794558
- "fixed_by",
794559
- "uses_battery",
794560
- "connected_via",
794561
- "part_of_network",
794562
- "mentioned_by",
794563
- "source_for"
794564
- ];
794565
794512
  HOME_GRAPH_CAPABILITIES = [
794566
794513
  "knowledge-space-isolation",
794567
794514
  "snapshot-sync",
@@ -795968,7 +795915,6 @@ var init_service5 = __esm(() => {
795968
795915
  var init_home_graph = __esm(() => {
795969
795916
  init_service5();
795970
795917
  init_extension();
795971
- init_types15();
795972
795918
  });
795973
795919
 
795974
795920
  // node_modules/@pellux/goodvibes-sdk/dist/platform/knowledge/store-refinement.js
@@ -798359,14 +798305,10 @@ var init_service6 = __esm(() => {
798359
798305
  var init_project_planning = __esm(() => {
798360
798306
  init_service6();
798361
798307
  init_helpers3();
798362
- init_readiness();
798363
798308
  });
798364
798309
 
798365
798310
  // node_modules/@pellux/goodvibes-sdk/dist/platform/knowledge/persistence.js
798366
- var init_persistence = __esm(() => {
798367
- init_store_schema();
798368
- init_store_load();
798369
- });
798311
+ var init_persistence = () => {};
798370
798312
 
798371
798313
  // node_modules/@pellux/goodvibes-sdk/dist/platform/knowledge/projections.js
798372
798314
  class KnowledgeProjectionService {
@@ -801871,21 +801813,21 @@ var init_service7 = __esm(() => {
801871
801813
  var exports_knowledge = {};
801872
801814
  __export(exports_knowledge, {
801873
801815
  withKnowledgeSpace: () => withKnowledgeSpace,
801874
- uniqKnowledgeValues: () => uniq2,
801875
- stabilizeKnowledgeText: () => stableText,
801876
- runKnowledgeSemanticSelfImprovement: () => runKnowledgeSemanticSelfImprovement,
801816
+ uniqKnowledgeValues: () => uniq3,
801817
+ stabilizeKnowledgeText: () => stableText2,
801818
+ runKnowledgeSemanticSelfImprovement: () => runKnowledgeSemanticSelfImprovement2,
801877
801819
  resolveProjectPlanningSpace: () => resolveProjectPlanningSpace,
801878
- resolveKnowledgeDbPathFromControlPlaneDir: () => resolveKnowledgeDbPathFromControlPlaneDir,
801820
+ resolveKnowledgeDbPathFromControlPlaneDir: () => resolveKnowledgeDbPathFromControlPlaneDir2,
801879
801821
  renderPacket: () => renderPacket,
801880
801822
  renderKnowledgeSchemaSql: () => renderKnowledgeSchemaSql,
801881
801823
  renderKnowledgeMap: () => renderKnowledgeMap,
801882
801824
  readKnowledgeSearchText: () => readKnowledgeSearchText,
801883
- readBrowserKnowledgeProfile: () => readBrowserKnowledgeProfile,
801825
+ readBrowserKnowledgeProfile: () => readBrowserKnowledgeProfile2,
801884
801826
  projectPlanningSourceId: () => projectPlanningSourceId,
801885
801827
  projectPlanningProjectIdFromPath: () => projectPlanningProjectIdFromPath,
801886
801828
  projectPlanningCanonicalUri: () => projectPlanningCanonicalUri,
801887
801829
  projectKnowledgeSpaceId: () => projectKnowledgeSpaceId,
801888
- parseKnowledgeJsonValue: () => parseJsonValue,
801830
+ parseKnowledgeJsonValue: () => parseJsonValue2,
801889
801831
  normalizeProjectId: () => normalizeProjectId,
801890
801832
  normalizeKnowledgeSpaceId: () => normalizeKnowledgeSpaceId,
801891
801833
  normalizeHomeAssistantInstallationId: () => normalizeHomeAssistantInstallationId,
@@ -801893,12 +801835,12 @@ __export(exports_knowledge, {
801893
801835
  materializeGeneratedKnowledgeProjection: () => materializeGeneratedKnowledgeProjection,
801894
801836
  looksLikeRawPdfPayload: () => looksLikeRawPdfPayload,
801895
801837
  looksBinaryLikeText: () => looksBinaryLikeText,
801896
- loadKnowledgeStoreSnapshot: () => loadKnowledgeStoreSnapshot,
801838
+ loadKnowledgeStoreSnapshot: () => loadKnowledgeStoreSnapshot2,
801897
801839
  listGeneratedKnowledgePages: () => listGeneratedKnowledgePages,
801898
- listBrowserKinds: () => listBrowserKinds,
801840
+ listBrowserKinds: () => listBrowserKinds2,
801899
801841
  knowledgeSpaceMetadata: () => knowledgeSpaceMetadata,
801900
801842
  knowledgePageSourceWeight: () => knowledgePageSourceWeight,
801901
- knowledgeNowMs: () => nowMs,
801843
+ knowledgeNowMs: () => nowMs2,
801902
801844
  knowledgeExtractionNeedsRefresh: () => knowledgeExtractionNeedsRefresh,
801903
801845
  isUsefulKnowledgePageSourceCandidate: () => isUsefulKnowledgePageSourceCandidate,
801904
801846
  isUsefulKnowledgePageSource: () => isUsefulKnowledgePageSource,
@@ -801918,12 +801860,12 @@ __export(exports_knowledge, {
801918
801860
  generatedKnowledgeSourceId: () => generatedKnowledgeSourceId,
801919
801861
  generatedKnowledgeCanonicalUri: () => generatedKnowledgeCanonicalUri,
801920
801862
  extractKnowledgeArtifact: () => extractKnowledgeArtifact,
801921
- evaluateProjectPlanningReadiness: () => evaluateProjectPlanningReadiness,
801922
- discoverBrowserKnowledgeProfiles: () => discoverBrowserKnowledgeProfiles,
801863
+ evaluateProjectPlanningReadiness: () => evaluateProjectPlanningReadiness2,
801864
+ discoverBrowserKnowledgeProfiles: () => discoverBrowserKnowledgeProfiles2,
801923
801865
  createWebKnowledgeGapRepairer: () => createWebKnowledgeGapRepairer,
801924
801866
  createProviderBackedKnowledgeSemanticLlm: () => createProviderBackedKnowledgeSemanticLlm,
801925
801867
  createMemoryApi: () => createMemoryApi,
801926
- createKnowledgeSchema: () => createSchema2,
801868
+ createKnowledgeSchema: () => createSchema3,
801927
801869
  createKnowledgeApi: () => createKnowledgeApi,
801928
801870
  createDefaultKnowledgeConnectorRegistry: () => createDefaultKnowledgeConnectorRegistry,
801929
801871
  compareKnowledgePageSources: () => compareKnowledgePageSources,
@@ -804387,7 +804329,7 @@ var init_delivery_manager = __esm(() => {
804387
804329
  });
804388
804330
 
804389
804331
  // node_modules/@pellux/goodvibes-sdk/dist/platform/automation/scheduler-capacity.js
804390
- function computeSchedulerCapacity(slotsTotal, runs, nowMs2 = Date.now()) {
804332
+ function computeSchedulerCapacity(slotsTotal, runs, nowMs3 = Date.now()) {
804391
804333
  let slotsInUse = 0;
804392
804334
  const queuedRuns = [];
804393
804335
  for (const run7 of runs) {
@@ -804397,7 +804339,7 @@ function computeSchedulerCapacity(slotsTotal, runs, nowMs2 = Date.now()) {
804397
804339
  queuedRuns.push(run7);
804398
804340
  }
804399
804341
  const queueDepth = queuedRuns.length;
804400
- const oldestQueuedAgeMs = queueDepth > 0 ? nowMs2 - Math.min(...queuedRuns.map((r6) => r6.queuedAt)) : null;
804342
+ const oldestQueuedAgeMs = queueDepth > 0 ? nowMs3 - Math.min(...queuedRuns.map((r6) => r6.queuedAt)) : null;
804401
804343
  return { slotsTotal, slotsInUse, queueDepth, oldestQueuedAgeMs };
804402
804344
  }
804403
804345
 
@@ -830785,7 +830727,7 @@ var createStyledCell = (char, overrides = {}) => ({
830785
830727
  // src/version.ts
830786
830728
  import { readFileSync } from "fs";
830787
830729
  import { join } from "path";
830788
- var _version = "1.5.7";
830730
+ var _version = "1.5.8";
830789
830731
  try {
830790
830732
  const pkg = JSON.parse(readFileSync(join(import.meta.dir, "..", "package.json"), "utf-8"));
830791
830733
  _version = typeof pkg.version === "string" ? pkg.version : _version;
@@ -855898,7 +855840,7 @@ var WORK_PLAN_STATUSES = [
855898
855840
  "failed",
855899
855841
  "cancelled"
855900
855842
  ];
855901
- function nowMs2() {
855843
+ function nowMs3() {
855902
855844
  return Date.now();
855903
855845
  }
855904
855846
  function isObject4(value) {
@@ -856004,7 +855946,7 @@ class WorkPlanStore {
856004
855946
  if (!normalizedTitle)
856005
855947
  throw new Error("Work plan item title is required.");
856006
855948
  const plan = this.readPlan();
856007
- const time4 = nowMs2();
855949
+ const time4 = nowMs3();
856008
855950
  const item = {
856009
855951
  id: createItemId(),
856010
855952
  title: normalizedTitle,
@@ -856028,7 +855970,7 @@ class WorkPlanStore {
856028
855970
  updateItem(idOrPrefix, patch2) {
856029
855971
  const plan = this.readPlan();
856030
855972
  const item = this.resolveItem(plan, idOrPrefix);
856031
- const time4 = nowMs2();
855973
+ const time4 = nowMs3();
856032
855974
  const nextStatus = patch2.status ?? item.status;
856033
855975
  const next = this.pruneItem({
856034
855976
  ...item,
@@ -856061,7 +856003,7 @@ class WorkPlanStore {
856061
856003
  removeItem(idOrPrefix) {
856062
856004
  const plan = this.readPlan();
856063
856005
  const item = this.resolveItem(plan, idOrPrefix);
856064
- const time4 = nowMs2();
856006
+ const time4 = nowMs3();
856065
856007
  const remaining = plan.items.filter((candidate) => candidate.id !== item.id);
856066
856008
  this.writePlan({
856067
856009
  ...plan,
@@ -856081,7 +856023,7 @@ class WorkPlanStore {
856081
856023
  ...plan,
856082
856024
  items: remaining,
856083
856025
  activeItemId: remaining[0]?.id,
856084
- updatedAt: nowMs2()
856026
+ updatedAt: nowMs3()
856085
856027
  });
856086
856028
  return removed;
856087
856029
  }
@@ -856120,7 +856062,7 @@ class WorkPlanStore {
856120
856062
  const parsed = JSON.parse(raw);
856121
856063
  if (!isObject4(parsed))
856122
856064
  return this.createEmptyPlan();
856123
- const time4 = nowMs2();
856065
+ const time4 = nowMs3();
856124
856066
  const createdAt = typeof parsed.createdAt === "number" ? parsed.createdAt : time4;
856125
856067
  const updatedAt = typeof parsed.updatedAt === "number" ? parsed.updatedAt : createdAt;
856126
856068
  const items = Array.isArray(parsed.items) ? parsed.items.map((item) => normalizeItem(item, createdAt)).filter((item) => item !== null) : [];
@@ -856139,7 +856081,7 @@ class WorkPlanStore {
856139
856081
  };
856140
856082
  }
856141
856083
  createEmptyPlan() {
856142
- const time4 = nowMs2();
856084
+ const time4 = nowMs3();
856143
856085
  return {
856144
856086
  id: createPlanId(this.options.projectId, this.options.projectRoot),
856145
856087
  projectId: this.options.projectId,
@@ -901803,9 +901745,9 @@ Run goodvibes-agent skills discover to inspect available skill files.`, 1);
901803
901745
  }
901804
901746
 
901805
901747
  // src/cli/memory-command.ts
901748
+ init_state();
901806
901749
  import { mkdirSync as mkdirSync83, readFileSync as readFileSync105, writeFileSync as writeFileSync72 } from "fs";
901807
901750
  import { dirname as dirname80, resolve as resolve43 } from "path";
901808
- init_state();
901809
901751
  var VALID_CLASSES2 = ["decision", "constraint", "incident", "pattern", "fact", "risk", "runbook", "architecture", "ownership"];
901810
901752
  var VALID_SCOPES4 = ["session", "project", "team"];
901811
901753
  var VALID_REVIEW_STATES3 = ["fresh", "reviewed", "stale", "contradicted"];
@@ -901939,10 +901881,7 @@ function timestamp(value) {
901939
901881
  return new Date(value).toISOString().slice(0, 19).replace("T", " ");
901940
901882
  }
901941
901883
  function memoryDbPath(runtime2) {
901942
- return createShellPathService2({
901943
- workingDirectory: runtime2.workingDirectory,
901944
- homeDirectory: runtime2.homeDirectory
901945
- }).resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "memory.sqlite");
901884
+ return resolveCanonicalMemoryDbPath(runtime2.homeDirectory);
901946
901885
  }
901947
901886
  async function withMemory(runtime2, fn) {
901948
901887
  const path7 = memoryDbPath(runtime2);
@@ -967711,8 +967650,8 @@ function formatDigestTime(at, from = Date.now()) {
967711
967650
  return `yesterday ${time4}`;
967712
967651
  return `${d4.toLocaleDateString(undefined, { month: "short", day: "numeric" })} ${time4}`;
967713
967652
  }
967714
- function formatRelativeTime(targetMs, nowMs3 = Date.now()) {
967715
- const diffMs = targetMs - nowMs3;
967653
+ function formatRelativeTime(targetMs, nowMs4 = Date.now()) {
967654
+ const diffMs = targetMs - nowMs4;
967716
967655
  if (diffMs <= 0)
967717
967656
  return "soon";
967718
967657
  const diffMin = Math.round(diffMs / 60000);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pellux/goodvibes-agent",
3
- "version": "1.5.7",
3
+ "version": "1.5.8",
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
  import type { MemoryRecord, MemoryRegistry, MemoryVectorStats } from '@pellux/goodvibes-sdk/platform/state';
2
- // W6-C2 (E6): the recall-honesty floor + eligibility receipt now live in the SDK as
2
+ // The recall-honesty floor + eligibility receipt now live in the SDK as
3
3
  // the ONE cross-surface contract (memory-recall-contract.ts) instead of being defined
4
4
  // per surface. This file re-exports them unchanged so every existing agent consumer
5
5
  // keeps importing from './memory-prompt.ts', while the SDK is the single source of the
@@ -32,9 +32,9 @@ function formatMemoryLine(record: MemoryRecord): string {
32
32
  }
33
33
 
34
34
  /**
35
- * Per-turn semantic ranking of an already-eligible memory set (Wave-4 W4-A1B).
35
+ * Per-turn semantic ranking of an already-eligible memory set.
36
36
  *
37
- * W4-A1 shipped eligibility (confidence + reviewState + provenance) as the hard trust
37
+ * Eligibility (confidence + reviewState + provenance) shipped as the hard trust
38
38
  * gate but had no per-turn query to rank WITHIN that eligible set — records were only
39
39
  * ever ordered by stored confidence/recency, regardless of whether they had anything to
40
40
  * do with what the user actually just asked. `rankMemoryForTurn` never touches the gate
@@ -103,7 +103,7 @@ export const OPERATOR_ACTIONS: Record<OperatorActionId, OperatorActionDescriptor
103
103
  pathTemplate: '/api/automation/jobs/{jobId}/run',
104
104
  targetField: 'jobId',
105
105
  },
106
- // W6-C3: automation.jobs.pause/resume were retired (redundant with
106
+ // automation.jobs.pause/resume were retired (redundant with
107
107
  // disable/enable — same {id,enabled} output, same semantics). The
108
108
  // user-facing "pause"/"resume" verb is unchanged; only the wire action +
109
109
  // path moved to the canonical disable/enable methods.
@@ -140,7 +140,7 @@ function receiptSegment(input: Omit<PromptContextReceiptSegment, 'approxTokens'>
140
140
 
141
141
  function buildRuntimePromptReceiptSegments(input: RuntimePromptCompositionInput): readonly PromptContextReceiptSegment[] {
142
142
  const vibe = discoverVibeFiles(input.shellPaths);
143
- // W6-C2 (E6): the VIBE prompt is a PROJECTION of persona/constraint records, not a
143
+ // The VIBE prompt is a PROJECTION of persona/constraint records, not a
144
144
  // re-read of the files (discoverVibeFiles above stays for the file-discovery receipt).
145
145
  const vibePrompt = buildVibeProjectionPrompt(input.memoryRegistry) ?? '';
146
146
  const projectContext = discoverProjectContextFiles(input.shellPaths);
@@ -234,7 +234,7 @@ function buildRuntimePromptReceiptSegments(input: RuntimePromptCompositionInput)
234
234
  suppressedCount: suppressedMemory.length,
235
235
  promptChars: memoryPrompt.length,
236
236
  promptText: memoryPrompt,
237
- // Honest degrade note (Wave-4 W4-A1B): when per-turn relevance scoring did not
237
+ // Honest degrade note: when per-turn relevance scoring did not
238
238
  // run — no active-turn text, semantic index unavailable, or no vector match —
239
239
  // say so instead of silently presenting the fallback confidence/recency order as
240
240
  // if it were a relevance ranking.
@@ -245,7 +245,7 @@ function buildRuntimePromptReceiptSegments(input: RuntimePromptCompositionInput)
245
245
  class: record.cls,
246
246
  confidence: record.confidence,
247
247
  reason: describeMemoryPromptEligibility(record).reason,
248
- // Per-turn relevance (W4-A1B): honest wording, only present when actually scored.
248
+ // Per-turn relevance: honest wording, only present when actually scored.
249
249
  // F7a: the raw percent is paired with a qualitative band (see relevanceBand)
250
250
  // so a genuinely-lower-but-real score like "28%" doesn't read as noise.
251
251
  ...(memoryRanking.scored ? { relevance: `relevance to this turn: ${memoryRanking.relevanceById.get(record.id) ?? 0}% (${relevanceBand(memoryRanking.relevanceById.get(record.id) ?? 0)})` } : {}),
@@ -86,7 +86,7 @@ export interface SessionRecordSummary {
86
86
  }
87
87
 
88
88
  /**
89
- * Honest outcome discriminator. 'still_closed' is the Wave-1 heartbeat-resurrection
89
+ * Honest outcome discriminator. 'still_closed' is the heartbeat-resurrection
90
90
  * guard: a 200 that carries conflict:{status:'closed'} with reopened:false MUST NOT
91
91
  * be read as 'registered' or 'reopened'.
92
92
  */
@@ -5,7 +5,7 @@ import type { ShellPathService } from '@/runtime/index.ts';
5
5
  import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
6
6
  import { assertNoSecretLikeText } from './persona-registry.ts';
7
7
  import { parseMarkdownFrontmatter, stripMarkdownFrontmatter } from './markdown-frontmatter.ts';
8
- // W6-C2 (E6): VIBE.md is now a PROJECTION of persona/constraint records in the
8
+ // VIBE.md is now a PROJECTION of persona/constraint records in the
9
9
  // canonical memory store, not a separate source of truth. renderVibeProjection emits
10
10
  // the same '## VIBE.md' block from those records (caveat preserved); the file is
11
11
  // demoted to an import/export FORMAT folded in via vibeBodyToConstraintOptions.
@@ -213,7 +213,7 @@ export function buildVibePrompt(shellPaths: AgentVibePaths): string | null {
213
213
  }
214
214
 
215
215
  /**
216
- * W6-C2 (E6): the VIBE.md prompt block as a PROJECTION of persona/constraint records.
216
+ * The VIBE.md prompt block as a PROJECTION of persona/constraint records.
217
217
  *
218
218
  * This is the store-sourced replacement for buildVibePrompt (which reads the file
219
219
  * directly). It renders the same '## GoodVibes Agent VIBE.md' block — including the
@@ -226,7 +226,7 @@ export function buildVibeProjectionPrompt(memoryRecords: { getAll(): readonly Me
226
226
  }
227
227
 
228
228
  /**
229
- * W6-C2 (E6): fold discovered VIBE.md files into the store as persona/constraint
229
+ * Fold discovered VIBE.md files into the store as persona/constraint
230
230
  * records — the file demoted to an IMPORT FORMAT. Each bullet becomes one record so a
231
231
  * later single-record edit changes exactly one projected line. Secret-like content is
232
232
  * already rejected by discoverVibeFiles (readVibeCandidate → assertNoSecretLikeText),
@@ -257,7 +257,7 @@ export async function importVibeFilesIntoMemory(
257
257
  }
258
258
 
259
259
  /**
260
- * W6-C2 (E6): the persisted marker that makes the VIBE.md → memory import a strictly
260
+ * The persisted marker that makes the VIBE.md → memory import a strictly
261
261
  * ONE-TIME migration. Keyed by absolute file path → content hash, so importing the same
262
262
  * VIBE.md twice is a no-op (re-import would create near-duplicate persona records), while
263
263
  * a NEW project's VIBE.md still migrates exactly once. Mirrors the sessions.spine-folded
@@ -300,7 +300,7 @@ function hashVibeBody(body: string): string {
300
300
  }
301
301
 
302
302
  /**
303
- * W6-C2 (E6): fold discovered VIBE.md files into persona/constraint records ONCE.
303
+ * Fold discovered VIBE.md files into persona/constraint records ONCE.
304
304
  * Guarded by a persisted path→hash marker so it never re-imports the same file (which
305
305
  * would create near-duplicate persona records). Called at boot AFTER memoryStore.init().
306
306
  * Returns the number of records created this run (0 when everything is already migrated).
@@ -7,7 +7,7 @@ import type { CliCommandRuntime } from './management.ts';
7
7
  /**
8
8
  * Shared prelude for the Agent-local library CLI commands (personas, skills,
9
9
  * skill bundles): option parsing, success/failure envelopes, and registry
10
- * accessors. Split out of local-library-command.ts (W4-H1 ruling: the file
10
+ * accessors. Split out of local-library-command.ts (the file
11
11
  * cleanly contained three independent command handlers glued together) so
12
12
  * personas-command.ts, skills-command.ts, and skill-bundle-command.ts can
13
13
  * share one option-parsing/output prelude without duplicating it.
@@ -1,10 +1,10 @@
1
1
  import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
2
  import { dirname, resolve } from 'node:path';
3
- import { createShellPathService } from '@/runtime/index.ts';
4
3
  import {
5
4
  MemoryEmbeddingProviderRegistry,
6
5
  MemoryRegistry,
7
6
  MemoryStore,
7
+ resolveCanonicalMemoryDbPath,
8
8
  type MemoryBundle,
9
9
  type MemoryClass,
10
10
  type MemoryLink,
@@ -18,7 +18,6 @@ import {
18
18
  } from '@pellux/goodvibes-sdk/platform/state';
19
19
  import { assertNoSecretLikeMemoryText } from '../agent/memory-safety.ts';
20
20
  import { formatAgentRecordReference, formatAgentRecordReviewState } from '../agent/record-labels.ts';
21
- import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
22
21
  import type { CliCommandOutput } from './types.ts';
23
22
  import type { CliCommandRuntime } from './management.ts';
24
23
 
@@ -196,11 +195,15 @@ function timestamp(value: number): string {
196
195
  return new Date(value).toISOString().slice(0, 19).replace('T', ' ');
197
196
  }
198
197
 
198
+ // The CLI no longer opens a private per-surface agent/memory.sqlite. It opens the
199
+ // ONE canonical cross-surface store (~/.goodvibes/shared/memory.sqlite) so a memory
200
+ // added via `goodvibes-agent memory add` is visible to the runtime, the TUI, and the
201
+ // SDK — and vice-versa. The old CLI-written store is folded into the canonical store
202
+ // (loss-free, idempotent) by the runtime's foldAgentLegacyMemory at boot, since that
203
+ // fold already sources shellPaths.resolveUserPath('agent', 'memory.sqlite') — the exact
204
+ // path this function used to write to.
199
205
  function memoryDbPath(runtime: CliCommandRuntime): string {
200
- return createShellPathService({
201
- workingDirectory: runtime.workingDirectory,
202
- homeDirectory: runtime.homeDirectory,
203
- }).resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, 'memory.sqlite');
206
+ return resolveCanonicalMemoryDbPath(runtime.homeDirectory);
204
207
  }
205
208
 
206
209
  async function withMemory<T>(runtime: CliCommandRuntime, fn: (context: MemoryContext) => Promise<T> | T): Promise<T> {
@@ -1,7 +1,7 @@
1
1
  import type { SessionManager } from '@pellux/goodvibes-sdk/platform/sessions';
2
2
 
3
3
  /**
4
- * RESUME-ON-RELAUNCH (W4-A4).
4
+ * RESUME-ON-RELAUNCH.
5
5
  *
6
6
  * The dogfood finding: relaunching the agent after a normal (non-crash) exit
7
7
  * silently starts fresh with no offer or notice about the prior session — the
@@ -116,7 +116,7 @@ export function applyInitialTuiCliState(options: {
116
116
  // Normal relaunch: onboarding is done and the user didn't ask for
117
117
  // onboarding or an explicit `sessions resume`. Surface an honest,
118
118
  // non-blocking resume affordance instead of silently starting fresh
119
- // (the W4-A4 dogfood finding) — never auto-resume, declining is
119
+ // (a dogfood finding) — never auto-resume, declining is
120
120
  // frictionless (just start typing).
121
121
  surfaceResumeRelaunchNotice({
122
122
  getLastSessionPointer: () => readLastSessionPointer({
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * credential-status.ts — client-side, secret-FREE credential STATUS read.
3
3
  *
4
- * W6-C1 (E7 config sharing). When GoodVibes Agent acts as a CLIENT of an adopted
4
+ * When GoodVibes Agent acts as a CLIENT of an adopted
5
5
  * external daemon, it reads credential *status* (configured / usable) from the
6
6
  * daemon's shared store over the wire — the `credentials.get` operator method
7
7
  * (GET /config/credentials, admin + read:config). It NEVER receives raw secret
@@ -56,7 +56,7 @@ export function getConfiguredSystemPrompt(configManager: Pick<ConfigManager, 'ge
56
56
 
57
57
  export { getConfiguredApiKeys, resolveApiKeys } from '@pellux/goodvibes-sdk/platform/config';
58
58
 
59
- // W6-C1 (E7): the daemon-client credential STATUS read (secret-free, honest-degrade).
59
+ // The daemon-client credential STATUS read (secret-free, honest-degrade).
60
60
  // Value reads above stay local/env; only the status VISIBILITY path moves to the daemon.
61
61
  export {
62
62
  deriveCredentialAvailability,
@@ -16,7 +16,7 @@ import {
16
16
  import { isSecretRefInput } from '@pellux/goodvibes-sdk/platform/config';
17
17
  import { GOODVIBES_AGENT_SURFACE_ROOT } from './surface.ts';
18
18
 
19
- // W6-C1 host-vs-client split (E7 config sharing): this SecretsManager is the LOCAL-HOST
19
+ // Host-vs-client split: this SecretsManager is the LOCAL-HOST
20
20
  // read path — pinned to GOODVIBES_AGENT_SURFACE_ROOT, it resolves secret VALUES from the
21
21
  // surface store/env for provider auth, unchanged. When the Agent acts as a CLIENT of an
22
22
  // adopted external daemon, credential *status* (configured/usable — never bytes) is read
@@ -123,8 +123,8 @@ export function renderConversationAssistantMessage(
123
123
  // `numWidth=6` (fits 999,999 lines, but wastes 3-4 gutter columns on typical
124
124
  // messages) or rendering the numbered output into a scratch buffer and trimming.
125
125
  // Neither is clearly better than the current two-pass measurement approach.
126
- // The commit message claim that this "eliminates double-parse when line
127
- // numbers are enabled" was inaccurate: eliminated the legacy
126
+ // An earlier commit message's claim that this "eliminates double-parse when line
127
+ // numbers are enabled" was inaccurate: that commit eliminated the legacy
128
128
  // `renderMarkdown()` duplicate used for code-block line-number mode ('code').
129
129
  // The 'all' mode double-call is a deliberate design choice and remains unchanged.
130
130
  const measureWidth = showAllLineNumbers ? width : 0;
@@ -9,7 +9,7 @@
9
9
  * Ported from the TUI (src/core/system-message-noise.ts). The TUI regexes are
10
10
  * kept VERBATIM (provider-replay fold / agents-snapshot drop / stale-replay
11
11
  * drop); the only agent-specific addition is the `[Terminal] Captured …` rule
12
- * (W4-R2, absorbing A8 papercut #3 — the stdout-capture leak). Dropped noise is
12
+ * (the stdout-capture leak). Dropped noise is
13
13
  * drop-from-the-feed, NOT delete: the captured-write detail stays reachable via
14
14
  * the activity log (the terminal-output guard logs each intercept + the count).
15
15
  */
@@ -46,7 +46,7 @@ const REPLAY_CHAIN_RE = /WRFC chain (\S+) transitioned .* waiting for action/;
46
46
 
47
47
  /**
48
48
  * Matches the terminal-output guard's aggregate captured-write notice
49
- * (W4-R2, agent-specific). First-run plumbing writes a burst of direct stdout
49
+ * (agent-specific). First-run plumbing writes a burst of direct stdout
50
50
  * that the guard intercepts and would otherwise summarize into the Recent feed;
51
51
  * the count stays reachable in the activity log, so the feed copy is dropped.
52
52
  */
@@ -57,7 +57,7 @@ const TERMINAL_CAPTURED_RE = /^\[Terminal\] Captured \d+ direct /;
57
57
  * lookup, so it is trivially testable.
58
58
  */
59
59
  export function classifyNoise(message: string, deps: NoiseGateDeps): NoiseVerdict {
60
- // agent (W4-R2) — the terminal-output guard's aggregate captured-write notice.
60
+ // Agent-specific — the terminal-output guard's aggregate captured-write notice.
61
61
  // Kept out of the Recent feed; the detail stays in the activity log.
62
62
  if (TERMINAL_CAPTURED_RE.test(message)) {
63
63
  return DROP;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * thinking-overlay.ts (W4-R4) — the thinking-indicator overlay + its honest
2
+ * thinking-overlay.ts — the thinking-indicator overlay + its honest
3
3
  * stall clock, extracted from main.ts's render loop.
4
4
  *
5
5
  * The SDK orchestrator surfaces no lastDeltaAtMs / reconnect signal directly, so
@@ -42,7 +42,7 @@ function unconfirmed(editor: AgentWorkspaceLocalEditor, message: string, status:
42
42
  /**
43
43
  * The submission data table for the kinds this module builds itself (delegate-task and
44
44
  * workplan/notify/secret/profile kinds keep dispatching to their own sibling submission
45
- * modules below, unchanged). W4-H2: split out of the single ~570-line
45
+ * modules below, unchanged). Split out of the single ~570-line
46
46
  * `buildAgentWorkspaceBasicCommandEditorSubmission` if-chain, mirroring the
47
47
  * construction-side split in agent-workspace-basic-command-editors.ts.
48
48
  */
@@ -127,7 +127,7 @@ function modelPinUnpinSpec(kind: AgentWorkspaceBasicOwnCommandEditorKind): Agent
127
127
 
128
128
  /**
129
129
  * The field-spec data table for the kinds this module builds itself (the rest are
130
- * delegated to sibling domain modules above). W4-H2: split out of the single
130
+ * delegated to sibling domain modules above). Split out of the single
131
131
  * ~600-line `createAgentWorkspaceBasicCommandEditor` if-chain into a data table, the
132
132
  * same shape used by every other agent-workspace command-editor domain.
133
133
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Calendar connect card (W4-A5) — promotes the "Calendar workflows" workspace
2
+ * Calendar connect card — promotes the "Calendar workflows" workspace
3
3
  * card from a dead guidance card into a real, dispatchable action.
4
4
  *
5
5
  * GROUNDED: unlike email, there is no external calendar account/CalDAV
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Calendar OAuth advanced-credentials wizard (W4-A10).
2
+ * Calendar OAuth advanced-credentials wizard.
3
3
  *
4
4
  * The DEFAULT connect experience needs no card at all: `/calendar connect google`
5
5
  * (or `outlook`) uses the bundled project client id + PKCE and opens the browser.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Calendar subscribe wizard (W4-A9) — the "Calendar workflows" card's real
2
+ * Calendar subscribe wizard — the "Calendar workflows" card's real
3
3
  * connect flow. Subscribes to an external calendar by its iCalendar feed URL
4
4
  * (Google "secret address", Outlook published .ics, or any .ics URL), READ-ONLY.
5
5
  *