diff --git a/.codex/config.toml b/.codex/config.toml new file mode 100644 index 000000000..9bfd3b5ae --- /dev/null +++ b/.codex/config.toml @@ -0,0 +1,5 @@ +# Codex FirstMate background profile. +# Not YOLO: workspace sandbox stays active; blocked boundary work escalates on request. +sandbox_mode = "workspace-write" +approval_policy = "on-request" +approvals_reviewer = "auto_review" diff --git a/.codex/hooks.json b/.codex/hooks.json index 337bd0a68..e51d59dd8 100644 --- a/.codex/hooks.json +++ b/.codex/hooks.json @@ -24,6 +24,11 @@ "type": "command", "command": "bash -lc 'payload=$(cat 2>/dev/null || true); [ -n \"$payload\" ] || exit 0; command -v jq >/dev/null 2>&1 || exit 0; root=$(pwd -P) || exit 0; [ -x \"$root/bin/fm-cd-pretool-check.sh\" ] || exit 0; [ -f \"$root/AGENTS.md\" ] || exit 0; [ -f \"$root/.codex/hooks.json\" ] || exit 0; jq -e \"any(.hooks.PreToolUse[]?.hooks[]?.command?; type == \\\"string\\\" and contains(\\\"fm-cd-pretool-check.sh\\\"))\" \"$root/.codex/hooks.json\" >/dev/null 2>&1 || exit 0; printf \"%s\" \"$payload\" | \"$root/bin/fm-cd-pretool-check.sh\"'", "timeout": 10 + }, + { + "type": "command", + "command": "bash -lc 'command -v graphify >/dev/null 2>&1 || exit 0; graphify hook-check'", + "timeout": 10 } ] } diff --git a/.gitignore b/.gitignore index 5ed2da0c3..d1fb69b11 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ config/backend config/x-mode.env config/cmux-socket-password config/wedge-alarm +graphify-out/ diff --git a/AGENTS.md b/AGENTS.md index cdf7b1682..e4a4df318 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -37,9 +37,9 @@ Hard rules, in priority order: If work failed, say so plainly with the evidence. You may maintain this repo's private operational state directly. -Shared tracked material is `AGENTS.md`, `README.md`, `CONTRIBUTING.md`, `.tasks.toml`, `.github/workflows/`, `bin/`, `.agents/skills/`, and public `skills/`. +Shared tracked material is `AGENTS.md`, `README.md`, `CONTRIBUTING.md`, `.tasks.toml`, `.codex/`, `.github/workflows/`, `bin/`, `.agents/skills/`, and public `skills/`. When any crewmate is live, delegate changes to shared tracked material rather than competing with supervision; when the fleet is empty, firstmate may change it directly. -This repo is a shared template, while `.env`, `data/`, `state/`, `config/`, `projects/`, and `.no-mistakes/` are captain-private and gitignored. +This repo is a shared template, while `.env`, `data/`, `state/`, `config/`, `projects/`, `.no-mistakes/`, and `graphify-out/` are captain-private and gitignored. Ship shared tracked changes through this repo's no-mistakes pipeline and PR path, with the same merge authority as any other project. Never add an agent name as a commit co-author. @@ -58,6 +58,7 @@ CONTRIBUTING.md contributor workflow and repo conventions README.md public overview and development notes .github/workflows/ shared CI and PR enforcement, committed .tasks.toml tracked tasks-axi markdown backend config for the default backlog backend (section 10) +.codex/ tracked Codex primary profile plus SessionStart, PreToolUse, and Stop hooks (docs/configuration.md "Codex profile and Graphify hooks") .agents/skills/ firstmate-loaded internal skills, committed; each carries metadata.internal=true for installers .claude/skills symlink to .agents/skills for claude compatibility skills/ standalone public installer-facing skills, committed; not loaded by firstmate @@ -81,6 +82,7 @@ data/ personal fleet records; LOCAL, gitignored as a whole /brief.md per-task crewmate brief, or per-secondmate charter brief when kind=secondmate /report.md scout task deliverable, written by the crewmate; survives teardown projects/ cloned repos; gitignored; READ-ONLY for you +graphify-out/ local Graphify knowledge graph artifacts; gitignored, expected to drift after hook or incremental updates state/ volatile runtime signals; gitignored .status appended by crewmates: ": " wake-event lines, not current-state truth .turn-ended touched by turn-end hooks @@ -476,3 +478,19 @@ Keep this file for knowledge useful to almost every future agent session in this Do not repeat what the codebase already shows; point to the authoritative file, skill, command, or doc. Prefer rewriting or pruning existing entries over appending new ones. When updating this file, preserve every safety boundary and keep the always-loaded contract concise. + +## Graphify + +This project may have a knowledge graph at graphify-out/ with god nodes, community structure, and cross-file relationships. + +When the user types `/graphify`, use the installed graphify skill or instructions before doing anything else. + +Rules: +- For codebase questions, first run `graphify query ""` when graphify-out/graph.json exists. + Use `graphify path "" ""` for relationships and `graphify explain ""` for focused concepts. + These return a scoped subgraph, usually much smaller than GRAPH_REPORT.md or raw grep output. +- Dirty graphify-out/ files are expected after hooks or incremental updates; dirty graph files are not a reason to skip graphify. + Only skip graphify if the task is about stale or incorrect graph output, or the user explicitly says not to use it. +- If graphify-out/wiki/index.md exists, use it for broad navigation instead of raw source browsing. +- Read graphify-out/GRAPH_REPORT.md only for broad architecture review or when query/path/explain do not surface enough context. +- After modifying code, run `graphify update .` to keep the graph current (AST-only, no API cost). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4e7bd8154..c7ac11502 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,13 +34,14 @@ See the [no-mistakes quick start](https://kunchenguid.github.io/no-mistakes/star - This repo is a template for running a firstmate orchestrator agent. `AGENTS.md` is the agent's main job description and names when to load bundled firstmate skills; `CLAUDE.md` is a symlink to it, and `.claude/skills` is a symlink to `.agents/skills`. -- Only shared material is tracked: `AGENTS.md`, `README.md`, `CONTRIBUTING.md`, `.tasks.toml`, `.github/workflows/`, `bin/`, `.agents/skills/`, and `skills/`. +- Only shared material is tracked: `AGENTS.md`, `README.md`, `CONTRIBUTING.md`, `.tasks.toml`, `.codex/`, `.github/workflows/`, `bin/`, `.agents/skills/`, and `skills/`. `.agents/skills/` holds agent-loaded skills that assume a live firstmate home and carry `metadata.internal: true` so installers such as [skills.sh](https://skills.sh) hide them from discovery; `skills/` holds standalone, installer-facing public skills with no firstmate dependency (see the README's "Two-tier skill layout"). - Everything personal to one captain's fleet (`.env`, `data/`, `state/`, `config/`, `projects/`, `.no-mistakes/`) is gitignored; never commit it. + Everything personal to one captain's fleet (`.env`, `data/`, `state/`, `config/`, `projects/`, `.no-mistakes/`, `graphify-out/`) is gitignored; never commit it. The root `.tasks.toml` is tracked `tasks-axi` config for `data/backlog.md`; compatible `tasks-axi` is the default backend for routine backlog mutations, with the compatibility definition owned by [`docs/configuration.md`](docs/configuration.md) ("Backlog backend"). A local `config/backlog-backend=manual` opt-out forces firstmate's routine backlog updates to hand-editing and stays gitignored; validated secondmate handoffs still delegate through `tasks-axi mv`. A local `config/backend` file explicitly overrides runtime auto-detection for new task endpoints and stays gitignored; spawn-supported values are `tmux` plus experimental `herdr`, `zellij`, `orca`, and `cmux`, while `codex-app` is documented only in `docs/codex-app-backend.md`. It does not make `data/` tracked. + The tracked `.codex/` files are firstmate's Codex primary profile and project hooks, not personal Codex settings. - Helper scripts in `bin/` are plain bash. Each starts with a usage header comment; keep it accurate when you change behavior. Test scripts and helpers in `tests/` are plain bash too. diff --git a/README.md b/README.md index 407aa376d..08ee7b3cd 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ For larger fleets, you can opt in to persistent secondmates: second mates that a firstmate is not a model, not a harness, not a skill, not an MCP server, and not a CLI. firstmate is an agent distro for running a crew of agents. An agent distro is a portable directory of instructions, skills, tooling, policies, and state conventions that turns a general-purpose agent into a specialized one. -There is no app to install: the cloned repo is the distro - `AGENTS.md`, bundled firstmate skills, and helper scripts that any terminal coding agent can follow. +There is no app to install: the cloned repo is the distro - `AGENTS.md`, bundled firstmate skills, tracked harness hooks and profiles, and helper scripts that any terminal coding agent can follow. Launching a supported harness inside it instantiates your first mate - and makes you the captain. ## Features @@ -183,7 +183,7 @@ Firstmate's skills live in two separate places with different audiences: ## Documentation - [docs/architecture.md](docs/architecture.md) - how the crew, supervision, worktrees, secondmates, and project modes work. -- [docs/configuration.md](docs/configuration.md) - environment variables, `FM_HOME`, runtime backend selection, optional X mode, the files you set, and harness support. +- [docs/configuration.md](docs/configuration.md) - environment variables, `FM_HOME`, runtime backend selection, optional X mode, Codex profile and Graphify hook configuration, the files you set, and harness support. - [docs/wedge-alarm.md](docs/wedge-alarm.md) - configure the active alert for an away-mode escalation delivery that gets stuck. - [docs/tmux-backend.md](docs/tmux-backend.md) - setup guide for the tmux reference backend: prerequisites, attaching, and watching crew windows. - [docs/herdr-backend.md](docs/herdr-backend.md) - setup guide for the experimental herdr backend, plus its verification notes and known gaps. diff --git a/bin/fm-afk-launch.sh b/bin/fm-afk-launch.sh index a6ddcbcc6..da6947c93 100755 --- a/bin/fm-afk-launch.sh +++ b/bin/fm-afk-launch.sh @@ -77,9 +77,9 @@ fm_afk_launch_lock_owned() { } fm_afk_launch_lock_acquire() { - local i incomplete=0 identity + local _ incomplete=0 identity mkdir -p "$FM_AFK_LAUNCH_STATE" || return 1 - for i in $(seq 1 200); do + for _ in $(seq 1 200); do if mkdir "$FM_AFK_LAUNCH_LOCK" 2>/dev/null; then if ! printf '%s' "$$" > "$FM_AFK_LAUNCH_LOCK/pid"; then rm -rf "$FM_AFK_LAUNCH_LOCK" @@ -257,12 +257,12 @@ fm_afk_launch_terminal_alive() { # } fm_afk_launch_wait_ready() { # - local backend=$1 target=$2 i + local backend=$1 target=$2 _ if [ -n "${FM_AFK_LAUNCH_ENTRY:-}" ]; then fm_afk_launch_terminal_alive "$backend" "$target" return fi - for i in $(seq 1 100); do + for _ in $(seq 1 100); do daemon_lock_held_by_live_daemon && return 0 fm_afk_launch_terminal_alive "$backend" "$target" || return 1 sleep 0.05 @@ -287,8 +287,8 @@ fm_afk_launch_commit_terminal() { # [already-recorde } fm_afk_launch_herdr_recover_created() { #