import { type DevCapabilityConfig, type WorkspaceYaml } from "../util/config.js"; import { type AgentProfileMerged } from "../util/agent-profile.js"; import type { SkillSpec } from "./skill-parser.js"; /** * v0.6 §2.2 — Spawn-time 8-layer JIT context assembler. * * Pure aggregator: returns an ordered list of Layer records. Building the * actual Task prompt string (concatenation order, header decorations, * tool/system-prompt placement) is the caller's job — `chief-runner.ts`. The * split exists because spawn callers have different needs (Task tool prompt, * `--append-system-prompt`, cwd-adjacent file injection) and the assembler * has no business hard-coding one. * * Drop policy (P1 #4) — `workspace.yaml.spawn.max_context_tokens` (default * 80,000). When the running total exceeds the cap, layers are dropped in * ascending priority: * * priority 1 (REQUIRED): [3] agent SKILL.md — never drop * priority 2 (REQUIRED): [4] org core, [5] agent-profile — never drop * priority 3: [7] handoff slice — oldest first * priority 4: [2] team KNOWLEDGE — keyword match low * priority 5: [6] org domain — keyword match low * priority 6: [1] workspace knowledge — keyword match 0 * priority 7: [8] target repo — biggest files first * * Drops are recorded to `/memory/spawn-decisions.jsonl` (event_type: * `spawn_decision`) — input to the §4.6 FTS5 archive. */ export type LayerKind = "workspace-knowledge" | "team-knowledge" | "agent-skill" | "team-okr" | "org-core" | "agent-profile" | "org-domain" | "handoff" | "repo-context"; export interface Layer { /** Stable index per §2.2 (1-based). */ index: number; kind: LayerKind; /** Human-readable label for diagnostics + JSONL records. */ label: string; /** Concatenated markdown content for this layer (may be empty). */ content: string; /** File paths that contributed (for debugging + telemetry). */ sources: string[]; /** Estimated token count. */ tokens: number; } export interface AssembledContext { layers: Layer[]; /** Labels of layers that were dropped (in drop order). */ truncated: string[]; /** Total tokens after drops. */ totalTokens: number; /** Effective cap used. */ maxTokens: number; } export interface AssembleSpawnContextInput { workspace: string; orgSlug: string; /** Either `{ team, name }` or a `team/name` slug. */ agentRef: { team: string; name: string; }; /** Optional target repo slug — only present when PM hands one off. */ repoSlug?: string; /** Optional workflow id for the handoff slice. */ workflowId?: string; /** Free-form user text (or task description) used for keyword matching. */ query?: string; /** Pre-loaded workspace.yaml — saves a parse on the hot path. */ workspaceYaml?: WorkspaceYaml | null; /** Pre-loaded agent-profile (already 3-tier merged). */ agentProfile?: AgentProfileMerged; /** * v0.8 §3.3 — Owning user handle for this spawn. When set, the assembler * injects the corresponding `/.solosquad/users/.yaml` into * Layer 5 so the specialist sees who issued the command. When omitted, the * assembler falls back to the org's first user yaml (solo-mode default) — * matches v0.6 behavior for callers that have not yet wired the user id. */ userHandle?: string; /** Override max_context_tokens (for tests). */ maxContextTokens?: number; /** Override the per-token char heuristic (for tests). */ charsPerToken?: number; /** Stable "now" for tests. */ now?: Date; /** Disable JSONL writes (for tests). */ dryRun?: boolean; } export declare function assembleSpawnContext(input: AssembleSpawnContextInput): AssembledContext; /** * v0.8.2 §4.1 — runtime tool / bash policy attached to a spawn. * * The factory contract in `claude-process.ts` is intentionally permissive: * we resolve a policy here, the claude-process layer enforces it (allow-list * for `--allowed-tools`, then a pre-check wrap around any Bash invocation). * * Fields: * - `allowedTools` / `disallowedTools` → fed to Claude Code's * `--allowed-tools` / `--disallowed-tools` flags. * - `bashAllowlist` — array of *leading-token* matches (e.g. `"git"`, * `"gh pr create"`, `"npm test"`). A bash command is permitted iff at * least one entry is a prefix of it. * - `bashDenylist` — workspace-strict denylist. Merged on top of the SKILL's * own denied list. A bash command is *always* rejected if any entry is a * substring of it. * - `requirePushConfirmation` — true means `git push` / `gh pr merge` / * `gh pr close` must funnel through `dev-confirm.ts`. * - `networkAllowed` — when false, the bash pre-check rejects `curl`/`wget` * unless the call is to an explicit MCP-server target. v0.8.2 1차에서는 * 단순히 `curl http*` / `wget http*` 패턴을 denylist에 추가하는 식으로 구현. */ export interface SpawnDevPolicy { allowedTools: string[]; disallowedTools: string[]; bashAllowlist: string[]; bashDenylist: string[]; requirePushConfirmation: boolean; networkAllowed: boolean; /** Why the spawn ended up in this mode — useful for logging + tests. */ reason: "read-only" | "dev-enabled" | "workspace-disabled"; } export declare const READ_ONLY_ALLOWED_TOOLS: readonly string[]; export declare const READ_ONLY_DISALLOWED_TOOLS: readonly string[]; export declare const DEV_ENABLED_ALLOWED_TOOLS: readonly string[]; /** * Minimal subset of a SKILL.md frontmatter that this function needs. The full * `SkillSpec` from `skill-parser.ts` is structurally compatible — pass it * directly. (Tests can hand-roll the shape.) */ export interface DevCapabilitySkillView { frontmatter?: Pick; /** Backwards-compatible alternative — top-level fields if the caller has * already destructured a parsed SkillSpec. */ dev_capability?: SkillSpec["dev_capability"]; dev_permissions?: SkillSpec["dev_permissions"]; } /** * Resolve the SpawnDevPolicy for a SKILL given the workspace.yaml master * toggle + the SKILL's own dev_capability declaration. * * Layer-5 (user yaml) override hook is intentionally not implemented here — * v0.8.0 owns the per-user budget/identity injection, and this function only * deals with global dev_capability gating. When v0.8.0 lands, the caller can * post-process the returned policy. */ export declare function applyDevPermissions(skill: DevCapabilitySkillView, workspaceYaml: WorkspaceYaml | DevCapabilityConfig | null | undefined): SpawnDevPolicy;