singularity-forge/src/help-text.ts

409 lines
19 KiB
TypeScript
Raw Normal View History

const SUBCOMMAND_HELP: Record<string, string> = {
config: [
"Usage: sf config",
"",
"Re-run the interactive setup wizard to configure:",
" - LLM provider (Anthropic, OpenAI, Google, OpenRouter, Ollama, LM Studio, etc.)",
" - Web search provider (Brave, Tavily, built-in)",
" - Remote questions (Discord, Slack, Telegram)",
" - Tool API keys (Context7, Jina, Groq)",
"",
"All steps are skippable and can be changed later with /login or /search-provider.",
"",
"For detailed provider setup instructions (OpenRouter, Ollama, LM Studio, vLLM,",
"and other OpenAI-compatible endpoints), see docs/providers.md.",
].join("\n"),
update: [
"Usage: sf update",
"",
"Update SF to the latest version.",
"",
"Equivalent to: npm install -g singularity-forge@latest",
].join("\n"),
sessions: [
"Usage: sf sessions",
" sf sessions --all",
"",
"List saved sessions and interactively pick one to resume. Shows date,",
"message count, and a preview of the first message for each session.",
"",
"Sessions are stored per-directory by default. Use --all to list sessions",
"across all projects.",
"",
" sf sessions List sessions for the current directory",
" sf sessions --all List sessions across all projects",
"",
"Compare with --continue (-c) which always resumes the most recent session.",
].join("\n"),
install: [
"Usage: sf install <source> [-l, --local]",
"",
"Install a package/extension source and run post-install validation (dependency checks, setup).",
"",
"Examples:",
" sf install npm:@foo/bar",
" sf install git:github.com/user/repo",
" sf install https://github.com/user/repo",
" sf install ./local/path",
].join("\n"),
feat(core): support for 'non-api-key' provider extensions like Claude Code CLI (#2382) * feat(core): add generic native post-install hooks for package install * feat(core): add before/after install/remove lifecycle hooks * refactor(core): remove postInstall alias from lifecycle hook fallback * feat(core): complete authMode support for keyless providers The initial authMode implementation fixed model-registry, sdk, and fallback-resolver but missed agent-session.ts (6 callsites) and compaction-orchestrator.ts (2 callsites) that block externalCli providers at runtime. Architecture: separate readiness gating from credential retrieval. - isProviderRequestReady(): authMode-aware readiness check - getApiKey()/getApiKeyForProvider(): return undefined for externalCli/none providers instead of triggering auth errors - All 8 callsites in agent-session and compaction-orchestrator now gate on readiness, not key presence - Downstream signatures (compaction, branch-summarization) accept apiKey: string | undefined - Replaced hardcoded ollama exception in discoverModels with isProviderRequestReady Zero behavioral change for classic apiKey/oauth providers. * feat(core): add isReady callback for provider readiness verification Extensions can now provide an isReady() callback when registering any provider. isProviderRequestReady() calls it before default auth checks, allowing providers to verify actual reachability (CLI authenticated, API key valid, service online) rather than relying solely on credential presence. * test(core): expand authMode test coverage Cover all four auth modes (apiKey, oauth, externalCli, none), isReady callback behavior, getProviderAuthMode defaults, isProviderRequestReady for each mode, getAvailable filtering, and getApiKey early-return for keyless providers. * chore: remove provider-api-bridge files from this branch These files implement GSD core → provider-api wiring (deps + tool registry) and belong in a separate PR. Reverts register-extension.ts to upstream state.
2026-03-24 21:50:12 +00:00
remove: [
"Usage: sf remove <source> [-l, --local]",
"",
"Remove an installed package source and its settings entry.",
].join("\n"),
feat(core): support for 'non-api-key' provider extensions like Claude Code CLI (#2382) * feat(core): add generic native post-install hooks for package install * feat(core): add before/after install/remove lifecycle hooks * refactor(core): remove postInstall alias from lifecycle hook fallback * feat(core): complete authMode support for keyless providers The initial authMode implementation fixed model-registry, sdk, and fallback-resolver but missed agent-session.ts (6 callsites) and compaction-orchestrator.ts (2 callsites) that block externalCli providers at runtime. Architecture: separate readiness gating from credential retrieval. - isProviderRequestReady(): authMode-aware readiness check - getApiKey()/getApiKeyForProvider(): return undefined for externalCli/none providers instead of triggering auth errors - All 8 callsites in agent-session and compaction-orchestrator now gate on readiness, not key presence - Downstream signatures (compaction, branch-summarization) accept apiKey: string | undefined - Replaced hardcoded ollama exception in discoverModels with isProviderRequestReady Zero behavioral change for classic apiKey/oauth providers. * feat(core): add isReady callback for provider readiness verification Extensions can now provide an isReady() callback when registering any provider. isProviderRequestReady() calls it before default auth checks, allowing providers to verify actual reachability (CLI authenticated, API key valid, service online) rather than relying solely on credential presence. * test(core): expand authMode test coverage Cover all four auth modes (apiKey, oauth, externalCli, none), isReady callback behavior, getProviderAuthMode defaults, isProviderRequestReady for each mode, getAvailable filtering, and getApiKey early-return for keyless providers. * chore: remove provider-api-bridge files from this branch These files implement GSD core → provider-api wiring (deps + tool registry) and belong in a separate PR. Reverts register-extension.ts to upstream state.
2026-03-24 21:50:12 +00:00
list: [
"Usage: sf list",
"",
"List installed package sources from user and project settings.",
].join("\n"),
feat(core): support for 'non-api-key' provider extensions like Claude Code CLI (#2382) * feat(core): add generic native post-install hooks for package install * feat(core): add before/after install/remove lifecycle hooks * refactor(core): remove postInstall alias from lifecycle hook fallback * feat(core): complete authMode support for keyless providers The initial authMode implementation fixed model-registry, sdk, and fallback-resolver but missed agent-session.ts (6 callsites) and compaction-orchestrator.ts (2 callsites) that block externalCli providers at runtime. Architecture: separate readiness gating from credential retrieval. - isProviderRequestReady(): authMode-aware readiness check - getApiKey()/getApiKeyForProvider(): return undefined for externalCli/none providers instead of triggering auth errors - All 8 callsites in agent-session and compaction-orchestrator now gate on readiness, not key presence - Downstream signatures (compaction, branch-summarization) accept apiKey: string | undefined - Replaced hardcoded ollama exception in discoverModels with isProviderRequestReady Zero behavioral change for classic apiKey/oauth providers. * feat(core): add isReady callback for provider readiness verification Extensions can now provide an isReady() callback when registering any provider. isProviderRequestReady() calls it before default auth checks, allowing providers to verify actual reachability (CLI authenticated, API key valid, service online) rather than relying solely on credential presence. * test(core): expand authMode test coverage Cover all four auth modes (apiKey, oauth, externalCli, none), isReady callback behavior, getProviderAuthMode defaults, isProviderRequestReady for each mode, getAvailable filtering, and getApiKey early-return for keyless providers. * chore: remove provider-api-bridge files from this branch These files implement GSD core → provider-api wiring (deps + tool registry) and belong in a separate PR. Reverts register-extension.ts to upstream state.
2026-03-24 21:50:12 +00:00
logs: [
"Usage: sf logs tail|follow [--source notif|session|activity|audit] [--severity level]",
"",
"Follow a merged live stream from .sf/notifications.jsonl, the latest",
"headless session JSONL, the latest .sf/activity JSONL, and .sf/audit-log.jsonl.",
"",
"Examples:",
" sf logs tail",
" sf logs follow --source audit",
" sf logs tail --severity error",
].join("\n"),
status: [
"Usage: sf status --live [--watch]",
"",
"Show a printable aggregate project view: current milestone, slice, task,",
"phase, next dispatch, recent events, session cost, and current model.",
"",
"Examples:",
" sf status --live",
" sf status --live --watch",
" sf dash --watch",
].join("\n"),
dash: ["Usage: sf dash [--watch]", "", "Alias for sf status --live."].join(
"\n",
),
stats: [
"Usage: sf stats models [--unit-type <type>] [--since <duration>]",
"",
"Summarize Bayesian model outcome rows from .sf/sf.db.",
"",
"Examples:",
" sf stats models --since 7d",
" sf stats models --unit-type execute-task --since 24h",
].join("\n"),
worktree: [
"Usage: sf worktree <command> [args]",
"",
"Manage isolated git worktrees for parallel work streams.",
"",
"Commands:",
" list List worktrees with status (files changed, commits, dirty)",
" merge [name] Squash-merge a worktree into main and clean up",
" clean Remove all worktrees that have been merged or are empty",
" remove <name> Remove a worktree (--force to remove with unmerged changes)",
"",
"The -w flag creates/resumes worktrees for interactive sessions:",
" sf -w Auto-name a new worktree, or resume the only active one",
" sf -w my-feature Create or resume a named worktree",
"",
"Lifecycle:",
" 1. sf -w Create worktree, start session inside it",
" 2. (work normally) All changes happen on the worktree branch",
" 3. Ctrl+C Exit — dirty work is auto-committed",
" 4. sf -w Resume where you left off",
" 5. sf worktree merge Squash-merge into main when done",
"",
"Examples:",
" sf -w Start in a new auto-named worktree",
' sf -w auth-refactor Create/resume "auth-refactor" worktree',
" sf worktree list See all worktrees and their status",
" sf worktree merge auth-refactor Merge and clean up",
" sf worktree clean Remove all merged/empty worktrees",
" sf worktree remove old-branch Remove a specific worktree",
" sf worktree remove old-branch --force Remove even with unmerged changes",
].join("\n"),
graph: [
"Usage: sf graph <subcommand> [options]",
"",
"Manage the SF project knowledge graph. Reads .sf/ artifacts and builds",
"a queryable graph of milestones, slices, tasks, rules, patterns, and lessons.",
"",
"Subcommands:",
" build Parse .sf/ artifacts (STATE.md, milestone ROADMAPs, slice PLANs,",
" KNOWLEDGE.md) and write .sf/graphs/graph.json atomically.",
" query Search graph nodes by term (BFS from seed matches, budget-trimmed).",
" Returns matching nodes and reachable edges within the token budget.",
" status Show whether graph.json exists, its age, node/edge counts, and",
" whether it is stale (built more than 24 hours ago).",
" diff Compare current graph.json with .last-build-snapshot.json.",
" Returns added, removed, and changed nodes and edges.",
"",
"Examples:",
" sf graph build Build the graph from .sf/ artifacts",
" sf graph status Check graph age and node/edge counts",
' sf graph query auth Find nodes related to "auth"',
" sf graph diff Show changes since last snapshot",
].join("\n"),
feat(graph): implement knowledge graph system (closes #4202) Ports the v1 graphify system to v2 as a native TypeScript implementation. The knowledge graph builds semantic relationships between milestones, slices, tasks, and knowledge entries — and injects relevant subgraphs automatically into every agent dispatch prompt. ## Core implementation (packages/mcp-server/src/readers/graph.ts) - `buildGraph(projectDir)` — walks all .gsd/ artifacts (STATE.md, milestone PLANs, slice PLANs, KNOWLEDGE.md), extracts nodes and edges with confidence tiers (EXTRACTED / INFERRED / AMBIGUOUS). Parse errors skip the node rather than crashing. - `writeGraph(gsdRoot, graph)` — atomic write via tmp file + rename. - `writeSnapshot(gsdRoot)` — saves a diff baseline before each rebuild. - `graphQuery(projectDir, term, budget?)` — BFS subgraph search with case-insensitive matching on label + description; trims AMBIGUOUS edges first, then INFERRED, respecting the token budget (default 4 000). - `graphStatus(projectDir)` — freshness check; stale = older than 24 h. - `graphDiff(projectDir)` — compares current graph to last snapshot, returns added / removed / changed counts for nodes and edges. ## MCP tool (packages/mcp-server/src/server.ts) Registers `gsd_graph` immediately after `gsd_knowledge` with four modes: build | query | status | diff. All errors returned as isError: true. ## CLI subcommand (src/cli.ts, src/help-text.ts) `gsd graph build|status|query <term>|diff` — follows the established `if (cliFlags.messages[0] === '...')` dispatch pattern. Uses `resolveGsdRoot()` for git-root-aware path resolution (not a naive `.gsd` append). Help text updated with correct positional argument format. ## Auto-rebuild after slice completion (src/resources/extensions/gsd/tools/complete-slice.ts) Fire-and-forget `buildGraph → writeGraph` triggered after every slice completion. Uses `@gsd-build/mcp-server` package import (not a relative src path) and `resolveGsdRoot()` for correct path resolution in monorepos. ## Graph-aware dispatch injection (src/resources/extensions/gsd/graph-context.ts, src/resources/extensions/gsd/auto-prompts.ts) `inlineGraphSubgraph(projectDir, term, { budget })` queries the graph and formats the result as a `### Knowledge Graph Context` markdown block, consistent with all other inlined context blocks. Adds a stale warning annotation when the graph is older than 24 h. Returns null (graceful skip) when graph.json is missing, the query returns zero nodes, or the import fails — no agent dispatch is ever blocked by graph availability. Injected into three prompt builders: - `buildResearchSlicePrompt` — 3 000 token budget - `buildPlanSlicePrompt` — 3 000 token budget - `buildExecuteTaskPrompt` — 2 000 token budget ## Tests - 22 tests for the core graph reader (graph.test.ts) - 14 tests for the dispatch injection helper (graph-context.test.ts) - All tests use real on-disk fixtures (no module mocking needed) - Full suite: 6 318 passed, 0 failed Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 02:20:49 +02:00
plan: [
"Usage: sf plan <command>",
"",
"Manage SF milestone planning artifacts and human docs exports.",
"",
"Commands:",
" promote <source> Copy a file from .sf/ to docs/plans/, docs/adr/, or docs/specs/",
" list List milestone and slice files in .sf/",
" diff Compare .sf/ state with promoted docs/ artifacts",
" specs <cmd> Generate, diff, or check docs/specs exports from .sf state",
"",
"See docs/plans/README.md, docs/adr/README.md, and docs/specs/README.md for conventions.",
].join("\n"),
2026-05-06 06:02:46 +02:00
schedule: [
"Usage: sf schedule <command> [args]",
"",
"Manage time-bound reminders and deferred work items.",
"Entries are stored as versioned append-only JSONL in .sf/schedule.jsonl (project)",
2026-05-06 06:02:46 +02:00
"or ~/.sf/schedule.jsonl (global). No daemon required — items surface on pull.",
"",
"Commands:",
" add --in <duration> [--kind <kind>] [--scope <scope>] <title>",
" --at <ISO-date> Schedule by absolute date instead",
" list [--due] [--all] [--json] [--scope <scope>]",
" done <id> Mark a scheduled item as done",
" cancel <id> Cancel a scheduled item",
" snooze <id> --by <duration> Postpone by relative time",
" run <id> Execute a scheduled item (show reminder or run command)",
"",
"Duration format: <number><unit> where unit is w(weeks), d(days), h(hours), m(minutes).",
" e.g. 30m, 4h, 2d, 1w",
"",
"Scope: project (default, stored in .sf/schedule.jsonl) or global (~/.sf/schedule.jsonl).",
"",
"Kinds: reminder, milestone_check, review_due, review, audit, recurring, command",
"",
"Examples:",
' sf schedule add --in 2w "Review feature adoption metrics"',
' sf schedule add --at 2026-06-01T09:00:00Z --kind audit "Audit ADR-007"',
" sf schedule list --due",
" sf schedule snooze 01ARZ3ND --by 1d",
" sf schedule done 01ARZ3ND",
].join("\n"),
key: [
"Usage: sf key <subcommand> [args]",
"",
"Manage provider API keys stored in ~/.sf/agent/auth.json.",
"",
"Credentials for SF runtime live in ~/.sf/agent/auth.json.",
"SF does NOT read API keys from environment variables at runtime —",
"env is only used during initial provider setup. Use `sf key set`",
"to rotate keys. auth.json is always the authoritative source.",
"",
"Subcommands:",
" set <provider> <api-key> Set or rotate the API key for a provider",
" get <provider> Show key status (last 4 chars only, never full key)",
" remove <provider> [--yes] Remove the credential (prompts unless --yes)",
" list List all providers with credential status",
"",
"Examples:",
" sf key set anthropic sk-ant-abc123 Set the Anthropic API key",
" sf key set xiaomi tp-abc123 Set the Xiaomi API key",
" sf key get anthropic Show masked key for anthropic",
" sf key remove anthropic Remove anthropic credential (confirms)",
" sf key remove anthropic --yes Remove without prompting",
" sf key list List all providers",
"",
"Security:",
" - Keys are never echoed in full. Only the last 4 characters are shown.",
" - All writes go through AuthStorage (file-locked, chmod 600).",
" - sf key remove always asks for confirmation unless --yes is passed.",
].join("\n"),
headless: [
"Usage: sf headless [flags] [command] [args...]",
"",
"Machine surface for direct SF commands. Runs the same SF flow without rendering the TUI.",
"",
"Flags:",
" --timeout N Overall timeout in ms (default: 300000)",
" --json JSONL event stream to stdout (alias for --output-format stream-json)",
" --output-format <fmt> Output format: text (default), json (structured result), stream-json (JSONL events)",
" --bare Minimal context: skip CLAUDE.md, AGENTS.md, user settings, user skills",
" --resume <id> Resume a prior headless session by ID",
" --model ID Override model",
" --supervised Forward interactive UI requests to orchestrator via stdout/stdin",
" --response-timeout N Timeout (ms) for orchestrator response (default: 30000)",
" --answers <path> Pre-supply answers and secrets (JSON file)",
" --events <types> Filter JSONL output to specific event types (comma-separated)",
"",
"Commands:",
" autonomous Run all queued product units continuously",
" next Run one unit",
" status Show progress dashboard",
" new-milestone Create a milestone from a specification document",
" query Machine snapshot: JSON state + next dispatch + costs (no LLM)",
feat(headless,gemini-cli): add sf headless usage + unify gemini quota path Adds a machine-readable headless surface for live LLM-provider usage and unifies the gemini-cli quota fetch through one helper, removing the duplication that existed between usage-bar.js and the new package. 1. snapshotGeminiCliAccount in @singularity-forge/google-gemini-cli-provider - Single source of truth for { projectId, userTierId, userTierName, paidTier, models[] } via setupUser + retrieveUserQuota. - Dedups buckets per modelId, keeping the worst (lowest remainingFraction) so consumers always see the most-restrictive window. Code Assist sometimes returns multiple buckets per model; the pessimistic choice is what every consumer needs. - discoverGeminiCliModels(cwd?) wraps it for catalog-cache callers that only need the IDs. 2. sf headless usage subcommand - New src/headless-usage.ts handler. text (default) and --json output. Uses the package's snapshot directly — no RPC child, no jiti gymnastics — matching the shape of headless-uok-status / headless-doctor. - Wired into src/headless.ts after the doctor block. - Help text adds the command line. 3. usage-bar.js refactored to delegate - fetchGeminiUsage no longer imports gemini-cli-core directly. It calls snapshotGeminiCliAccount and reshapes the result into the existing { provider, displayName, windows[] } UI contract. - Eliminates the duplicate setupUser + retrieveUserQuota code path. - The fast existsSync(~/.gemini/oauth_creds.json) pre-flight stays so unauth'd users get a friendly message without paying for OAuth bootstrap. 4. Model registry refactor (separate track committed alongside) - src/resources/extensions/sf/model-registry.ts (new) consolidates canonical model identity, capability tier, and generation tags into one source of truth that auto-model-selection, benchmark-selector, and model-router now consume instead of maintaining parallel maps. All 1487 tests pass (151 files); typecheck clean for both the package and the SF extensions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 03:42:53 +02:00
" usage Live LLM-provider usage snapshot (today: gemini-cli tier + per-model quota)",
feat(reflection): wire LLM dispatch (sf headless reflect --run) Phase 1B of the reflection layer: complete the operator-driven loop by adding actual LLM dispatch. Phase 1A (commit e161a59e2) shipped the corpus assembler + prompt template + the prompt-emit operator surface. This commit wires the dispatch end so `sf headless reflect --run` produces a real report on disk without manual model piping. Why shell-out to the gemini CLI and not SF's provider abstraction: reflection is a single-prompt one-shot inference. Going through SF's full agent dispatch would require a session, model registry, tool registration, recovery shell — overkill for "render this prompt, capture text." The gemini CLI handles auth (~/.gemini/oauth_creds.json), Code Assist project discovery, and protocol drift on its behalf. Subprocess cost is paid once per reflection (rare). Implementation: - reflection.js: runGeminiReflection(prompt, options) spawns `gemini --yolo --model <model> -p "<directive>"` and pipes the giant rendered template via stdin (gemini -p reads stdin and appends). Returns { ok, content, cleanFinish, exitCode, error, stderr }; never throws. Defaults to gemini-3-pro-preview (0% used on AI Ultra, strongest agentic model with quota). 8-minute timeout. cleanFinish detected by REFLECTION_COMPLETE terminator (emitted by the prompt template's output contract) — operator gets a warning when the report is truncated. - headless-reflect.ts: --run flag triggers dispatch + report write via writeReflectionReport. --model overrides the default. Errors surface as JSON or text per --json. Successful runs emit the report path on stdout; failures emit error + truncated stderr. - help-text.ts: documents --run and --model flags. - Tests (4 new, 13 total): use a fake `gemini` binary on PATH to exercise the spawn path without real OAuth/network — covers ok+cleanFinish, non-zero exit, hang/timeout, missing-terminator. All 1538 SF extension tests pass; typecheck clean. Phase 2 follow-up (still gated on sf-mp4rxkwb-l4baga triage-not-a-first-class-unit-type landing): reflection-pass becomes a real autonomous-loop unit type, milestone-close auto-triggers it, the report's `Recommended new self-feedback entries` section gets parsed and the entries auto-filed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 04:33:16 +02:00
" reflect Assemble reflection corpus + render prompt for cross-corpus pattern analysis (--json for raw, --run to dispatch to gemini-cli, --model <id> to override)",
2026-05-14 19:43:01 +02:00
" triage Render canonical self-feedback triage prompt (--list/--json inspect, --run writes decisions, --apply runs triage-decider -> review-code)",
" complete-slice Mark a slice complete out-of-band: complete-slice <M>/<S> [--reason <txt>]",
" skip-slice Mark a slice skipped out-of-band (placeholder/migration cleanup)",
" complete-milestone Mark a milestone complete out-of-band: complete-milestone <M> [--reason <txt>]",
" feedback add File a self_feedback entry (--summary <txt> --severity low|medium|high|critical [--kind <k>] [--evidence <t>] [--suggested-fix <t>] [--milestone M --slice S --task T] [--impact-score N] [--effort-estimate N] [--blocking] [--purpose <fragment>])",
" feedback list List self_feedback entries [--unresolved] [--severity <s>] [--purpose <fragment>] [--json]",
" feedback resolve Resolve an entry: feedback resolve <id> --reason <txt> [--evidence-kind human-clear|agent-fix|...]",
"",
"new-milestone flags:",
" --context <path> Path to spec/PRD file (use '-' for stdin)",
" --context-text <txt> Inline specification text",
" --autonomous Start autonomous mode after milestone creation",
" --verbose Show tool calls in progress output",
" --skip-pdd-check Bypass the ADR-0000 PDD-fields gate (migration escape hatch)",
"",
"Output formats:",
" text Human-readable progress on stderr (default)",
" json Collect events silently, emit one structured result on stdout at exit",
" stream-json Stream JSONL events to stdout in real time (same as --json)",
"",
"Examples:",
" sf headless Show this help",
" sf headless autonomous Run autonomous mode through the machine surface",
" sf headless next Run one unit",
" sf headless --output-format json autonomous Structured JSON result on stdout",
" sf headless --json status Machine-readable JSONL stream",
" sf headless --timeout 60000 autonomous Run autonomous with 1-minute timeout",
" sf headless --bare autonomous Minimal context (CI/ecosystem use)",
" sf headless --resume abc123 autonomous Resume a prior session",
" sf headless new-milestone --context spec.md Create milestone from file",
" cat spec.md | sf headless new-milestone --context - From stdin",
" sf headless new-milestone --context spec.md --autonomous Create + run autonomously",
" sf headless --supervised autonomous Supervised orchestrator mode",
" sf headless --answers answers.json autonomous With pre-supplied answers",
" sf headless --events agent_end,extension_ui_request autonomous Filtered event stream",
" sf headless query Instant machine JSON state snapshot",
" sf headless status uok UOK gate health table (last 24h)",
" sf headless status uok --json UOK gate health as JSON",
" sf headless triage --list Self-feedback queue digest (impact↓ effort↑ ts↑)",
" sf headless triage | sf-some-model Pipe triage prompt to any model",
" sf headless triage --run Dispatch triage to default model + write decisions",
2026-05-14 19:43:01 +02:00
" sf headless triage --apply Apply via triage-decider, then gate with review-code",
" sf headless reflect Render reflection prompt for piping",
" sf headless reflect --run Dispatch reflection + write report",
" sf headless complete-slice M010/S03 Flip M010/S03 to status=complete (idempotent)",
" sf headless skip-slice M003/S01 --reason \"migration placeholder\" Mark placeholder slice skipped",
" sf headless complete-milestone M010 Flip milestone to status=complete",
" sf headless feedback add --severity high --summary \"30K truncate drops the why\" File self-feedback",
" sf headless feedback add --summary \"...\" --purpose \"M015 vision: ...\" Anchor to a purpose (ADR-0000)",
" sf headless feedback list --unresolved Pending self-feedback entries",
" sf headless feedback list --purpose \"M015 vision\" Triage by purpose anchor",
" sf headless feedback resolve sf-mp4xxx --reason \"shipped in 7b85a6\" Resolve an entry",
"",
"Exit codes: 0 = success, 1 = error/timeout, 10 = blocked, 11 = cancelled",
].join("\n"),
};
// Alias: `sf wt --help` → same as `sf worktree --help`
SUBCOMMAND_HELP["wt"] = SUBCOMMAND_HELP["worktree"];
export function printHelp(version: string): void {
process.stdout.write(`SF v${version} — Singularity Forge\n\n`);
process.stdout.write("Usage: sf [options] [message...]\n\n");
process.stdout.write("Options:\n");
process.stdout.write(
" --mode <text|json|rpc> Session I/O mode: text/json print format or RPC protocol\n",
);
process.stdout.write(" --print, -p Single-shot print mode\n");
process.stdout.write(
" --continue, -c Resume the most recent session\n",
);
process.stdout.write(
" --worktree, -w [name] Start in an isolated worktree (auto-named if omitted)\n",
);
process.stdout.write(
" --model <id> Override model (e.g. provider/model-id)\n",
);
process.stdout.write(
" --no-session Disable session persistence\n",
);
process.stdout.write(
" --extension <path> Load additional extension\n",
);
process.stdout.write(" --tools <a,b,c> Restrict available tools\n");
process.stdout.write(
" --list-models [search] List available models and exit\n",
);
process.stdout.write(
" --discover Force live verification for filtered --list-models\n",
);
process.stdout.write(" --version, -v Print version and exit\n");
process.stdout.write(" --help, -h Print this help and exit\n");
process.stdout.write("\nSubcommands:\n");
process.stdout.write(" config Re-run the setup wizard\n");
process.stdout.write(
" install <source> Install a package/extension source\n",
);
process.stdout.write(
" remove <source> Remove an installed package source\n",
);
process.stdout.write(
" list List installed package sources\n",
);
process.stdout.write(
" update Update SF to the latest version\n",
);
process.stdout.write(
" sessions List and resume a past session\n",
);
process.stdout.write(" logs tail|follow Follow merged SF logs\n");
process.stdout.write(
" status --live Show aggregate project status\n",
);
process.stdout.write(" dash Alias for status --live\n");
process.stdout.write(" stats models Summarize model outcomes\n");
process.stdout.write(
" worktree <cmd> Manage worktrees (list, merge, clean, remove)\n",
);
process.stdout.write(
" autonomous [args] Run autonomous mode through the machine surface (pipeable)\n",
);
process.stdout.write(
" headless [cmd] [args] Machine surface for direct SF commands\n",
);
process.stdout.write(
" graph <subcommand> Manage knowledge graph (build, query, status, diff)\n",
);
process.stdout.write(
" plan <cmd> Manage SF planning artifacts and docs exports\n",
);
2026-05-06 06:02:46 +02:00
process.stdout.write(
" schedule <cmd> Manage time-bound reminders (add, list, done, cancel, snooze, run)\n",
);
process.stdout.write(
" key <set|get|remove|list> Manage provider API keys in auth.json\n",
);
process.stdout.write(
"\nRun sf <subcommand> --help for subcommand-specific help.\n",
);
}
export function printSubcommandHelp(
subcommand: string,
version: string,
): boolean {
const help = SUBCOMMAND_HELP[subcommand];
if (!help) return false;
process.stdout.write(`SF v${version} — Singularity Forge\n\n`);
process.stdout.write(help + "\n");
return true;
}