Preview — /opt/jfmsrv01/scripts/CHANGELOG.md

/opt/jfmsrv01/scripts/CHANGELOG.md

## 2026-05-29 - GoSeek AI Workbench + aiepyc01

### Added
- aiepyc01: New Ubuntu 24.04 VM on EPYC ESXi, 60 vCPU, 280GB RAM
- aiepyc01: Ollama 0.24.0 installed, listening on 10.133.133.2:11434
- aiepyc01: llama3.3:70b and llama3.2:3b models installed
- jfmsrv01: Second NIC (ens192) added, 10.133.133.1/24, direct link to aiepyc01
- GoSeek: New Laravel/Filament AI workbench at /var/www/goseek port 8090
- GoSeek: 10 AI providers configured (Ollama, Anthropic, OpenAI, Google, Deepseek, Kimi, Groq, Mistral, xAI, Cohere)
- GoSeek: Tool engine (read files, run commands, logs, database queries, Ollama management)
- GoSeek: Groq API key configured and working (248ms response time)
- GoSeek: AI Provider management UI with encrypted key storage
- GoSeek: Full screen chat interface

### Architecture
- Direct 10.133.133.x network for AI traffic bypasses Untangle
- API keys encrypted with Laravel encrypt() - never plaintext in DB

## 2026-05-30 - Repair GoSeek AI Provider form namespace

### Fixed
- Repaired GoSeek AI Provider Filament resource after the API key save patch caused a class namespace error.
- Form input components such as `TextInput` now use the Filament Forms component namespace instead of the Filament Schemas namespace.
- Confirmed Groq's existing API key remains stored and reports as encrypted without exposing the key value.

### Changed
- Confirmed this server now uses the generic `/opt/jfmsrv01/scripts/` handover workflow, not the old `/opt/legaltranscribe/scripts/` path.

## 2026-05-30 - Fix GoSeek external provider key saving and selection

### Fixed
[REDACTED SECRET-LIKE LINE]
- AI Provider create/edit pages now preserve existing keys when the field is blank and pass new key input to the model mutator.
- API key input is dehydrated only when filled, preventing blank edits from wiping existing keys.
- Provider selector now returns enabled providers that are local or have a stored key.

### Security
- API keys are still never pre-filled into the browser.
- Verification reports only `empty`, `encrypted`, or `legacy_or_invalid`; it does not print key values.

[REDACTED SECRET-LIKE LINE]

### Fixed
[REDACTED SECRET-LIKE LINE]
- `AiProvider: [REDACTED]
- Edit form blanks the API key field before display so stored keys are never sent back to the browser.
- Blank key field on edit keeps the existing encrypted key.
- Provider selector continues to list only enabled providers that are local or have a stored key.

### Validation
- Model save was tested inside a rolled-back transaction.
- The test confirmed `enabled=yes`, encrypted key status, and successful decrypt match without persisting or printing a real key.

## 2026-05-30 - Add OpenAI model options for GoSeek selector

### Fixed
- Added selectable OpenAI model options when the OpenAI provider has no models configured.
- Updated GoSeek provider API output to return enabled local providers or enabled keyed external providers with model lists.
- Updated `AiProviderSeeder` so OpenAI is no longer reseeded with an empty model list.

### Validation
- `/chat-api/providers` was checked after cache clear.
- Verification output reports provider visibility and model counts only; it does not print API keys.

## 2026-05-30 - Complete GoSeek provider dropdown loading fix

### Fixed
- Completed the provider dropdown repair after the first patch script stopped on a Python regex escaping error.
- Patched `ChatController::models()` safely.
- Ensured `ProviderRouter::all()` uses normalised model options.
- Normalised existing provider model data so `/chat-api/providers` no longer fails when models are stored as strings.

### Validation
- PHP lint passed.
- Direct `ProviderRouter::all()` was checked.
- `/chat-api/providers` was checked for HTTP 200.

## 2026-05-30 - Fix GoSeek provider classification and OpenAI visibility

### Fixed
- Normalised GoSeek provider records so only Ollama is treated as local.
- Cloud providers are now classified as cloud/external.
- OpenAI is enabled automatically when a saved key is present.
- Provider API now strictly returns Ollama as local and keyed external providers as cloud.
- Confirmed provider API returns JSON after cache clear.

### Security
- No API key values are printed or published; checks only show key status.

## 2026-05-30 - Securely set GoSeek OpenAI provider

### Fixed
- OpenAI provider was not visible in the GoSeek selector because it was not passing the enabled/keyed provider filter.
- OpenAI provider was securely set using a hidden terminal prompt.
- OpenAI is now classified as cloud, enabled, keyed, and configured with selectable models.

### Security
- The OpenAI API key was not printed to the terminal, handover, changelog, or chat.
- Verification output reports only key status, not key value.

## 2026-05-30 - Refresh jfmsrv01 handoff and publish PHP source

- Replaced stale transcribe01/legaltranscribe wording with current jfmsrv01 generic server layout.
- Updated workflow paths to /opt/jfmsrv01/scripts.
- Documented mainsite, admin, GoSeek and handoff portal.
- Published first-party PHP source browsers for active development inspection.
- Excluded .env, vendor, node_modules, storage logs/cache, sessions and private files.

## 2026-05-30 - Fix handoff aliases and add fresh run publishing

### Fixed
- Non-slug aliases such as /server/HANDOVER.html now read from the canonical slug tree instead of stale root-level files.
- Added no-cache headers to the handoff HTTPS vhost.
- Redirected the accidental missing-v slug to the canonical slug.

### Added
- Added /opt/jfmsrv01/scripts/publish_fresh_handoff_run.sh.
- Each fresh publish creates /runs/<timestamp>/ so ChatGPT/browser inspection can use a new URL and avoid stale cache.

## 20260530-160357 - Publish fresh handoff run

### Changed
- Published unique cache-busting handoff run: runs/20260530-160357/
- Updated latest-run pointers.
- Added fresh run links to the canonical handoff index.

### URLs
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260530-160357/
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260530-160357/server/HANDOVER.html
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260530-160357/source/goseek/index.html

## 2026-05-30 - Fix GoSeek AI Provider API key saving through the UI

### Fixed
[REDACTED SECRET-LIKE LINE]
  dehydrated(false) won, so the field was stripped from the form payload and
  the Create/Edit page mutators never received it. No API key entered in the
  UI was ever persisted.
[REDACTED SECRET-LIKE LINE]
  encrypted key via the page mutators. This also restores cloud provider
  visibility in the chat selector, since ProviderRouter::all() requires a key.

### Security
- API keys remain encrypted at rest and are never pre-filled into the browser,
  printed, logged, or published.

## 2026-05-31 - GoSeek ssh_exec build capability

### Added
- GoSeek ToolEngine: new ssh_exec tool, locked to a single build host
  defined in /etc/goseek/build_target.php (outside the webroot).
- Dedicated ed25519 build keypair in /etc/goseek (root-owned, group-read
  for the GoSeek runtime user only; never published to the handoff portal).

### Security
- ssh_exec cannot target any host other than the one in build_target.php.
- Build key should be restricted on the target with from="<jfmsrv01-ip>".
- Build target is an isolated, rebuildable VM; access to be re-scoped once
  the gateway is deployed.

## 2026-05-31 - GoSeek ssh_exec known_hosts cleanup
### Fixed
- ssh_exec now uses /etc/goseek/known_hosts (writable by www-data), removing
  the "Could not create /var/www/.ssh" warning and pinning the build host
  key after first connect.
- Reloaded PHP-FPM after editing ToolEngine; optimize:clear alone does not
  flush opcache.

## 2026-06-02 - AI Gateway + GoSeek Site Tools (major session)

### Added — llmgateway (192.168.100.110)
- New Ubuntu 24.04.4 VM: AI Gateway, dedicated and isolated
- Custom Laravel app at /var/www/gateway, port 8095, Filament admin
- POST /v1/chat/completions — OpenAI-compatible inbound API
[REDACTED SECRET-LIKE LINE]
- Provider routing with encrypted key storage (Laravel encrypt())
- 7 providers seeded: Ollama, DeepSeek, OpenAI, Anthropic, Groq, Google, Kimi
[REDACTED SECRET-LIKE LINE]
- Rules engine: immutable rules (/etc/gateway/rules.immutable.php, root-owned)
  + editable DB rules via Filament UI, fail-closed, default-allow-with-deny-rules
- Budget enforcement (daily/monthly, per-client or global, deny or hold)
- Decision logging (every request evaluated and logged)
[REDACTED SECRET-LIKE LINE]
- Spend dashboard: per-client, per-provider, per-model, per-day, recent requests
- Filament resources: Providers, Models, Clients, Rules, Budgets (all with delete)
- /health endpoint for liveness checks
- Phase 1 hardening: ufw (SSH + 8095 from LAN), timezone Australia/Perth
- ESXi snapshot taken before build

### Added — jfmsrv01 (GoSeek improvements)
[REDACTED SECRET-LIKE LINE]
- GoSeek ssh_exec tool: locked to one build host via /etc/goseek/build_target.php
- Dedicated ed25519 build keypair in /etc/goseek/ (root-owned, outside webroot)
- GoSeek clone_website tool: dual-mode (quick=wget, deep=httrack), browser UA
- GoSeek scan_site tool: crawls local clone, reports broken links + missing resources
- GoSeek fix_site_links tool: bulk find-and-replace across HTML/CSS/JS
- GoSeek serve_site tool: creates nginx vhost for cloned site (narrow sudo for nginx ops)
- GoSeek auto_fix: downloads missing resources from original site
- GoSeek AI Clone: clones site then sends each page through gateway for AI-powered link fixing
- Sites Manager admin page: Clone (quick/deep/AI), Scan, Auto Fix, Manual Fix, Serve, Preview, Delete
- Tools admin page: lists all 16+ tools with usage stats from tool_calls_log
- Sites preview nginx vhost on port 9090 (autoindex /var/www/sites/)
- Narrow sudoers for www-data: nginx test/reload/vhost-write only
- GoSeek gateway provider configured: routes all AI through the gateway
- httrack installed for deep website cloning

### Architecture decisions
- Gateway on dedicated VM for isolation (RULE D1)
- OpenAI-compatible API shape so clients just change base_url at cutover
- Immutable rules in root-owned file: enforcement below the model layer
- Fail-closed: engine/DB error → deny (no ungoverned requests)
[REDACTED SECRET-LIKE LINE]
- Decimal(12,6) for cost columns (exact, no floating-point drift)
- DeepSeek + Kimi at privacy tier 3 (China-based data routing)
- GoSeek ssh_exec key restricted with from= to jfmsrv01 IP only
- HTTrack for deep clones; wget for quick clones; AI for smart clones

### Known issues / incomplete
- Untangle egress lock not yet done (gateway works but bypass still possible)
- GoSeek direct providers not yet disabled (cutover step 2 pending)
[REDACTED SECRET-LIKE LINE]
- Anthropic adapter not built (API not OpenAI-shaped)
- Streaming not supported on gateway endpoint
- Ollama shelved until GPU available; not reachable from llmgateway
- GoSeek models_json UI field still broken (models set via tinker)
- Per-client provider allow-list not built (planned Phase 8c)
- Budget daily-reset not implemented (spent_amount accumulates)
- GoSeek ToolEngine input validation weak (models name args differently)
- Builder sudo on llmgateway to be tightened after build complete
- WordPress backup import feature planned
- Hosting packages (domains, SSL, DB, email) planned

## 20260602-084132 - Publish fresh handoff run

### Changed
- Published unique cache-busting handoff run: runs/20260602-084132/
- Updated latest-run pointers.
- Added fresh run links to the canonical handoff index.

### URLs
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260602-084132/
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260602-084132/server/HANDOVER.html
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260602-084132/source/goseek/index.html

## 20260602-144040 - Publish fresh handoff run

### Changed
- Published unique cache-busting handoff run: runs/20260602-144040/
- Updated latest-run pointers.
- Added fresh run links to the canonical handoff index.

### URLs
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260602-144040/
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260602-144040/server/HANDOVER.html
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260602-144040/source/goseek/index.html

## 2026-06-02 (PM) - GoSeek source browser, AI site editing, gateway /v1 fix

### Added
- publish_goseek_source.sh: regenerates the GoSeek first-party PHP source browser
  (app, routes, config, database, resources/views) from LIVE /var/www/goseek, with
[REDACTED SECRET-LIKE LINE]
  step. Root cause of prior staleness: nothing regenerated source/goseek; the wrapper
  only copied a frozen 2026-05-30 artifact forward.
- GoSeek ToolEngine: ai_edit_site (apply a natural-language instruction to every HTML
  page of a cloned site via the gateway; backs up originals; dry_run previews one page;
  truncation guard keeps original if output < 40% of source).
- GoSeek ToolEngine: restore_site_backup (revert a site from an ai_edit_site run).
- GoSeek SitesManager + blade: "AI Edit" panel (instruction, model picker, path filter,
  page cap, Preview / Apply / Revert).

### Fixed
- Gateway endpoint path: GoSeek called <base_url>/chat/completions (404). Correct path is
  /v1/chat/completions. Fixed in new gatewayEndpoint() and pre-existing aiCloneSite().
- publish_handoff.sh: added missing shebang (was falling back to dash -> pipefail error);
  removed stray installer leftover lines (PUBLISHEOF + self-chmod) at EOF.

### Known issues / next
- ai_edit_site backups live under /var/www/sites/.backups/, which refreshSites() lists as
  a bogus "site". TODO: move to /var/www/site-backups/, migrate existing, skip dot-dirs.
- ai_edit_site is single-shot full-page rewrite: unsafe for cosmetic changes (redraws whole
  page). Use CSS injection for style; structural edits ("add contact form") and shared-template
  propagation need an agentic multi-step loop in ChatService (currently single-shot tool use).

## 2026-06-03 (PM session 2) - GoSeek agentic system (agent loop + durable queue + worker)

### Added — agentic GoSeek
- ChatService now runs a BOUNDED MULTI-STEP AGENT LOOP (runAgent): model -> tool
  -> feed result back -> model, until a turn has no <tool_call> or the step cap
  is hit. Cap = config('goseek.agent_max_steps', 8). Previously single-shot.
- Durable runs: agent_runs table + AgentRun model + RunAgentJob (queued).
  Long tasks run in a worker, not the HTTP request, so they can't time out.
- Dedicated 'agent' queue connection in config/queue.php (driver=database,
  retry_after=3600 — MUST stay greater than the job timeout or runs relaunch).
- Async chat path: POST /chat-api/conversations/{id}/chat-async creates the user
  message + an AgentRun and dispatches RunAgentJob; GET /chat-api/runs/{id}
  returns status/steps/result. Chat blade dispatches then POLLS, streaming each
  tool step live. The old synchronous /chat endpoint still exists but the UI no
  longer calls it.
- systemd worker: goseek-agent-worker.service runs
  'queue:work agent --queue=agent --tries=1 --timeout=1800 --max-time=3600'
  as www-data. Enabled at boot.

### Added/Fixed earlier this session (if not already logged above)
- publish_goseek_source.sh: regenerates GoSeek source browser from LIVE app, wired
  into publish_fresh_handoff_run.sh. (Fixes stale-source problem.)
- ToolEngine: ai_edit_site / restore_site_backup (bulk AI edit of cloned sites,
  backups + dry-run + truncation guard). Backups now under /var/www/site-backups/.
- Gateway endpoint fixed to /v1/chat/completions (gatewayEndpoint + aiCloneSite).
- publish_handoff.sh: added shebang, removed stray installer leftover lines.

### OPERATIONAL — READ BEFORE EDITING GoSeek CODE
- The worker holds PHP code IN MEMORY. After ANY change to ChatService, ToolEngine,
  ProviderRouter, providers, or models, you MUST restart it or it runs stale code:
      systemctl restart goseek-agent-worker      (or: php artisan queue:restart)
- Worker status / logs:
      systemctl status goseek-agent-worker
      journalctl -u goseek-agent-worker -f
- Raise agent step budget: set GOSEEK_AGENT_MAX_STEPS in .env (config goseek.agent_max_steps).
- Stuck run: rows in agent_runs left 'running' after a worker kill are orphans
  (tries=1, won't retry). Safe to mark failed/delete.

### Next
- Anthropic gateway adapter (enables Claude-model as reviewer in builder/reviewer pattern).
- Site-scoped tools (list_site_files/read_site_file) to stop raw find/permission noise.
- Cleaner agent context (don't bleed last-20 chat history into agent runs).

## 20260603-125356 - Publish fresh handoff run

### Changed
- Published unique cache-busting handoff run: runs/20260603-125356/
- Updated latest-run pointers.
- Added fresh run links to the canonical handoff index.

### URLs
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260603-125356/
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260603-125356/server/HANDOVER.html
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260603-125356/source/goseek/index.html

## 2026-06-03 — Wire GOSEEK_AGENT_MAX_STEPS into config
- config/goseek.php now defines 'agent_max_steps' => (int) env('GOSEEK_AGENT_MAX_STEPS', 8).
  The key was previously absent, so the documented .env override was a no-op and the
  step cap silently defaulted to 8. The env knob now works as documented.
- Cleared config cache; restarted goseek-agent-worker. Backup: /var/www/goseek/config/goseek.php.bak.20260603-135252

## 20260603-135253 - Publish fresh handoff run

### Changed
- Published unique cache-busting handoff run: runs/20260603-135253/
- Updated latest-run pointers.
- Added fresh run links to the canonical handoff index.

### URLs
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260603-135253/
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260603-135253/server/HANDOVER.html
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260603-135253/source/goseek/index.html

## 2026-06-03 23:04 AWST - GoSeek chat full-width fix
- chat.blade.php: released Filament width cap (.fi-main/.fi-main-ctn/.fi-page -> 100%).
  Page was previously centred in a max-width column on wide screens.
- Blade-only; ran 'php artisan view:clear'. No goseek-agent-worker restart required.
- Backup: /var/www/goseek/resources/views/filament/pages/chat.blade.php.bak-20260603-230420

## 20260603-230421 - Publish fresh handoff run

### Changed
- Published unique cache-busting handoff run: runs/20260603-230421/
- Updated latest-run pointers.
- Added fresh run links to the canonical handoff index.

### URLs
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260603-230421/
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260603-230421/server/HANDOVER.html
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260603-230421/source/goseek/index.html

## 2026-06-03 23:10 AWST - GoSeek full-screen launcher
- chat.blade.php (Filament page): added topbar "Full screen" link to standalone /chat.
- Blade-only; ran 'php artisan view:clear'. No goseek-agent-worker restart.
- Note: /chat still uses the synchronous /chat endpoint (not /chat-async). Modernisation pending.
- Backup: /var/www/goseek/resources/views/filament/pages/chat.blade.php.bak-20260603-231049

## 20260603-231049 - Publish fresh handoff run

### Changed
- Published unique cache-busting handoff run: runs/20260603-231049/
- Updated latest-run pointers.
- Added fresh run links to the canonical handoff index.

### URLs
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260603-231049/
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260603-231049/server/HANDOVER.html
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260603-231049/source/goseek/index.html

## 2026-06-03 23:33 AWST - GoSeek /chat ported to async agent flow
- chat.blade.php: sendMessage() now POSTs /chat-async and polls /runs/{id} via new pollRun().
- Spinner shows live "Step N: tool" progress; 30-min poll cap matches the Filament page.
- Blade-only; ran 'php artisan view:clear'. No goseek-agent-worker restart.
- Backup: /var/www/goseek/resources/views/chat.blade.php.bak-20260603-233326

## 20260603-233326 - Publish fresh handoff run

### Changed
- Published unique cache-busting handoff run: runs/20260603-233326/
- Updated latest-run pointers.
- Added fresh run links to the canonical handoff index.

### URLs
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260603-233326/
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260603-233326/server/HANDOVER.html
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260603-233326/source/goseek/index.html

## 2026-06-03 23:33 AWST - Internal quick-links dashboard
- New GoSeek route /links -> resources/views/links.blade.php (served on :8090).
- Launcher for mainsite, admin, GoSeek (chat/full-screen/providers), gateway, previews, handoff.
- Web route only; cleared view + route caches. No worker restart.

## 20260603-233345 - Publish fresh handoff run

### Changed
- Published unique cache-busting handoff run: runs/20260603-233345/
- Updated latest-run pointers.
- Added fresh run links to the canonical handoff index.

### URLs
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260603-233345/
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260603-233345/server/HANDOVER.html
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260603-233345/source/goseek/index.html

## 2026-06-04 01:37 AWST - GoSeek delete chats
- chat.blade.php: per-conversation delete (x) button in the /chat sidebar.
- Calls existing DELETE /chat-api/conversations/{id} (soft-delete). Confirm dialog; resets view if active chat deleted.
- Blade-only; ran 'php artisan view:clear'. No goseek-agent-worker restart.
- Backup: /var/www/goseek/resources/views/chat.blade.php.bak-20260604-013743

## 20260604-013743 - Publish fresh handoff run

### Changed
- Published unique cache-busting handoff run: runs/20260604-013743/
- Updated latest-run pointers.
- Added fresh run links to the canonical handoff index.

### URLs
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260604-013743/
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260604-013743/server/HANDOVER.html
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260604-013743/source/goseek/index.html

## 2026-06-04 01:50 AWST - GoSeek website orchestration
- ToolEngine: + vm_write_file, + publish_build (rsync build VM dist -> /var/www/sites/<slug>, then serve_site).
- ChatService: system prompt gained the from-scratch website build pipeline (full-auto on build VM).
- No new sudo: reuses serve_site allowlist + build SSH key. Restarted goseek-agent-worker.

## 20260604-015013 - Publish fresh handoff run

### Changed
- Published unique cache-busting handoff run: runs/20260604-015013/
- Updated latest-run pointers.
- Added fresh run links to the canonical handoff index.

### URLs
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260604-015013/
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260604-015013/server/HANDOVER.html
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260604-015013/source/goseek/index.html

## 2026-06-04 01:51 AWST - GoSeek Projects (backend)
- New projects table + conversations.project_id FK (legacy 'project' string kept).
- Project model, ProjectController CRUD, chat-api /projects routes.
- ChatController: conversations filter by project_id; create accepts project_id.
- Website projects get workspace_path = goseek.build_workspace/<slug> (build VM).
- Ran migrate; restarted goseek-agent-worker. UI switcher is the next patch.

## 20260604-015132 - Publish fresh handoff run

### Changed
- Published unique cache-busting handoff run: runs/20260604-015132/
- Updated latest-run pointers.
- Added fresh run links to the canonical handoff index.

### URLs
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260604-015132/
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260604-015132/server/HANDOVER.html
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260604-015132/source/goseek/index.html

## 2026-06-04 01:51 AWST - GoSeek website orchestration
- ToolEngine: + vm_write_file, + publish_build (rsync build VM dist -> /var/www/sites/<slug>, then serve_site).
- ChatService: system prompt gained the from-scratch website build pipeline (full-auto on build VM).
- No new sudo: reuses serve_site allowlist + build SSH key. Restarted goseek-agent-worker.

## 20260604-015159 - Publish fresh handoff run

### Changed
- Published unique cache-busting handoff run: runs/20260604-015159/
- Updated latest-run pointers.
- Added fresh run links to the canonical handoff index.

### URLs
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260604-015159/
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260604-015159/server/HANDOVER.html
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260604-015159/source/goseek/index.html

## 2026-06-04 02:00 AWST - GoSeek Projects UI
- chat.blade.php: sidebar project switcher (dropdown + create), conversation filter by project,
  new chats inherit selected project, website projects open a chat with a prefilled build prompt.
- Blade-only; ran 'php artisan view:clear'. No worker restart.
- Backup: /var/www/goseek/resources/views/chat.blade.php.bak-20260604-020027

## 20260604-020027 - Publish fresh handoff run

### Changed
- Published unique cache-busting handoff run: runs/20260604-020027/
- Updated latest-run pointers.
- Added fresh run links to the canonical handoff index.

### URLs
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260604-020027/
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260604-020027/server/HANDOVER.html
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260604-020027/source/goseek/index.html

## 2026-06-04 11:31 AWST - GoSeek login redirect fix
- chat.blade.php loadProviders(): redirect on auth failure /login -> /admin/login (no /login route existed).
- Blade-only; ran 'php artisan view:clear'.
- Backup: /var/www/goseek/resources/views/chat.blade.php.bak-20260604-113130

## 20260604-113130 - Publish fresh handoff run

### Changed
- Published unique cache-busting handoff run: runs/20260604-113130/
- Updated latest-run pointers.
- Added fresh run links to the canonical handoff index.

### URLs
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260604-113130/
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260604-113130/server/HANDOVER.html
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260604-113130/source/goseek/index.html

## 20260604-121407 - Publish fresh handoff run

### Changed
- Published unique cache-busting handoff run: runs/20260604-121407/
- Updated latest-run pointers.
- Added fresh run links to the canonical handoff index.

### URLs
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260604-121407/
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260604-121407/server/HANDOVER.html
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260604-121407/source/goseek/index.html


<!-- SPLICEVPN-HANDOVER-CHANGELOG-START -->

## 2026-06-09 — SpliceVPN handover update

- Added SpliceVPN dedicated handover from `/opt/splicevpn/HANDOVER.md`.
- Published HTML and Markdown copies into the public handoff area.
- Documented hub-and-spoke relay architecture, coordinator, hub, agent, firewall rules, paths, status, tests, and MVP limitations.
- Recorded outstanding work:
  - two-machine overlay ping test;
  - public website wording correction;
  - refresh Windows ZIP and Linux tarball;
[REDACTED SECRET-LIKE LINE]
  - add authentication to handoff site.
<!-- SPLICEVPN-HANDOVER-CHANGELOG-END -->

## 2026-06-09 — SpliceVPN handoff pack

- Added proper SpliceVPN section to public handoff portal.
- Added HTML-rendered SpliceVPN handover, file tree, source browser, downloads inventory, and service status.
- Added publisher hook so future handoff publishes can re-add the SpliceVPN section after the main generated index is rebuilt.
[REDACTED SECRET-LIKE LINE]


## 20260609-124454 — Complete fresh handoff V2

Generated controlled complete handoff pack:

- `complete-handoff-v2-20260609-124454/index.html`
- `complete-handoff-v2-20260609-124454/all-links.html`
- `complete-handoff-v2-20260609-124454/new-chat-start.html`
- `complete-handoff-v2-20260609-124454/recent-work-since-20260604.html`

[REDACTED SECRET-LIKE LINE]