Phases
Render this plan ticket as a navigable HTML site at a dedicated URL. Serves as the master reference/process/guide for the entire build. Redeployed after each phase close so status reflects reality. Living document, not a snapshot.
Create
-
C:/MHS/tools/render_plan.py
Std-lib Python renderer. Reads the v1.7 JSON ticket; emits a single self-contained HTML page with TOC, phase cards (status badges, objective, artifacts, ordered tasks, verification, five-field), doctrinal framing cards, lineage list, architecture summary, open-questions panel, hascom-integration section, chain-link footer. Dark Weyland aesthetic; anchor-linked phases; print + mobile friendly.
-
C:/MHS/.hascom_deploy/weyland-plan/index.html
Rendered plan output. Single file, no JS dependencies, cacheable.
-
Cloudflare Pages project: weyland-plan
Dedicated Pages project hosting the rendered plan. Independent of weyland-onamerica deployment so plan-site changes never risk the venture.
Tasks
- [0.1] Author tools/render_plan.py — std-lib only; reads CH-2026-0507-WEYLAND-001 JSON; emits index.html
- [0.2] Render plan: python tools/render_plan.py hascom/tickets/CH-2026-0507-WEYLAND-001_*.json .hascom_deploy/weyland-plan/index.html
- [0.3] Deploy: wrangler pages deploy .hascom_deploy/weyland-plan --project-name=weyland-plan --branch=production
- [0.4] Verify: curl <pages-url>; visual check in browser; confirm all 10+1 phases visible, anchor links work, status badges render
- [0.5] Record live URL in this ticket's hascom_integration block
- [0.6] Commit: 'feat(plan): Phase 0 — render+deploy CH-0507 plan to dedicated reference site'
Verification
Plan URL returns 200 in browser; plan content matches JSON ticket; per-phase anchors navigate correctly; status badges reflect current phase states.
Five-Field
- status target
- Plan published to dedicated URL; living-document workflow established (re-render + re-deploy on each phase close)
- artifacts
- tools/render_plan.py (~300 lines std-lib Python), rendered HTML, CF Pages project
- testing
- Browser smoke (visual check); curl 200 verification
- dependencies
- wrangler installed; CF account credentials available (use existing onamerica account)
- issues
- None projected — std-lib renderer is straightforward; CF Pages deploy is a one-line wrangler command
Replace the 'images TBD' return path in dispatch_claude_code with a working image+document handler that subprocesses claude CLI in headless read-only mode.
blocks: phase 2, 6, 7
Modify
-
C:/MHS/workers/weyland-bridge/weyland-bridge.py
lines: 175-238 (dispatch_claude_code function)
Rewrite to handle image and document content blocks per Section B. Add base64/tempfile/shutil imports. Per-job tempdir under tempfile.mkdtemp(prefix='weyland-job-'); write each blob as page-NNN.<ext>; build prompt = concatenated text + file references; subprocess.run(['claude', '--print', '--permission-mode', 'bypassPermissions', '--allowed-tools', 'Read,Grep,Glob', '--output-format', 'text', '--add-dir', workdir, '-p', prompt], timeout=300); cleanup in try/finally; wrap stdout as Anthropic Messages-shape result.
Create
-
C:/MHS/workers/weyland-bridge/test_vision_adapter.py
Std-lib unittest. Mocks subprocess.run; asserts: (a) image blocks decoded and written to tempdir; (b) tempdir included via --add-dir; (c) prompt references file paths; (d) tempdir cleaned on success AND on subprocess error; (e) result wraps stdout in correct shape.
Tasks
- [TDD-1.1] Write test_image_block_writes_to_tempdir failing test — assert subprocess called with --add-dir matching a real path, file at <tmp>/page-001.png exists at call time
- [TDD-1.2] Implement image-block extraction loop: parse messages, decode base64, write to tempdir, collect paths
- [TDD-1.3] Run test — verify pass
- [TDD-1.4] Write test_subprocess_args_match_design failing test — assert claude invoked with bypassPermissions + Read,Grep,Glob + text output format
- [TDD-1.5] Implement subprocess invocation with the documented flags
- [TDD-1.6] Run test — verify pass
- [TDD-1.7] Write test_tempdir_cleaned_on_error — assert shutil.rmtree called even when subprocess raises
- [TDD-1.8] Implement try/finally cleanup; verify pass
- [TDD-1.9] Write test_response_shape_matches_anthropic_messages — assert returned dict has success/result.content[0].text/provider_path/latency_ms keys
- [TDD-1.10] Implement response wrapping; verify pass
- [TDD-1.11] Manual smoke test: run weyland-bridge.py with WEYLAND_PROVIDER=claude_code, queue a real PDF page job via local hascom-edge dev (or mock), verify claude CLI invoked and returned JSON
- [TDD-1.12] Update agent/PROVIDERS.md doc with vision-capable claude_code adapter description
- [TDD-1.13] Commit: 'feat(bridge): claude_code adapter handles image and document content blocks'
Verification
All test_vision_adapter.py tests pass. Manual smoke test against weyland-onamerica-staging: queue an image-bearing job; agent picks up; claude CLI processes; result returns through SABP without 'images TBD' error.
Five-Field
- status target
- Vision adapter complete; agent ready for cloud bridge AND local sidecar reuse
- artifacts
- weyland-bridge.py (modified ~80 lines), test_vision_adapter.py (new), PROVIDERS.md (updated)
- testing
- Unit (5 tests, std-lib unittest, mocked subprocess) + manual smoke against staging
- dependencies
- claude CLI on test box; staging hascom-edge reachable; staging weyland reachable
- issues
- None projected; subprocess mocking is std-lib unittest.mock
Make the affirmation-gate route choice actually drive extraction. Hoist shared logic. Add async lifecycle. Apply §4a token boundary with graceful PASETO/JWT fallback.
depends on: phase 1 · blocks: phase 3, 7
Modify
-
C:/MHS/PAD_backup/PrecisionAutoDoors/forge/SubmittalExpressFoundry/SubmittalExpress/Phase2/Prototype1/weyland-worker.js
- Hoist EXTRACTION_PROMPT_TEMPLATE to module-level const (currently inline in processWithClaudeVision @780)
- Hoist parseAndPersistExtraction (extract from processWithClaudeVision body)
- Rename processWithClaudeVision → viaApiDirect; preserve behavior
- Add viaSabpClaudeCode per Section C.1
- Add viaLocalSubprocess per Section F.1 (registered only when env.WEYLAND_EDITION=='local')
- Add adaptersForEdition(env) helper
- Add dispatchVisionExtraction(sessionId, pdfBuffer, env, ctx)
- Update three call sites (L2641, L2738, L2941) to use dispatchVisionExtraction; handle {sync:false} response shape
- Add /api/sessions/:sessionId/finalize-from-job/:jobId route handler per Section C.2
- Wrap callEdge → introduce mintInternalToken helper per Section C.3 with PASETO-then-FLEET_API_KEY fallback and X-Surface header
- Update /api/version to return edition field (env.WEYLAND_EDITION || 'cloud')
-
C:/MHS/PAD_backup/PrecisionAutoDoors/forge/SubmittalExpressFoundry/SubmittalExpress/Phase2/Prototype1/wrangler-hascom.toml
Create
-
C:/MHS/.hascom_deploy/weyland-onamerica/worker/migrations/012_session_pending_job.sql
ALTER TABLE hardware_extraction_sessions ADD COLUMN pending_job_id TEXT; ALTER TABLE hardware_extraction_sessions ADD COLUMN pending_job_queued_at TEXT; ALTER TABLE hardware_extraction_sessions ADD COLUMN extraction_completed_at TEXT; CREATE INDEX IF NOT EXISTS hes_pending_job ON hardware_extraction…
Tasks
- [2.1] Hoist EXTRACTION_PROMPT_TEMPLATE → module const above processWithClaudeVision
- [2.2] Extract parseAndPersistExtraction → top-level async function; processWithClaudeVision calls it; verify no behavior change via existing tests
- [2.3] Rename processWithClaudeVision → viaApiDirect; update three call sites (L2641, L2738, L2941); deploy to staging; verify api_direct path still works
- [2.4] Commit: 'refactor(weyland): hoist prompt template + parser; rename processWithClaudeVision→viaApiDirect (no behavior change)'
- [2.5] Apply migration 012 to staging D1: wrangler d1 execute weyland-onamerica-staging --file=migrations/012_session_pending_job.sql --remote
- [2.6] Apply migration 012 to production D1 (same command, weyland-onamerica db)
- [2.7] Add adaptersForEdition + dispatchVisionExtraction; do NOT yet swap call sites — keep both old (viaApiDirect direct) and new (dispatch) reachable
- [2.8] Add viaSabpClaudeCode (cloud) and viaLocalSubprocess (local-only registration)
- [2.9] Add /api/sessions/:sessionId/finalize-from-job/:jobId handler
- [2.10] Add mintInternalToken; refactor callEdge to use it; emit X-Surface header on every internal call
- [2.11] Swap the three call sites to use dispatchVisionExtraction; on {sync:false} return 202 with poll/finalize URLs per Section C.2
- [2.12] Update /api/version to return edition field
- [2.13] Deploy to staging via wrangler deploy --config wrangler-hascom.toml --env staging
- [2.14] Verify staging: api_direct path returns sync result (regression check); claude_code_local path returns 202 + job_id (new behavior); /api/version reports edition=cloud
- [2.15] Commit: 'feat(weyland): edition-aware dispatcher + async extraction lifecycle + PASETO-internal mintInternalToken'
Verification
Staging probes (curl): (a) POST upload with route=api_direct → sync result with extraction; (b) POST upload with route=claude_code_local → 202 with job_id; (c) GET /api/version → edition=cloud; (d) X-Surface header present on internal calls in observability logs; (e) /api/sessions/:id/finalize-from-job/:jobId returns 425 Too Early when job not yet completed, then 200 once complete with extraction persisted.
Five-Field
- status target
- Worker-side wiring complete; cloud bridge edition end-to-end functional via staging
- artifacts
- weyland-worker.js (~250 lines added), migrations/012 (new), wrangler-hascom.toml (var update)
- testing
- Existing worker tests must pass (regression). Staging curl probes for new routes. End-to-end test with real bridge (Andrew's box, tomorrow on-site).
- dependencies
- Phase 1 Vision adapter merged so the bridge can actually return real extraction results when claude_code_local route is exercised
- issues
- PASETO mint endpoint may not yet be available in auth-onamerica binding — fallback path tagged X-Surface: internal-fallback-jwt. Migration 012 must run BEFORE deploy; cron sweep of orphaned pending_job_id rows is post-launch hardening.
SPA detects edition via /api/version, tailors affirmation gate to available routes, and handles 202 async response from upload handlers (poll job, then call finalize-from-job).
depends on: phase 2 · blocks: phase 9
Modify
-
C:/MHS/PAD_backup/PrecisionAutoDoors/forge/SubmittalExpressFoundry/SubmittalExpress/Phase2/Prototype1/deployment/public/subx.html
- At SPA bootstrap: fetch /api/version; store window.WEYLAND_EDITION ('cloud' | 'local')
- renderExtractionRouteGate (L15912): branch on edition — cloud shows api_direct + claude_code_local; local shows api_direct (BYO key) + claude_code_subprocess (RECOMMENDED)
- Upload handler client-side: when worker returns 202 with async:true + job_id + poll_url + finalize_url, enter polling state; render progress; on job.status==completed, POST finalize_url; render extraction results
Tasks
- [3.1] Add edition probe at SPA bootstrap; expose window.WEYLAND_EDITION
- [3.2] Refactor route option list in renderExtractionRouteGate to a routeOptionsForEdition(edition) helper
- [3.3] Add async-handling code path: if response.status===202 && body.async, start polling body.poll_url at 2s interval; show progress UI 'Your Claude Code is working on this PDF (NN seconds)'; on completion, POST body.finalize_url; on success, render result; on error, surface error
- [3.4] Commit: 'feat(spa): edition-aware affirmation gate + async extraction lifecycle handler'
- [3.5] Deploy SPA to staging Pages: wrangler pages deploy deployment/public --project-name=staging-onamerica-weyland --branch=staging
- [3.6] Manual test in browser against staging.weyland.onamerica.org: upload PDF, affirm claude_code_local route (with mock bridge or real one), watch poll progress, see extraction render
Verification
Manual browser walk-through against staging: (1) login → upload PDF → affirmation gate shows correct routes for cloud edition → affirm api_direct → sync result OK (regression). (2) Same flow, affirm claude_code_local → 202 → poll progress visible → completion → result rendered. (3) Visit /api/version → edition=cloud reflected in SPA chrome.
Five-Field
- status target
- SPA fully integrated with new dispatcher; cloud bridge edition end-to-end through browser
- artifacts
- subx.html (~150 lines modified)
- testing
- Manual browser test on staging. Cypress/Playwright not yet wired for this SPA; regression test discipline is currently human-walk-through.
- dependencies
- Phase 2 deployed to staging
- issues
- Polling at 2s may be too frequent for production; tune to 3-5s after Andrew's first session. Add exponential backoff on errors.
Stand up /padinstall as a JWT-gated landing page with device-authorization download flow. Bundle delivery is personalized (identity hints) but secret-free (no token in ZIP).
blocks: phase 5, 6, 9
Modify
-
C:/MHS/PAD_backup/PrecisionAutoDoors/forge/SubmittalExpressFoundry/SubmittalExpress/Phase2/Prototype1/weyland-worker.js
- Add GET /padinstall/bundle.zip handler — JWT-gated; fetches base ZIP from R2; rezips with .weyland/install-context.json (mhs_id, edge_url, weyland_origin, bundle_version, issued_at — NO TOKEN); streams response; X-Surface: external-jwt
- Add POST /api/install/device-auth/init — generate device_code (32 hex bytes), user_code (AB12-CD34 shape), insert install_device_auth row with TTL=600s, return {device_code, user_code, verification_uri, interval_seconds, expires_in}
- Add GET /api/install/device-auth/poll?device_code=... — read row; if expired, mark expired and return; if status==approved AND not consumed, mark consumed_at and return {status:approved, bridge_token}; else return {status:<current>}
- Add POST /api/install/device-auth/approve — JWT-required; verify mhs_id matches device_code's bound mhs_id (or bind it now if init was anon); mint sabp_<hex> via callEdge('/ai/v1/bridge/token'); persist on row; mark approved
- Add POST /api/install/device-auth/deny — JWT-required; mark status=denied
- Add helper rezipWith(baseZipBytes, addPath, addContent) — std-lib JS Zip writer (or import wasm minimal zip lib if needed; CF Workers nodejs_compat allows zlib)
Create
-
C:/MHS/.hascom_deploy/weyland-onamerica/worker/migrations/013_install_device_auth.sql
Per Section D.5 — install_device_auth table with device_code PK, user_code, mhs_id, hostname, agent_label, status, bridge_token, approved_by, approved_at, ip_at_init/approve, ua_at_init, expires_at, created_at, consumed_at; indexes on user_code, mhs_id, (status, expires_at).
-
C:/MHS/PAD_backup/PrecisionAutoDoors/forge/SubmittalExpressFoundry/SubmittalExpress/Phase2/Prototype1/deployment/public/padinstall/index.html
Static landing page per Section D.1 — header, hero quickstart, primary download CTA, live install state probe, bundle inventory, requirements, doctrine references. ~250 lines static HTML.
-
C:/MHS/PAD_backup/PrecisionAutoDoors/forge/SubmittalExpressFoundry/SubmittalExpress/Phase2/Prototype1/deployment/public/padinstall/confirm.html
Device-auth approval page. Shows hostname/capabilities/issued_at; Approve and Deny buttons; calls device-auth/approve|deny.
Tasks
- [4.1] Apply migration 013 to staging and production D1
- [4.2] Implement device-auth/init handler; unit test via curl: returns 200 with shape {device_code, user_code, verification_uri, interval_seconds, expires_in}
- [4.3] Implement device-auth/poll handler with status-machine (pending → approved|denied|expired; approved is single-use via consumed_at)
- [4.4] Implement device-auth/approve handler; tests: (a) JWT required; (b) mhs_id binding check; (c) mints sabp_<hex>; (d) idempotent for the SAME approver
- [4.5] Implement device-auth/deny handler
- [4.6] Build and stage padinstall/index.html — login probe, render hero, fetch bridge status, render install state
- [4.7] Build and stage padinstall/confirm.html — read code from URL, fetch device-auth row metadata for display, wire Approve/Deny buttons
- [4.8] Implement rezipWith helper; manual test: download bundle.zip; unzip; verify .weyland/install-context.json contains mhs_id matching authenticated user; verify NO token strings anywhere in archive (grep -r sabp_)
- [4.9] Implement bundle.zip handler — fetches install/padinstall-v1.0.0.zip from R2, rezips with personalized context, streams
- [4.10] Deploy worker + Pages assets to staging
- [4.11] Manual end-to-end: visit https://staging.weyland.onamerica.org/padinstall while logged in → click download → unzip → grep for 'sabp_' (must return 0 hits) → run install.py with mock device-auth flow → verify token persists
- [4.12] Commit: 'feat(weyland): /padinstall landing + RFC-8628 device-authorization download flow'
Verification
Logged-in browse to staging /padinstall → page renders with bridge status. Anonymous browse → 401/redirect. Bundle download produces ZIP with no secrets. Device-auth init→poll(pending)→browser-approve→poll(approved with token)→token works against /api/me/bridge/status.
Five-Field
- status target
- /padinstall live in staging; device-auth flow exercised end-to-end
- artifacts
- weyland-worker.js (~300 lines added), padinstall/index.html (new), padinstall/confirm.html (new), migration 013 (new)
- testing
- Per-handler curl tests + browser end-to-end. Negative tests: anonymous bundle.zip → 401; expired device_code → status=expired; replay of approved poll → second call returns gone-or-empty
- dependencies
- None blocking — this phase is parallel to Phases 1-3
- issues
- rezipWith implementation: prefer pure-JS zip lib over WASM to keep CF Workers cold-start fast. nodejs_compat zlib gives us deflate; zip envelope is a thin wrapper. Verify in CF Workers context — this is the only mildly novel sub-task.
Produce padinstall-v1.0.0.zip reproducibly via HASCOM capability. Reads bundle_manifest from venture manifest, copies canonical artifacts, generates README/VERSION/install-context-template, zips, optionally uploads to R2.
depends on: phase 4 · blocks: phase 6
Modify
-
C:/MHS/hascom/sites/weyland-onamerica.json
Add padinstall block with bundle_version, bundle_r2_key, bundle_uri, bundle_manifest (operator + source + docs + tools + local_edition file lists)
Create
-
C:/MHS/hascom/providers/padinstall.py
HASCOM provider — registers padinstall.build, padinstall.list, padinstall.upload capabilities. Reads bundle_manifest from manifest. Copies files. Generates ZIP. Optionally pushes to R2 via wrangler r2 object put.
-
C:/MHS/hascom/providers/__init__.py
Register padinstall provider
Tasks
- [5.1] Author padinstall.py provider scaffolding — register capabilities (padinstall.build, padinstall.list, padinstall.upload)
- [5.2] Implement padinstall.build: read manifest, resolve bundle_manifest paths, copy to staging dir under .hascom_deploy/weyland-onamerica/install/padinstall-v1.0.0/, generate VERSION + README + .weyland/install-context.json template + .gitignore-style exclusions, zipfile.ZipFile to padinstall-v1.0.0.zip
- [5.3] Implement padinstall.list: enumerate ZIP contents, sha256 each, return manifest report
- [5.4] Implement padinstall.upload: subprocess wrangler r2 object put weyland-onamerica-assets/install/padinstall-v1.0.0.zip --remote (prod) and weyland-onamerica-staging-assets/install/padinstall-v1.0.0.zip --remote (staging)
- [5.5] Update weyland-onamerica.json manifest with padinstall block
- [5.6] Manual: run hascom invoke padinstall.build --version v1.0.0 → verify ZIP produced; hascom invoke padinstall.list → verify manifest matches expected layout; hascom invoke padinstall.upload → verify R2 keys present in both buckets
- [5.7] Commit: 'feat(hascom): padinstall.build|list|upload provider; manifest declares bundle layout'
Verification
padinstall.build produces a ZIP that, when extracted, has the exact layout in Section E.1 + F.7. padinstall.list output matches that layout. R2 upload visible via wrangler r2 object list.
Five-Field
- status target
- Bundle build is HASCOM-grounded, reproducible, R2-deployable
- artifacts
- hascom/providers/padinstall.py (~250 lines), manifest update, .hascom_deploy/weyland-onamerica/install/padinstall-v1.0.0.zip
- testing
- Capability-level test (hascom invoke padinstall.build). Bundle inventory check via padinstall.list.
- dependencies
- Phase 6 (bundle contents) must produce the artifacts the bundle_manifest references — actually this phase only needs the FILES to exist; phase 6 produces them. Run phase 6 mostly in parallel; final padinstall.build runs at the end of phase 6.
- issues
- Bundle versioning policy: SemVer on bundle_version. v1.0.0 is the first cut. Subsequent bundles bump as content changes.
Author every file in the bundle layout: install.bat/sh/py, uninstall.py, doctor.py, update.py, agent/ files, source/ copies, docs/ markdown.
depends on: phase 1, 4 · blocks: phase 9
Create
-
C:/MHS/.hascom_deploy/weyland-onamerica/install/padinstall-v1.0.0/
- README.md (~80 lines, warm Andrew-named greeting that's also clean for general use)
- install.bat (5 lines per Section E.2)
- install.sh (5 lines per Section E.2)
- install.py (~250 lines per Section E.3 — Phase 1-6 walk: banner, preflight, device-auth init, browser open, poll, persist config, stage agent, verify, offer service, start)
- uninstall.py (~80 lines: stop bridge, revoke token via DELETE /api/me/bridge/tokens/:id, rm ~/.weyland-bridge/, optionally remove auto-start)
- doctor.py (~80 lines: green/red checklist — bridge online, token valid, claude reachable, config sane)
- update.py (~60 lines: SHA-compare local vs R2 weyland-bridge.py, replace if newer, restart bridge)
- VERSION (single line: padinstall-v1.0.0-2026-05-07)
- .weyland/install-context.json (template; populated at download-time by /padinstall/bundle.zip handler)
- agent/weyland-bridge.py (canonical copy from C:/MHS/workers/weyland-bridge/)
- agent/PROVIDERS.md (adapter inventory)
- agent/service/windows-service.py (NSSM-style or schtasks-based wrapper)
- agent/service/launchd-plist.template
- agent/service/systemd-unit.template
- source/README.md (developer kit reading guide)
- source/frontend/subx.html (canonical copy)
- source/worker/weyland-worker.js (canonical copy)
- source/worker/wrangler-hascom.toml.template (with REPLACE: placeholders)
- source/worker/_headers (canonical copy)
- source/worker/migrations/*.sql (every migration)
- source/schema/weyland_monolith_live_schema.json (canonical copy)
- source/bridge/weyland-bridge.py (mirror of agent/, for diff-tracking convenience)
- docs/QUICKSTART.md (~1 page: cloud bridge + local 5-min paths)
- docs/ARCHITECTURE.md (3-4 pages: AI-agnostic, §4a, subscription-funded)
- docs/RUNBOOK.md (2-3 pages: ops, debug, extend, observe)
- docs/BRIDGE.md (2 pages: SABP v1 spec, adapter contract)
- docs/CLAUDE_CODE_VISION.md (1 page: how the adapter works, demystified)
- docs/DEPLOY_YOUR_OWN.md (2 pages: standing up your own weyland on your own CF account)
- docs/LOCAL_EDITION.md (2 pages: when to use local, tradeoffs, how it works)
- docs/doctrine/venture-standard-v1.2.md (verbatim copy)
- docs/doctrine/sovereign-ai-bridge-protocol-v1.md (verbatim copy)
Tasks
- [6.1] Author install.py end-to-end (the most consequential file in the bundle); std-lib only; test on a Windows VM if possible (Windows preflight + ACL token-permission lockdown is the trickiest cross-platform code)
- [6.2] Author uninstall.py / doctor.py / update.py — each ~50-80 lines, each with --json output mode for scripting
- [6.3] Author install.bat / install.sh / install-local.bat / install-local.sh / start-local.bat / start-local.sh — all thin shims
- [6.4] Copy canonical source/ artifacts (frontend, worker, migrations, schema)
- [6.5] Author docs/ markdown — start from QUICKSTART (most user-facing); ARCHITECTURE follows; RUNBOOK; the rest are technical reference
- [6.6] Copy docs/doctrine/* verbatim from canonical paths
- [6.7] Author agent/PROVIDERS.md and agent/service/* templates
- [6.8] Update agent/weyland-bridge.py to canonical (post-Phase-1 version with vision adapter)
- [6.9] Run hascom invoke padinstall.build --version v1.0.0; verify bundle layout matches Section E.1 + F.7
- [6.10] Run hascom invoke padinstall.upload — push to R2 staging + production buckets
- [6.11] Manual end-to-end: download bundle.zip from staging /padinstall as logged-in user; unzip; run install.bat on a Windows test environment; verify bridge comes online; verify all expected files present and permissions correct
- [6.12] Commit: 'feat(padinstall): v1.0.0 bundle contents + R2 upload'
Verification
Bundle download → unzip → install.bat → bridge online within 60s. doctor.py reports all green. Bundle inventory matches manifest declaration.
Five-Field
- status target
- Bundle is downloadable, installable, operational
- artifacts
- Entire .hascom_deploy/weyland-onamerica/install/padinstall-v1.0.0/ tree (~30 files, ~3MB), padinstall-v1.0.0.zip (~XX MB) in R2 staging + production buckets
- testing
- Manual install on Windows test box. Linux/macOS install on shell scripts (smoke). doctor.py post-install green check.
- dependencies
- Phase 1 (vision adapter in canonical agent/weyland-bridge.py); Phase 4 (/padinstall + device-auth wired so bundle delivery actually works)
- issues
- Windows ACL via icacls is the most brittle cross-platform bit — test on real Windows. Browser auto-open for device-auth confirm URL needs platform-specific fallback (webbrowser.open works generally; we print URL clearly as fallback).
Stand up the local edition: wrangler-local.toml + init-local-db.py + start-local.py + vision-sidecar.py + install-local.py. Same worker code runs both editions; sidecar reuses bridge's dispatch_claude_code.
depends on: phase 1, 2 · blocks: phase 9
Create
-
C:/MHS/.hascom_deploy/weyland-onamerica/install/padinstall-v1.0.0/local/
- README-LOCAL.md (~1 page: when local makes sense, how it differs from cloud-bridge)
- wrangler-local.toml (per Section F.3 — local D1, local R2, WEYLAND_EDITION=local, sidecar URL)
- install-local.py (~150 lines per Section F.4 — preflight Python+claude+Node+wrangler; install wrangler if missing; run migrations; seed local user; print 'run start-local.bat')
- start-local.py (~80 lines per Section F.4 — spawn wrangler dev + sidecar; wait for /api/health ready; open browser; trap Ctrl+C and clean up)
- vision-sidecar.py (~50 lines per Section F.2 — http.server.HTTPServer on 127.0.0.1:9999, /extract endpoint reuses dispatch_claude_code from agent/weyland-bridge.py)
- stop-local.py (~30 lines: find children by port, terminate gracefully)
- local-data/.gitkeep
Tasks
- [7.1] Author wrangler-local.toml; sanity: wrangler dev --config wrangler-local.toml --port 8787 should boot weyland-worker.js against emulated D1+R2
- [7.2] Author install-local.py preflight checks (Python 3.8+, claude, Node 18+, wrangler — install wrangler globally via npm if missing)
- [7.3] Author migration runner inside install-local.py: iterate source/worker/migrations/*.sql, execute each via wrangler d1 execute weyland-local --local --file=<path>
- [7.4] Author seed_local_user step: insert local-user-1 row with mhs_id=MHS-LOCAL-0001
- [7.5] Author vision-sidecar.py — http.server, single endpoint, reuses dispatch_claude_code
- [7.6] Author start-local.py — process supervision, wait-for-ready, browser open, Ctrl+C handler
- [7.7] Modify weyland-worker.js authenticate() to short-circuit when env.WEYLAND_EDITION==='local' returning LOCAL_DEFAULT_USER object (already covered in Phase 2 — verify it's wired)
- [7.8] Manual end-to-end on a fresh test environment: install Python+claude+Node, run install-local.bat, run start-local.bat, browse localhost:8787/workspace/?edition=local, upload PDF, affirm claude_code_subprocess, verify extraction completes via local sidecar via local claude subprocess
- [7.9] Commit: 'feat(padinstall): local edition twin — wrangler-dev + Vision sidecar reusing bridge adapter'
Verification
From a clean Windows box: install-local.bat runs preflight, applies migrations, prints success. start-local.bat boots wrangler+sidecar+browser. Upload + extract completes locally. ~/.weyland-bridge/ and cloud bridge ALSO work simultaneously without conflict.
Five-Field
- status target
- Local edition fully operational; same source as cloud edition; sidecar reuses bridge adapter
- artifacts
- local/ subtree in bundle (~6 files), one-line auth bypass in worker
- testing
- Manual end-to-end on Windows test box. Edge case: wrangler dev cold-start latency; first request may be slow.
- dependencies
- Phase 1 (vision adapter); Phase 2 (worker dispatcher with WEYLAND_EDITION+adaptersForEdition); Node + wrangler installable on Andrew's box
- issues
- Node + wrangler are non-trivial dependencies. install-local.py auto-installing wrangler globally via npm is convenient but assumes Node and npm exist. Document fallback: 'install Node from nodejs.org, then re-run install-local.bat'. Wrangler version compatibility with weyland-worker.js's compat date — pin to known-good wrangler@4.x.
Make the editions concept and padinstall pattern fleet doctrine. Codify in manifest schema and in venture-standard.md so future ventures inherit the pattern.
blocks: phase 10
Modify
-
C:/MHS/hascom/sites/weyland-onamerica.json
- Add 'editions' top-level block per Section F.9 — declares cloud + local editions, ai_routes per edition, auth posture per edition, preflight per edition, ports per edition
- Add 'padinstall' block per Section E.8 — bundle_version, bundle_r2_key, bundle_uri, bundle_manifest
- Update 'fleet_integrations.auth' to v2.1 surface map per Section C.4 — external_surface routes (JWT) include all customer-facing including new /padinstall/* and /api/install/device-auth/*; internal_surface routes (PASETO) include callEdge targets
- Add 'routes.api_surfaces' per-route classification (external_jwt vs internal_paseto)
- Bump manifest's framework_version to 'fleet-venture-manifest-v2.2'
-
C:/MHS/docs/fleet/venture-standard-v1.md
- Bump to v1.2 — header notes 'v1.2 change (2026-05-07): Added §6a — editions are first-class. Each venture may declare cloud (canonical SaaS) and local (wrangler-dev twin) editions. Same source, edition-aware dispatcher, edition-aware auth posture.'
- Add §6a — Editions section: principle, manifest contract (the editions block schema), edition-aware adapter pattern, single-source-of-truth discipline (same worker .js for all editions)
- Add §6b — /padinstall pattern: ventures may publish a personal-edition install bundle at <site>/padinstall, JWT-gated, RFC-8628 device-auth, secret-free ZIPs. Codify this as an inheritable pattern.
Create
-
C:/MHS/docs/specs/sovereign-ai-bridge-protocol-v1.1.md
Bump SABP doc to v1.1 — note that adapter contract is now formalized (Anthropic Messages shape in/out; std-lib subprocess; AI-agnostic principle). List the adapter inventory (anthropic_api ✓, claude_code text+vision ✓, codex_cli planned, gemini_cli planned, openconfig planned).
Tasks
- [8.1] Author manifest editions/padinstall blocks; validate JSON
- [8.2] Author venture-standard v1.2 (§6a, §6b)
- [8.3] Author SABP v1.1 doc
- [8.4] Sanity: hascom query 'editions' should surface the new manifest block; hascom find 'venture-standard-v1.2' should resolve
- [8.5] Commit: 'docs(fleet): venture-standard v1.2 (editions, padinstall); manifest v2.2 with edition+padinstall blocks; SABP v1.1'
Verification
Manifest parses (jq . hascom/sites/weyland-onamerica.json); doctrine docs render in any markdown viewer; HASCOM indexes the new blocks (hascom analyze on next pass).
Five-Field
- status target
- Doctrine and manifest reflect this delivery; pattern is reusable by future ventures
- artifacts
- Manifest update, venture-standard v1.2, SABP v1.1 spec
- testing
- JSON schema validation; markdown rendering
- dependencies
- None — runs in parallel with implementation phases
- issues
- Backwards compat for existing ventures: editions block is optional; absence implies single cloud edition (current behavior). No breaking change.
Prove both editions work end-to-end on Andrew's actual box. Real claude code subscription. Real PDF.
depends on: phase 3, 6, 7 · blocks: phase 10
Create
-
C:/MHS/hascom/tickets/RT-2026-0507-WEYLAND-001_personal_edition_session_retrospective.json
Session retrospective with verify_evidence — same shape as CH-2026-0420 chain_link.verify_evidence: cloud_bridge_e2e + local_edition_e2e + padinstall_flow_e2e.
Tasks
- [9.1] Cloud bridge edition end-to-end: Andrew visits weyland.onamerica.org/padinstall → logs in → downloads bundle → install.bat → device-auth flow → bridge online → uploads test PDF → affirms claude_code_local → his claude code processes → result renders. Capture timing, screenshots, evidence.
- [9.2] Local edition end-to-end: Andrew runs install-local.bat → migrations apply → start-local.bat → browser opens to localhost:8787/workspace/?edition=local → uploads same test PDF → affirms claude_code_subprocess → sidecar processes via his claude code → result renders. Capture timing, screenshots, evidence.
- [9.3] Coexistence test: run cloud bridge agent AND local edition simultaneously; upload PDF in each browser tab; verify no conflicts.
- [9.4] doctor.py post-install green check on both editions
- [9.5] Author RT-2026-0507-WEYLAND-001 retrospective with full verify_evidence
- [9.6] Commit: 'verify(weyland): personal edition end-to-end on PAD box (Andrew); both editions green'
Verification
Both editions successfully process Andrew's PDF using HIS Claude Code subscription, with NO API calls billed against MHS Anthropic key. Full subscription-funded compute thesis demonstrated.
Five-Field
- status target
- VERIFIED — both editions operational on Andrew's box; subscription-funded thesis demonstrated
- artifacts
- RT ticket with verify_evidence; screenshots; timing data
- testing
- Real-world end-to-end on Andrew's actual box with his actual subscription
- dependencies
- All previous phases deployed
- issues
- Andrew's claude code subscription must be active and have credit. CH-0420 evidence flagged 'local credit balance' as the gate; same applies here.
Promote staging → production. Forge ticket completion. Update HASCOM project index. Capture chain_link.verify_evidence.
depends on: phase 9
Modify
-
C:/MHS/hascom/tickets/00_HASCOM_PROJECT_INDEX.json
Add CH-2026-0507-WEYLAND-001 to active_tickets→completed; update revision counter.
Tasks
- [10.1] Production deploy worker: deploy_weyland.bat production (or python -m hascom invoke venture.migrate hascom/sites/weyland-onamerica.json weyland)
- [10.2] Apply migrations 012 and 013 to production D1 — wrangler d1 execute weyland-onamerica --remote --file=migrations/012... and --file=migrations/013...
- [10.3] Production /padinstall verify: visit https://weyland.onamerica.org/padinstall as authenticated user; download bundle; spot-check no secrets
- [10.4] Production end-to-end smoke: log in as Andrew (or test user with bridge); upload test PDF; verify claude_code_local route works against PRODUCTION weyland
- [10.5] Update CH-2026-0507-WEYLAND-001 status: PLANNED → IN_PROGRESS during build; → VERIFIED on Phase 9 close; → CLOSED on Phase 10 close. Capture chain_link.verify_evidence with cloud_bridge_e2e + local_edition_e2e + padinstall_flow + production_deploy.
- [10.6] Forge post: hascom forge post --channel MHS-V17-EVOLUTION --body 'CH-2026-0507-WEYLAND-001 CLOSED — Andrew operating personal edition; subscription-funded Vision OCR demonstrated; padinstall pattern available for fleet inheritance.'
- [10.7] Update MEMORY.md / hascom indexes per standing orders
- [10.8] Commit: 'verify(weyland): CH-2026-0507-WEYLAND-001 CLOSED — production deploy + forge'
Verification
Production /padinstall serves; production worker honors edition-aware dispatch; production migration 012+013 applied; HASCOM project index reflects close-out; forge post visible to fleet.
Five-Field
- status target
- CLOSED — work landed in production, doctrine codified, retrospective filed
- artifacts
- Production deployment, HASCOM project index update, forge post, RT-2026-0507-WEYLAND-001 retrospective
- testing
- Production smoke against live customer-facing surface
- dependencies
- Phase 9 verified
- issues
- Production migration application requires CAPT sign-off per CHENG standard.
Open questions & locked decisions
Should the bundle's claude code subprocess invocation pin a specific permission profile (e.g., --dangerously-skip-permissions vs --permission-mode bypassPermissions)?
→ Decided 2026-05-07: --permission-mode bypassPermissions + --allowed-tools 'Read,Grep,Glob' belt-and-suspenders. Truly headless; whitelist bounds blast radius.
Should /padinstall ZIP carry pairing code OR rely on browser device-auth?
→ Decided 2026-05-07: Browser device-auth (RFC-8628 shape). ZIP carries zero secrets; only identity hints.
Decision 1 — branch inside processWithClaudeVision vs introduce dispatchVisionExtraction?
→ Decided 2026-05-07: dispatchVisionExtraction. Worker-side mirror of bridge's PROVIDERS dict; honest naming; clean home for adapter map.
Decision 2 — public landing → tokenized download vs auth-gated → public-shape ZIP?
→ Decided 2026-05-07: Auth-gated /padinstall + public-shape ZIP. ZIP holds no token; device-auth handles pairing.
Local edition shape — wrangler-dev twin vs Python re-implementation vs documented-only?
→ Decided 2026-05-07: wrangler-dev twin. Same worker source for both editions; one new adapter; sidecar reuses bridge adapter via HTTP wrapper.
PASETO mint endpoint readiness in production — when does X-Surface internal-fallback-jwt retire?
→ OPEN. Next step: Track AE-2026-0415-FLEET-001 (currently phase=VERIFY). When CH-FLEET-AUTH-006 ships, retire fallback path; this becomes a follow-up CH ticket.
Bundle versioning strategy beyond v1.0.0 — automated bumps?
→ OPEN. Next step: After v1.0.0 ships, add padinstall.bump capability that increments bundle_version, regenerates VERSION + manifest, builds + uploads. Defer to fast-follow ticket.
Chain link
Authored by: Claude Opus 4.7 in collaboration with CAPT Ron Helms (on-site at PAD HQ with Andrew Miller)
Session: 2026-05-07 PAD-on-site personal-edition design and build session
Design walk completed
- Section A — AI-agnostic adapter contract: APPROVED
- Section B — Vision adapter (bypassPermissions + Read/Grep/Glob whitelist + stdout return channel): APPROVED
- Section C — Worker dispatcher + PASETO boundary + finalize endpoint: APPROVED
- Section D — /padinstall + RFC-8628 device authorization: APPROVED
- Section E — Install bundle (operator + developer + docs two-track): APPROVED
- Section F — Local edition (wrangler-dev twin): APPROVED
Decisions locked
- Decision 1B: dispatchVisionExtraction (worker-side) + adapter map pattern (mirrors bridge PROVIDERS)
- Decision 2B: auth-gated /padinstall + public-shape (secret-free) ZIP
- AI-agnostic doctrinal framing: adapters are headless equivalents of API calls; default to vendor latest model; std-lib only
- PASETO §4a integration with graceful fallback (system-under-development)
- Local edition: wrangler-dev twin, single source of truth for worker code, sidecar reuses bridge adapter
- claude --permission-mode bypassPermissions — full headless
Next action: Ron approves this plan ticket → execution begins. Recommended execution mode (per writing-plans skill terminal-state): superpowers:subagent-driven-development for parallel-safe phases (Phases 4, 5, 8 are independent; Phases 1, 2, 3, 7, 9 form a critical path). Phase 1 first (vision adapter unblocks Phase 2 and Phase 7); Phase 4 in parallel; Phases 5+6+8 follow; Phase 7 once Phase 2 lands; Phase 9 once 3+6+7; Phase 10 closes.