-
Notifications
You must be signed in to change notification settings - Fork 2
feat(context): founder-context + per-squad alignment as first-class layers #770
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
a93f70e
4b96938
3b0885b
2f52d7f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -95,13 +95,24 @@ export async function runCommand( | |
|
|
||
| // MODE 0: Org cycle — run all squads as a coordinated system | ||
| if (target === '--org' || options.org) { | ||
| const { scanOrg, planOrgCycle, displayOrgScan, displayPlan } = await import('../lib/org-cycle.js'); | ||
| const { scanOrg, planOrgCycle, displayOrgScan, displayPlan, refreshFounderContext } = await import('../lib/org-cycle.js'); | ||
|
|
||
| writeLine(); | ||
| const focusLabel = options.focus ? ` ${bold}[${options.focus}]${RESET}` : ''; | ||
| writeLine(` ${gradient('squads')} ${colors.dim}org cycle${RESET}${focusLabel}`); | ||
| writeLine(); | ||
|
|
||
| // Step 0: REFRESH founder context — distill recent sessions + git activity | ||
| // into per-squad alignment files so agents run aligned with the founder's | ||
| // current pipeline, not generic squad goals. | ||
| if (!options.dryRun) { | ||
| const ctxResult = refreshFounderContext(); | ||
| if (ctxResult === 'failed') { | ||
| writeLine(` ${colors.red}Aborting org cycle. Fix the digest script and retry.${RESET}\n`); | ||
| return; | ||
| } | ||
| } | ||
|
Comment on lines
+105
to
+114
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The founder context refresh is currently only wired into the |
||
|
|
||
| // Step 1: SCAN | ||
| const scan = scanOrg(); | ||
| displayOrgScan(scan); | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -12,8 +12,9 @@ | |||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| import { existsSync, readFileSync, readdirSync, statSync } from 'fs'; | ||||||||||||||||||||||||||||||||||||||||
| import { join } from 'path'; | ||||||||||||||||||||||||||||||||||||||||
| import { findSquadsDir, loadSquad } from './squad-parser.js'; | ||||||||||||||||||||||||||||||||||||||||
| import { spawnSync } from 'child_process'; | ||||||||||||||||||||||||||||||||||||||||
| import { join, dirname } from 'path'; | ||||||||||||||||||||||||||||||||||||||||
|
Check warning on line 16 in src/lib/org-cycle.ts
|
||||||||||||||||||||||||||||||||||||||||
| import { findSquadsDir, loadSquad, findProjectRoot } from './squad-parser.js'; | ||||||||||||||||||||||||||||||||||||||||
| import { findMemoryDir } from './memory.js'; | ||||||||||||||||||||||||||||||||||||||||
| import { colors, bold, RESET, writeLine } from './terminal.js'; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
|
|
@@ -158,6 +159,81 @@ | |||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||
| * Refresh founder context before an org cycle. | ||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||
| * Looks for the digest script at one of two paths (in order): | ||||||||||||||||||||||||||||||||||||||||
| * - .claude/hooks/founder-context-digest.py (preferred — version-controlled hook) | ||||||||||||||||||||||||||||||||||||||||
| * - scripts/founder-context-digest.py (fallback — for projects with a scripts/ dir) | ||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||
| * Runs the script when `.agents/memory/company/founder-context.md` is missing | ||||||||||||||||||||||||||||||||||||||||
| * or older than `staleHours` (default 2h). On success, the digest writes: | ||||||||||||||||||||||||||||||||||||||||
| * - .agents/memory/company/founder-context.md (universal) | ||||||||||||||||||||||||||||||||||||||||
| * - .agents/memory/{squad}/founder-alignment.md (per-squad) | ||||||||||||||||||||||||||||||||||||||||
| * which `gatherSquadContext` then injects into every agent's prompt. | ||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||
| * Returns: | ||||||||||||||||||||||||||||||||||||||||
| * 'refreshed' — digest ran successfully and produced fresh files | ||||||||||||||||||||||||||||||||||||||||
| * 'fresh' — existing context is recent enough, no refresh needed | ||||||||||||||||||||||||||||||||||||||||
| * 'skipped' — no digest script found at expected paths; nothing to do | ||||||||||||||||||||||||||||||||||||||||
| * 'failed' — digest exited non-zero; org cycle should NOT proceed | ||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||
| export function refreshFounderContext( | ||||||||||||||||||||||||||||||||||||||||
| options: { staleHours?: number; force?: boolean } = {} | ||||||||||||||||||||||||||||||||||||||||
| ): 'refreshed' | 'fresh' | 'skipped' | 'failed' { | ||||||||||||||||||||||||||||||||||||||||
| const projectRoot = findProjectRoot(); | ||||||||||||||||||||||||||||||||||||||||
| if (!projectRoot) return 'skipped'; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| const candidatePaths = [ | ||||||||||||||||||||||||||||||||||||||||
| join(projectRoot, '.claude', 'hooks', 'founder-context-digest.py'), | ||||||||||||||||||||||||||||||||||||||||
| join(projectRoot, 'scripts', 'founder-context-digest.py'), | ||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||
| const digestScript = candidatePaths.find(p => existsSync(p)); | ||||||||||||||||||||||||||||||||||||||||
| if (!digestScript) return 'skipped'; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| const memoryDir = findMemoryDir(); | ||||||||||||||||||||||||||||||||||||||||
| const contextFile = memoryDir | ||||||||||||||||||||||||||||||||||||||||
| ? join(memoryDir, 'company', 'founder-context.md') | ||||||||||||||||||||||||||||||||||||||||
| : null; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| const staleHours = options.staleHours ?? 2; | ||||||||||||||||||||||||||||||||||||||||
| const MS_PER_HOUR = 60 * 60 * 1000; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| let isStale = true; | ||||||||||||||||||||||||||||||||||||||||
| if (!options.force && contextFile && existsSync(contextFile)) { | ||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||
| const ageHours = (Date.now() - statSync(contextFile).mtimeMs) / MS_PER_HOUR; | ||||||||||||||||||||||||||||||||||||||||
| if (ageHours < staleHours) { | ||||||||||||||||||||||||||||||||||||||||
| isStale = false; | ||||||||||||||||||||||||||||||||||||||||
| writeLine( | ||||||||||||||||||||||||||||||||||||||||
| ` ${colors.dim}founder-context: fresh (${ageHours.toFixed(1)}h old, threshold ${staleHours}h)${RESET}` | ||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } catch { /* */ } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| if (!isStale) return 'fresh'; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| writeLine(` ${colors.dim}founder-context: refreshing from CC sessions + git activity...${RESET}`); | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+213
to
+217
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hardcoding
Suggested change
|
||||||||||||||||||||||||||||||||||||||||
| // Two Claude calls (universal + per-squad block for all squads in one shot) | ||||||||||||||||||||||||||||||||||||||||
| // can take 5-8 min on large inputs. Cap at 12 min to be safe. | ||||||||||||||||||||||||||||||||||||||||
| const result = spawnSync('python3', [digestScript], { | ||||||||||||||||||||||||||||||||||||||||
| cwd: projectRoot, | ||||||||||||||||||||||||||||||||||||||||
| stdio: 'inherit', | ||||||||||||||||||||||||||||||||||||||||
| timeout: 12 * 60 * 1000, | ||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| if (result.status === 0) { | ||||||||||||||||||||||||||||||||||||||||
| writeLine(` ${colors.green}founder-context: refreshed${RESET}\n`); | ||||||||||||||||||||||||||||||||||||||||
| return 'refreshed'; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| writeLine( | ||||||||||||||||||||||||||||||||||||||||
| ` ${colors.yellow}founder-context: digest failed (exit ${result.status ?? '?'}). ` + | ||||||||||||||||||||||||||||||||||||||||
| `Org cycle blocked — agents would run without strategic alignment.${RESET}\n` | ||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||
| return 'failed'; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||
| * Display execution plan. | ||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,13 +4,24 @@ | |||||||||||||||||||||
| * Squad Context System — context assembly for agent execution. | ||||||||||||||||||||||
| * | ||||||||||||||||||||||
| * Layers flow from general to particular (no overrides, each answers a different question): | ||||||||||||||||||||||
| * L0: SYSTEM.md — How (system, tools, principles — immutable, outside budget) | ||||||||||||||||||||||
| * L1: company.md — Why (company identity, alignment) | ||||||||||||||||||||||
| * L2: priorities.md — Where (current focus, urgency) | ||||||||||||||||||||||
| * L3: goals.md — What (measurable targets) | ||||||||||||||||||||||
| * L4: agent.md — You (agent role, specific instructions) | ||||||||||||||||||||||
| * L5: state.md — Memory (continuity from last run) | ||||||||||||||||||||||
| * L6+: Supporting — feedback, daily-briefing, cross-squad learnings | ||||||||||||||||||||||
| * L0: SYSTEM.md — How (system, tools, principles — immutable, outside budget) | ||||||||||||||||||||||
| * L1: company.md — Why (company identity, alignment) | ||||||||||||||||||||||
| * L2: priorities.md — Where (current focus, urgency) | ||||||||||||||||||||||
| * L3: goals.md — What (measurable targets) | ||||||||||||||||||||||
| * L4: agent.md — You (agent role, specific instructions) | ||||||||||||||||||||||
| * L5: state.md — Memory (continuity from last run) | ||||||||||||||||||||||
| * L6+: Supporting — feedback, daily-briefing, cross-squad learnings | ||||||||||||||||||||||
| * L9: founder-context.md — Live strategic state (universal, all squads see) | ||||||||||||||||||||||
| * L10: founder-alignment.md — Per-squad contribution to founder's current pipeline | ||||||||||||||||||||||
| * | ||||||||||||||||||||||
| * L9 + L10 are auto-generated (e.g. by hq/.claude/hooks/founder-context-digest.py) from | ||||||||||||||||||||||
| * interactive sessions, git activity, and open PRs/issues. They translate the | ||||||||||||||||||||||
| * founder's live strategic context into per-squad, named contributions so each | ||||||||||||||||||||||
| * squad shows up aligned with current priorities rather than inventing generic work. | ||||||||||||||||||||||
| * | ||||||||||||||||||||||
| * Business-specific structural reference (Drive folder map, ERP architecture, | ||||||||||||||||||||||
| * canonical sheet schemas) can be embedded inline into founder-context.md by | ||||||||||||||||||||||
| * the digest script. The CLI loader stays generic; users decide what to embed. | ||||||||||||||||||||||
| * | ||||||||||||||||||||||
| * SQUAD.md is metadata only (repo, agents, config) — NOT injected into prompt. | ||||||||||||||||||||||
| * Each layer adds a unique dimension. No layer contradicts another. | ||||||||||||||||||||||
|
|
@@ -31,24 +42,29 @@ export type ContextRole = 'scanner' | 'worker' | 'lead' | 'coo' | 'verifier'; | |||||||||||||||||||||
| // ── Token Budgets (chars, ~4 chars/token) ──────────────────────────── | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| const ROLE_BUDGETS: Record<ContextRole, number> = { | ||||||||||||||||||||||
| scanner: 4000, // ~1000 tokens — company + priorities + goals + agent + state | ||||||||||||||||||||||
| worker: 12000, // ~3000 tokens — + feedback | ||||||||||||||||||||||
| lead: 24000, // ~6000 tokens — all layers | ||||||||||||||||||||||
| coo: 32000, // ~8000 tokens — all layers + expanded | ||||||||||||||||||||||
| verifier: 12000, // similar needs to worker | ||||||||||||||||||||||
| scanner: 50000, // ~12500 tokens — full founder ctx (incl. embedded Drive structure) + identity layers | ||||||||||||||||||||||
| worker: 60000, // ~15000 tokens — + feedback + alignment | ||||||||||||||||||||||
| lead: 80000, // ~20000 tokens — all layers + founder ctx + alignment | ||||||||||||||||||||||
| coo: 100000, // ~25000 tokens — all layers + expanded + founder ctx | ||||||||||||||||||||||
| verifier: 60000, // similar needs to worker | ||||||||||||||||||||||
| }; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| /** | ||||||||||||||||||||||
| * Which layers each role gets access to. | ||||||||||||||||||||||
| * Numbers correspond to layer order in the Squad Context System: | ||||||||||||||||||||||
| * 1=company, 2=priorities, 3=goals, 4=agent, 5=state, 6=feedback, 7=daily-briefing, 8=cross-squad | ||||||||||||||||||||||
| * 1=company, 2=priorities, 3=goals, 4=agent, 5=state, 6=feedback, | ||||||||||||||||||||||
| * 7=daily-briefing, 8=cross-squad, 9=founder-context, 10=founder-alignment | ||||||||||||||||||||||
| * | ||||||||||||||||||||||
| * Layers 9 and 10 are visible to ALL roles (including scanners): live strategic | ||||||||||||||||||||||
| * context is always relevant, regardless of role. Without it, agents invent | ||||||||||||||||||||||
| * generic work disconnected from the founder's current pipeline. | ||||||||||||||||||||||
| */ | ||||||||||||||||||||||
| const ROLE_SECTIONS: Record<ContextRole, Set<number>> = { | ||||||||||||||||||||||
| scanner: new Set([1, 2, 3, 4, 5]), // identity + focus + role + memory | ||||||||||||||||||||||
| worker: new Set([1, 2, 3, 4, 5, 6]), // + feedback | ||||||||||||||||||||||
| lead: new Set([1, 2, 3, 4, 5, 6, 7, 8]), // + daily briefing + cross-squad | ||||||||||||||||||||||
| coo: new Set([1, 2, 3, 4, 5, 6, 7, 8]), // all layers + expanded budget | ||||||||||||||||||||||
| verifier: new Set([1, 2, 3, 4, 5, 6]), // same as worker | ||||||||||||||||||||||
| scanner: new Set([1, 2, 3, 4, 5, 9, 10]), // identity + focus + role + memory + founder ctx | ||||||||||||||||||||||
| worker: new Set([1, 2, 3, 4, 5, 6, 9, 10]), // + feedback + founder ctx | ||||||||||||||||||||||
| lead: new Set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), // all layers + founder ctx | ||||||||||||||||||||||
| coo: new Set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), // all layers + founder ctx + expanded budget | ||||||||||||||||||||||
| verifier: new Set([1, 2, 3, 4, 5, 6, 9, 10]), // same as worker + founder ctx | ||||||||||||||||||||||
|
Comment on lines
+63
to
+67
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comments for
Suggested change
|
||||||||||||||||||||||
| }; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // ── Agent Frontmatter ───────────────────────────────────────────────── | ||||||||||||||||||||||
|
|
@@ -395,14 +411,23 @@ export function resolveContextRoleFromAgent(agentPath: string, agentName: string | |||||||||||||||||||||
| * Gather context for agent execution. | ||||||||||||||||||||||
| * | ||||||||||||||||||||||
| * Layers flow general → particular (each adds a unique dimension): | ||||||||||||||||||||||
| * 1. company.md — Why (company identity, alignment) | ||||||||||||||||||||||
| * 2. priorities.md — Where (current focus, urgency) | ||||||||||||||||||||||
| * 3. goals.md — What (measurable targets) | ||||||||||||||||||||||
| * 4. agent.md — You (agent role, instructions) | ||||||||||||||||||||||
| * 5. state.md — Memory (continuity from last run) | ||||||||||||||||||||||
| * 6. feedback.md — Supporting (squad feedback) | ||||||||||||||||||||||
| * 7. daily-briefing — Supporting (org pulse, leads+coo only) | ||||||||||||||||||||||
| * 8. cross-squad — Supporting (learnings from other squads) | ||||||||||||||||||||||
| * 1. company.md — Why (company identity, alignment) | ||||||||||||||||||||||
| * 2. priorities.md — Where (current focus, urgency) | ||||||||||||||||||||||
| * 3. goals.md — What (measurable targets) | ||||||||||||||||||||||
| * 4. agent.md — You (agent role, instructions) | ||||||||||||||||||||||
| * 5. state.md — Memory (continuity from last run) | ||||||||||||||||||||||
| * 6. feedback.md — Supporting (squad feedback) | ||||||||||||||||||||||
| * 7. daily-briefing — Supporting (org pulse, leads+coo only) | ||||||||||||||||||||||
| * 8. cross-squad — Supporting (learnings from other squads) | ||||||||||||||||||||||
| * 9. founder-context.md — Live strategic state (universal, all roles) | ||||||||||||||||||||||
| * 10. founder-alignment.md — Per-squad contribution to current pipeline | ||||||||||||||||||||||
| * | ||||||||||||||||||||||
| * Layers 9 and 10 are injected FIRST in the prompt (LLMs pay most attention | ||||||||||||||||||||||
| * to the beginning of context) so squads align with the founder's live | ||||||||||||||||||||||
| * pipeline before processing any other layer. Both are auto-generated | ||||||||||||||||||||||
| * (e.g. by hq/.claude/hooks/founder-context-digest.py) which can also | ||||||||||||||||||||||
| * embed business-specific structural reference (Drive map, ERP architecture) | ||||||||||||||||||||||
| * directly into founder-context.md when relevant. | ||||||||||||||||||||||
| * | ||||||||||||||||||||||
| * SQUAD.md is NOT injected — it's metadata for the CLI (repo, agents, config). | ||||||||||||||||||||||
| * Missing files are skipped gracefully — no crashes on first run or new squads. | ||||||||||||||||||||||
|
|
@@ -422,25 +447,31 @@ export function gatherSquadContext( | |||||||||||||||||||||
| const sections: string[] = []; | ||||||||||||||||||||||
| let usedChars = 0; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| /** Try to add a layer. Returns true if added, false if budget exceeded or not allowed. */ | ||||||||||||||||||||||
| /** Try to add a layer. Returns true if added (possibly truncated), false if no budget left. */ | ||||||||||||||||||||||
| function addLayer(layerNum: number, header: string, content: string, maxChars?: number): boolean { | ||||||||||||||||||||||
| if (!allowedSections.has(layerNum)) return false; | ||||||||||||||||||||||
| if (!content) return false; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| let text = content; | ||||||||||||||||||||||
| const TRUNCATION_SUFFIX = '\n...'; | ||||||||||||||||||||||
| const remaining = Math.max(0, budget - usedChars); | ||||||||||||||||||||||
| const cap = maxChars !== undefined ? Math.min(maxChars, remaining) : remaining; | ||||||||||||||||||||||
| if (text.length > cap) { | ||||||||||||||||||||||
| text = text.substring(0, cap) + '\n...'; | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| if (usedChars + text.length > budget) { | ||||||||||||||||||||||
| if (remaining <= TRUNCATION_SUFFIX.length) { | ||||||||||||||||||||||
| // No room left for even a meaningful truncation | ||||||||||||||||||||||
| if (options.verbose) { | ||||||||||||||||||||||
| writeLine(` ${colors.dim}Context budget exhausted at layer ${layerNum} (${header})${RESET}`); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| return false; | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| const cap = maxChars !== undefined ? Math.min(maxChars, remaining) : remaining; | ||||||||||||||||||||||
| let text = content; | ||||||||||||||||||||||
| if (text.length > cap) { | ||||||||||||||||||||||
| // Reserve TRUNCATION_SUFFIX bytes for the suffix so total fits exactly within cap | ||||||||||||||||||||||
| text = text.substring(0, cap - TRUNCATION_SUFFIX.length) + TRUNCATION_SUFFIX; | ||||||||||||||||||||||
| if (options.verbose) { | ||||||||||||||||||||||
| writeLine(` ${colors.dim}Layer ${layerNum} truncated to ${text.length}/${content.length} chars${RESET}`); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| sections.push(`## ${header}\n${text}`); | ||||||||||||||||||||||
| usedChars += text.length; | ||||||||||||||||||||||
| return true; | ||||||||||||||||||||||
|
|
@@ -454,8 +485,32 @@ export function gatherSquadContext( | |||||||||||||||||||||
| // Put reference material last (company, agent definition). | ||||||||||||||||||||||
| // ═══════════════════════════════════════════════════════════════════ | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // ── L9: founder-context.md — Live strategic state (ACT-ALIGNED) ── | ||||||||||||||||||||||
| // Injected FIRST so agents see the founder's current pipeline before | ||||||||||||||||||||||
| // any squad-internal context. Auto-generated from interactive sessions, | ||||||||||||||||||||||
| // git activity, and open PRs/issues. Universal — all squads see this. | ||||||||||||||||||||||
| if (memoryDir) { | ||||||||||||||||||||||
| const founderContextFile = join(memoryDir, 'company', 'founder-context.md'); | ||||||||||||||||||||||
| const content = safeRead(founderContextFile); | ||||||||||||||||||||||
| if (content) { | ||||||||||||||||||||||
| addLayer(9, 'Founder Context (live strategic state — read first)', content); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // ── L10: founder-alignment.md — How THIS squad contributes this cycle ── | ||||||||||||||||||||||
| // Per-squad translation of founder context into named, domain-specific | ||||||||||||||||||||||
| // contributions. Auto-generated alongside L9. Specific to this squadName. | ||||||||||||||||||||||
| if (memoryDir) { | ||||||||||||||||||||||
| const alignmentFile = join(memoryDir, squadName, 'founder-alignment.md'); | ||||||||||||||||||||||
| const content = safeRead(alignmentFile); | ||||||||||||||||||||||
| if (content) { | ||||||||||||||||||||||
| addLayer(10, `Founder Alignment — ${squadName} (your contribution this cycle)`, content); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // ── L6: feedback.md — ACT ON THIS (corrections from last cycle) ── | ||||||||||||||||||||||
| // Injected FIRST so agents address feedback before anything else. | ||||||||||||||||||||||
| // Injected after founder context so corrections shape interpretation | ||||||||||||||||||||||
| // of the strategic state. | ||||||||||||||||||||||
| if (memoryDir) { | ||||||||||||||||||||||
| const feedbackFile = join(memoryDir, squadName, 'feedback.md'); | ||||||||||||||||||||||
| const content = safeRead(feedbackFile); | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
refreshFounderContextcall should pass theforceoption from the CLI to ensure that the--forceflag correctly triggers a context refresh even if the files are not yet stale.