Skip to content

feat(cohort): local-AI cohort chat + daily connection-graph engine#497

Open
Mikeishiring wants to merge 7 commits into
mainfrom
feat/cohort-chat-and-connections
Open

feat(cohort): local-AI cohort chat + daily connection-graph engine#497
Mikeishiring wants to merge 7 commits into
mainfrom
feat/cohort-chat-and-connections

Conversation

@Mikeishiring

Copy link
Copy Markdown
Collaborator

Two features on the read-side of the cohort value loop — both designed around bring-your-own local AI (no API keys) and precompute-then-read (the app never calls an LLM at runtime).

1. Daily connection engine → per-team "who to talk to"

A precomputed "who should talk to whom" graph, surfaced per team and as chat grounding.

  • scripts/lib/cohort-connections-engine.mjs — pure, deterministic scorer: normalizes every team/person to seeks/offers/skills token bags and scores directional edges from seeking↔offering matches, skill overlap, shared clusters, and declared dependencies — each with a written reason. 445 edges over current data.
  • scripts/build-cohort-connections.mjs — the daily routine: runs the operator's own local AI CLI (claude/codex/ollama, auto-detected, or COHORT_LLM_CMD) over the corpus + deterministic candidates to refine reasons. Falls back to the deterministic graph when no CLI/bad JSON. No API key.
  • publish-connections-to-supabase.mjs + migration public_cohort_connections (anon-read/service-write) + reader supabase-connections.mjs + applyConnectionsOverlay — the 6th live overlay (same pattern as the release feed; committed cohort_connections is the offline baseline).
  • .github/workflows/cohort-connections-sync.yml — hourly publish of the committed artifact (no LLM in CI). (Not in this commit — needs a workflow-scoped token to push; see below.)
  • Per-team UI: feeds the edges into the existing "who should talk next" inspector as the top-priority reasoned suggestions, with graceful fallback to the heuristic.

npm run build:connections (local AI) → commit → workflow publishes. Or npm run build:connections:publish to do both locally.

2. "Ask the cohort" chat

  • apps/os/cohort-chat-node.js — spawns the member's local AI CLI one-shot, pipes a grounded prompt to stdin, streams tokens back (mirrors swarm-node.js). No API key.
  • cohort-chat-context.mjs — retrieval-ranks the live surface into a compact grounded prompt: team profiles + the connection edges, distilled session insights, recent activity. The two features share one matching brain.
  • Panel (cohort-chat.js/.css + markup), opened via the "ask the cohort" button or Ctrl/Cmd+Shift+K.

Verification

  • 648 tests pass (624 existing + 24 new), 0 failures
  • Renderer bundle resolves (95 modules), drift gate green, privacy + surface-leak scans clean (graph built only from already-public cohort markdown)
  • Not verified here: the live chat spawn-and-stream (needs a local AI CLI + the running app). claude -p/ollama run read stdin cleanly; Codex reads its prompt as an argument, so set the command explicitly in chat settings.

Follow-ups

  1. cohort-connections-sync.yml is omitted from this commit — pushing .github/workflows/ needs a workflow-scoped token. Add it once the token allows (gh auth refresh -h github.com -s workflow), or merge it via the GitHub UI.
  2. Daily schedule for build:connections:publish (queued behind this landing).

🤖 Generated with Claude Code

1. Connection engine - a daily routine (build-cohort-connections.mjs) runs
   the operator's own local AI CLI over the cohort markdown to compute
   reasoned 'who should talk to whom' edges, published to
   public_cohort_connections (6th Supabase overlay). The app only ever reads
   precomputed edges; per-team detail pages show them in the 'who should talk
   next' inspector. Deterministic engine is the reliable fallback.

2. Cohort chat - 'ask the cohort' panel runs the member's own local AI CLI
   (claude/codex/ollama, no API key), grounded in the live surface +
   connection edges, streaming answers. Ctrl/Cmd+Shift+K.

Tests + renderer bundle + privacy/surface scans green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 24, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
shape-rotator-field-guide Ready Ready Preview, Comment Jun 25, 2026 10:59pm
shape-rotator-field-guide-web Ready Ready Preview, Comment Jun 25, 2026 10:59pm
shape-rotator-os-web Ready Ready Preview, Comment Jun 25, 2026 10:59pm

Request Review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ebd47bb62c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/os/main.js Outdated
// their OWN local CLI to draft a profile update. Raw never leaves the box;
// only the member-approved field delta is written, via the existing editor.
// See self-report-node.js + apps/os/src/renderer/self-report.js.
const selfReport = require("./self-report-node");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0 Badge Add the missing self-report module

In every Electron startup, this unconditional require resolves relative to apps/os/main.js, but a repo-wide search for self-report-node, scanLocalSessions, and runSynthesis only finds this new call/preload stubs and no apps/os/self-report-node.js, so Node throws MODULE_NOT_FOUND before any window is created. Either include the module or gate/remove these IPC handlers until it exists.

Useful? React with 👍 / 👎.

The daily connection routine, run with Claude (this session) as the LLM: 5 agents
reasoned over every team's seeking/offering/skills/journey/dependencies to produce
130 grounded, often non-obvious who-should-talk-to-whom edges (live integrations,
declared deps, exact need↔offer matches), each with a written reason. This is the
committed offline baseline; the live public_cohort_connections row is the runtime
overlay.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ine baseline)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Mikeishiring

Copy link
Copy Markdown
Collaborator Author

Live state (applied 2026-06-25): the public_cohort_connections migration is applied to production and the row is published — 130 Claude-computed connection edges (one per team pair, with reasons), verified via the anon REST path the app uses (edge_count: 130, all 26 teams). The committed connections.json artifact + the refreshed offline surface are the fallback baseline; the live row is the runtime overlay. So this PR's per-team "who to talk to" is live the moment it's read.

Mikeishiring and others added 2 commits June 25, 2026 23:28
main.js unconditionally require()'d ./self-report-node and registered
fg:self-report:* handlers, but that module lives on the Your-Mirror
branch (#504) and does not exist here — so the Electron main process
threw at boot and the app never started. The block leaked from a shared
base; nothing in this PR's two features (connections engine, cohort
chat) uses it, and no renderer references the preload entries. Remove
the require + both handlers from main.js and the bridge entries from
preload.js. All 7 local requires in main.js now resolve.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…connections

# Conflicts:
#	apps/os/src/cohort-surface.json
…wable

Folds the load-bearing privacy engineering from the Hermes "Ask Cohort"
PR (#417) into this chat, which the review flagged as lacking an enforced
public/private boundary on its CLI spawn:

- Provider-key stripping: cohort-chat-node.js spawnEnv() and the build
  side's local-ai-cli.mjs stripProviderKeys() now drop ANTHROPIC_API_KEY /
  ANTHROPIC_AUTH_TOKEN / CLAUDE_CODE_OAUTH_TOKEN / OPENAI_API_KEY[_PATH]
  from the spawn env (opt back in with COHORT_CHAT_USE_ENV_KEYS=1). This
  also fixes the flagged full-`process.env` passthrough — the member's CLI
  now rides THEIR login/subscription, never a key inherited from us.
- Data-sensitivity gate: assertBackendAllowed(dataMode, backend) blocks
  non-public grounding from reaching a remote backend (claude/codex);
  ollama (local) may receive anything. cohort grounding is public today,
  so this is structural defense-in-depth, not a behaviour change.
- 5 unit tests lock the gate + strip (the spawn path was untested before).

Also replaces the engine's 8 literal NUL-byte composite-key separators
with "::" (verified: no record id contains a colon), so git stops
classifying cohort-connections-engine.mjs as binary and the deterministic
scorer is actually reviewable in the diff. 12/12 engine tests unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Regression guard for the boot crash fixed earlier in this PR: a stray
require("./self-report-node") for a file that existed only on another
branch threw at Electron main-process boot, and nothing in the suite
caught it (renderer/unit tests and static asar analysis never load the
main process). This test reads main.js + preload.js, extracts every
local require("./…"), and asserts each resolves — failing loudly if a
future change references a module that isn't on the branch.

Verified end-to-end alongside this: `electron . --smoke-test` boots
clean (PASS, exit 0) on this branch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Mikeishiring

Copy link
Copy Markdown
Collaborator Author

Boot verified end-to-end. After removing the stray require("./self-report-node"), electron . --smoke-test boots clean on this branch:

[smoke] cp:preload
[smoke] cp:module-eval:boot.js → boot:start → … → boot:end
[smoke] PASS: renderer signalled ready    (exit 0)

The main process loads, preload runs, and boot.js completes every checkpoint. (loadGraph failed: Failed to fetch is expected headless — no server — and degrades gracefully.) Added a committed regression guard (apps/os/main-boot-requires.test.mjs) that asserts every local require() in main.js/preload.js resolves, so a future module-leak of this kind fails CI instead of only at runtime.

Also in this pass: harvested #417's provider-key stripping + data-sensitivity gate into the chat spawn (5 new tests), and replaced the engine's 8 NUL-byte composite keys with :: so cohort-connections-engine.mjs is no longer a binary diff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant