{"owner":"yc-software","repo":"qm","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md"],"skills":{"AGENTS.md":"# qm\n\nTo run and test, see [`README.md`](./README.md).\n\n## Working on the code\n\nTwo habits that keep task-focused changes from scarring the rest of the repo:\n\n- **Fix every instance, not just the reported one.** When you find a bug or a pattern\n  worth changing, grep the whole repo (`src/`, `plugins/`, `test/`, `scripts/`) for the\n  same pattern and fix all of it in the same change. One autocorrected call site with\n  five untouched siblings is a regression waiting to be rediscovered.\n- **Fixes should make the system simpler, not more complex.** Prefer removing or\n  consolidating code over adding a new layer, flag, or special case. If a fix grows the\n  system's surface area, look for the version that shrinks it.\n- **Never leave comments in the repo.** The standard is zero comments: no explanatory\n  comments or docblocks, TODO/FIXME notes, lint/type suppression directives, or commented-out\n  code. Express intent through names, structure, and tests; put rationale in commit messages or\n  PR descriptions. Interpreter shebangs are executable directives, not comments.\n- **Solve at the layer all paths flow through.** Before patching a call site, ask\n  whether the fix belongs in the shared helper, the store interface, or the base\n  module instead. Check for an existing helper before writing a new one-liner.\n  The helper homes: `src/util/errors.ts` (errMessage/swallow), `src/util/async.ts`\n  (sleep, createKeyedQueue), `src/util/sweeper.ts` (periodic loops),\n  `src/sandbox/process-poll.ts` (process polling/liveness), `src/memory/notebook.ts`\n  (memory line grammar). Plugins are separate packages and keep their own local\n  copies rather than importing core code — the one exception is the shared\n  `plugins/chassis` package (the sanctioned home for the plugin↔core plumbing:\n  source-auth signer, signed core-client, node:http helpers, error helpers, CORE_*\n  env), imported by relative path and never importing core. The bar cuts both ways:\n  don't manufacture an abstraction for a pattern with one caller.\n- **Never merge to `main` without a fresh-context pass that tries to break the change.**\n  Not a blessing — hunt for the bug, the missed edge case, the unstated assumption, the\n  thing that regresses. Always dispatch `/code-review` or an independent review agent that\n  did not watch you write the change: the context that produced a diff already believes it\n  is correct, and that belief is the bias review exists to defeat. Never self-review in the\n  authoring context, however small the diff; a green CI run is not review either. What\n  scales with risk is how deep the reviewer goes — a change with a narrow blast radius\n  warrants one reviewer at modest effort scoped to the diff, while core control flow, auth\n  and credentials, data loss or migrations, concurrency and retry logic, spend, public API\n  contracts, the shared helpers above that every path flows through, or a diff too large to\n  hold in your head warrant high effort and several reviewers with distinct lenses. Judge\n  blast radius by checking callers, not by counting files — a one-line edit to a helper with\n  fifty importers is not a small change. The reviewer, not the author, has the last word on\n  depth: a modest pass that spots risk it wasn't scoped for escalates on its own initiative\n  rather than staying in its lane. Resolve what they find before merging.\n- **Verify locally with the affected tests, not the whole suite.** Run the tests covering\n  what you changed plus typecheck and lint, then push and let CI be the full gate — CI\n  shards the suite across parallel runners, and reproducing that serially costs several\n  times the wall clock for the same signal. Judge \"affected\" by callers rather than by diff\n  size, for the same reason as above; run everything locally when you can't tell what a\n  change reaches.\n- **Verify non-trivial behavior changes in a live dev instance before opening a PR.**\n  When a change is substantial enough that unit tests alone won't prove it works\n  end-to-end — new or changed agent behavior, or anything touching the Slack/web\n  surfaces, orchestrator, directory, or cron flows — boot this worktree with the\n  `/dev-instance` skill and exercise it through a browser against the configured Slack\n  development workspace before opening a PR. Do this Slack QA in **Firefox**, never the\n  Slack Mac app, and don't ask permission first — do it on your own; don't wait to be\n  asked. Skip it for trivial refactors, docs, config, or pure-logic changes already\n  covered by tests.\n- **Demo every front-end change in the PR.** Anything an operator or user sees\n  rendered — admin/web/portal UI, Slack surfaces, emails — ships with a way for a\n  reviewer to see the result without booting it. Prefer a link to a live demo app\n  (e.g. the built UI served against a small mock API, published internally) so the\n  reviewer can click around the real thing; note in the PR what's mocked. Fall back\n  to screenshots only when a live demo isn't practical (e.g. Slack surfaces, emails),\n  and then show the after state (before/after for changes to something that existed),\n  rendered against realistic data.\n\n## Private forks\n\nOrganizations run qm from private forks of this repository. A private fork is a\nstandalone private repository whose history begins as a clone of qm. Everything\norganization-specific is confined to `deploy/layers/<org>/`, and every file outside\nthat directory, which these rules call core, stays byte-identical to upstream. Core\nhere covers the plugins, the CLI, the docs, and CI as much as the runtime under\n`src/`. A private fork is created with a plain clone and never with\nGitHub's fork feature, because a GitHub fork of a public repository cannot be made\nprivate and its commits stay fetchable by SHA from the public side. The README section\n\"Customize your instance\" gives the creation procedure.\n\nBefore you act, determine which repository this checkout is by running `git remote -v`.\nIf `origin` points at `yc-software/qm`, you are in upstream qm. If `origin`\npoints anywhere else, you are in a private fork, and five rules apply. Do not edit core;\na change to core belongs in upstream qm, and the `upstream-pr` skill sends it there\nwithout leaking organization context. Keep every organization-specific file under\n`deploy/layers/<org>/`. Sync from upstream with the `update-qm` skill, which merges and\nnever rebases. Pass `--repo` to every `gh` command, because `gh` may otherwise pick the\nupstream repository through the `upstream` remote and read or edit the wrong\nrepository's pull requests. Never reference an upstream issue or pull request by number\n(`yc-software/qm#123`) in a fork's PRs, issues, comments, or commit messages: GitHub\nmirrors such mentions onto the referenced upstream item as a permanent timeline event,\nso the fork's existence and the mentioning title become visible to whoever GitHub\ndecides may see them. Name upstream work in plain words instead.\n\n## Durable by default\n\nA recurring mistake: stashing state the system later relies on in process memory. The\ncore runs blue-green and multi-instance — an in-memory `Map` or ring buffer is\nper-instance and wiped by every deploy. Anything an operator or the system reads back\nlater (audit, logs, resolved config, queued or in-flight work) must live in a durable\nstore, never RAM alone. RAM-only is fine only as a cache in front of a durable store, or\nfor genuinely disposable, re-derivable state. If you're adding a log, audit, queue, or\nresolved config, back it with Postgres; the spec's data-model & durability section tracks the gaps.\n\n> `CLAUDE.md` is a symlink to `AGENTS.md`, so every tool (Claude Code, Codex,\n> Cursor, …) reads the same guidance from this one file. If a tool-specific\n> deviation ever becomes necessary, replace the symlink with a real file in the\n> commit that introduces the deviation.\n"},"files":{"AGENTS.md":"# qm\n\nTo run and test, see [`README.md`](./README.md).\n\n## Working on the code\n\nTwo habits that keep task-focused changes from scarring the rest of the repo:\n\n- **Fix every instance, not just the reported one.** When you find a bug or a pattern\n  worth changing, grep the whole repo (`src/`, `plugins/`, `test/`, `scripts/`) for the\n  same pattern and fix all of it in the same change. One autocorrected call site with\n  five untouched siblings is a regression waiting to be rediscovered.\n- **Fixes should make the system simpler, not more complex.** Prefer removing or\n  consolidating code over adding a new layer, flag, or special case. If a fix grows the\n  system's surface area, look for the version that shrinks it.\n- **Never leave comments in the repo.** The standard is zero comments: no explanatory\n  comments or docblocks, TODO/FIXME notes, lint/type suppression directives, or commented-out\n  code. Express intent through names, structure, and tests; put rationale in commit messages or\n  PR descriptions. Interpreter shebangs are executable directives, not comments.\n- **Solve at the layer all paths flow through.** Before patching a call site, ask\n  whether the fix belongs in the shared helper, the store interface, or the base\n  module instead. Check for an existing helper before writing a new one-liner.\n  The helper homes: `src/util/errors.ts` (errMessage/swallow), `src/util/async.ts`\n  (sleep, createKeyedQueue), `src/util/sweeper.ts` (periodic loops),\n  `src/sandbox/process-poll.ts` (process polling/liveness), `src/memory/notebook.ts`\n  (memory line grammar). Plugins are separate packages and keep their own local\n  copies rather than importing core code — the one exception is the shared\n  `plugins/chassis` package (the sanctioned home for the plugin↔core plumbing:\n  source-auth signer, signed core-client, node:http helpers, error helpers, CORE_*\n  env), imported by relative path and never importing core. The bar cuts both ways:\n  don't manufacture an abstraction for a pattern with one caller.\n- **Never merge to `main` without a fresh-context pass that tries to break the change.**\n  Not a blessing — hunt for the bug, the missed edge case, the unstated assumption, the\n  thing that regresses. Always dispatch `/code-review` or an independent review agent that\n  did not watch you write the change: the context that produced a diff already believes it\n  is correct, and that belief is the bias review exists to defeat. Never self-review in the\n  authoring context, however small the diff; a green CI run is not review either. What\n  scales with risk is how deep the reviewer goes — a change with a narrow blast radius\n  warrants one reviewer at modest effort scoped to the diff, while core control flow, auth\n  and credentials, data loss or migrations, concurrency and retry logic, spend, public API\n  contracts, the shared helpers above that every path flows through, or a diff too large to\n  hold in your head warrant high effort and several reviewers with distinct lenses. Judge\n  blast radius by checking callers, not by counting files — a one-line edit to a helper with\n  fifty importers is not a small change. The reviewer, not the author, has the last word on\n  depth: a modest pass that spots risk it wasn't scoped for escalates on its own initiative\n  rather than staying in its lane. Resolve what they find before merging.\n- **Verify locally with the affected tests, not the whole suite.** Run the tests covering\n  what you changed plus typecheck and lint, then push and let CI be the full gate — CI\n  shards the suite across parallel runners, and reproducing that serially costs several\n  times the wall clock for the same signal. Judge \"affected\" by callers rather than by diff\n  size, for the same reason as above; run everything locally when you can't tell what a\n  change reaches.\n- **Verify non-trivial behavior changes in a live dev instance before opening a PR.**\n  When a change is substantial enough that unit tests alone won't prove it works\n  end-to-end — new or changed agent behavior, or anything touching the Slack/web\n  surfaces, orchestrator, directory, or cron flows — boot this worktree with the\n  `/dev-instance` skill and exercise it through a browser against the configured Slack\n  development workspace before opening a PR. Do this Slack QA in **Firefox**, never the\n  Slack Mac app, and don't ask permission first — do it on your own; don't wait to be\n  asked. Skip it for trivial refactors, docs, config, or pure-logic changes already\n  covered by tests.\n- **Demo every front-end change in the PR.** Anything an operator or user sees\n  rendered — admin/web/portal UI, Slack surfaces, emails — ships with a way for a\n  reviewer to see the result without booting it. Prefer a link to a live demo app\n  (e.g. the built UI served against a small mock API, published internally) so the\n  reviewer can click around the real thing; note in the PR what's mocked. Fall back\n  to screenshots only when a live demo isn't practical (e.g. Slack surfaces, emails),\n  and then show the after state (before/after for changes to something that existed),\n  rendered against realistic data.\n\n## Private forks\n\nOrganizations run qm from private forks of this repository. A private fork is a\nstandalone private repository whose history begins as a clone of qm. Everything\norganization-specific is confined to `deploy/layers/<org>/`, and every file outside\nthat directory, which these rules call core, stays byte-identical to upstream. Core\nhere covers the plugins, the CLI, the docs, and CI as much as the runtime under\n`src/`. A private fork is created with a plain clone and never with\nGitHub's fork feature, because a GitHub fork of a public repository cannot be made\nprivate and its commits stay fetchable by SHA from the public side. The README section\n\"Customize your instance\" gives the creation procedure.\n\nBefore you act, determine which repository this checkout is by running `git remote -v`.\nIf `origin` points at `yc-software/qm`, you are in upstream qm. If `origin`\npoints anywhere else, you are in a private fork, and five rules apply. Do not edit core;\na change to core belongs in upstream qm, and the `upstream-pr` skill sends it there\nwithout leaking organization context. Keep every organization-specific file under\n`deploy/layers/<org>/`. Sync from upstream with the `update-qm` skill, which merges and\nnever rebases. Pass `--repo` to every `gh` command, because `gh` may otherwise pick the\nupstream repository through the `upstream` remote and read or edit the wrong\nrepository's pull requests. Never reference an upstream issue or pull request by number\n(`yc-software/qm#123`) in a fork's PRs, issues, comments, or commit messages: GitHub\nmirrors such mentions onto the referenced upstream item as a permanent timeline event,\nso the fork's existence and the mentioning title become visible to whoever GitHub\ndecides may see them. Name upstream work in plain words instead.\n\n## Durable by default\n\nA recurring mistake: stashing state the system later relies on in process memory. The\ncore runs blue-green and multi-instance — an in-memory `Map` or ring buffer is\nper-instance and wiped by every deploy. Anything an operator or the system reads back\nlater (audit, logs, resolved config, queued or in-flight work) must live in a durable\nstore, never RAM alone. RAM-only is fine only as a cache in front of a durable store, or\nfor genuinely disposable, re-derivable state. If you're adding a log, audit, queue, or\nresolved config, back it with Postgres; the spec's data-model & durability section tracks the gaps.\n\n> `CLAUDE.md` is a symlink to `AGENTS.md`, so every tool (Claude Code, Codex,\n> Cursor, …) reads the same guidance from this one file. If a tool-specific\n> deviation ever becomes necessary, replace the symlink with a real file in the\n> commit that introduces the deviation.\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","content":"# qm\n\nTo run and test, see [`README.md`](./README.md).\n\n## Working on the code\n\nTwo habits that keep task-focused changes from scarring the rest of the repo:\n\n- **Fix every instance, not just the reported one.** When you find a bug or a pattern\n  worth changing, grep the whole repo (`src/`, `plugins/`, `test/`, `scripts/`) for the\n  same pattern and fix all of it in the same change. One autocorrected call site with\n  five untouched siblings is a regression waiting to be rediscovered.\n- **Fixes should make the system simpler, not more complex.** Prefer removing or\n  consolidating code over adding a new layer, flag, or special case. If a fix grows the\n  system's surface area, look for the version that shrinks it.\n- **Never leave comments in the repo.** The standard is zero comments: no explanatory\n  comments or docblocks, TODO/FIXME notes, lint/type suppression directives, or commented-out\n  code. Express intent through names, structure, and tests; put rationale in commit messages or\n  PR descriptions. Interpreter shebangs are executable directives, not comments.\n- **Solve at the layer all paths flow through.** Before patching a call site, ask\n  whether the fix belongs in the shared helper, the store interface, or the base\n  module instead. Check for an existing helper before writing a new one-liner.\n  The helper homes: `src/util/errors.ts` (errMessage/swallow), `src/util/async.ts`\n  (sleep, createKeyedQueue), `src/util/sweeper.ts` (periodic loops),\n  `src/sandbox/process-poll.ts` (process polling/liveness), `src/memory/notebook.ts`\n  (memory line grammar). Plugins are separate packages and keep their own local\n  copies rather than importing core code — the one exception is the shared\n  `plugins/chassis` package (the sanctioned home for the plugin↔core plumbing:\n  source-auth signer, signed core-client, node:http helpers, error helpers, CORE_*\n  env), imported by relative path and never importing core. The bar cuts both ways:\n  don't manufacture an abstraction for a pattern with one caller.\n- **Never merge to `main` without a fresh-context pass that tries to break the change.**\n  Not a blessing — hunt for the bug, the missed edge case, the unstated assumption, the\n  thing that regresses. Always dispatch `/code-review` or an independent review agent that\n  did not watch you write the change: the context that produced a diff already believes it\n  is correct, and that belief is the bias review exists to defeat. Never self-review in the\n  authoring context, however small the diff; a green CI run is not review either. What\n  scales with risk is how deep the reviewer goes — a change with a narrow blast radius\n  warrants one reviewer at modest effort scoped to the diff, while core control flow, auth\n  and credentials, data loss or migrations, concurrency and retry logic, spend, public API\n  contracts, the shared helpers above that every path flows through, or a diff too large to\n  hold in your head warrant high effort and several reviewers with distinct lenses. Judge\n  blast radius by checking callers, not by counting files — a one-line edit to a helper with\n  fifty importers is not a small change. The reviewer, not the author, has the last word on\n  depth: a modest pass that spots risk it wasn't scoped for escalates on its own initiative\n  rather than staying in its lane. Resolve what they find before merging.\n- **Verify locally with the affected tests, not the whole suite.** Run the tests covering\n  what you changed plus typecheck and lint, then push and let CI be the full gate — CI\n  shards the suite across parallel runners, and reproducing that serially costs several\n  times the wall clock for the same signal. Judge \"affected\" by callers rather than by diff\n  size, for the same reason as above; run everything locally when you can't tell what a\n  change reaches.\n- **Verify non-trivial behavior changes in a live dev instance before opening a PR.**\n  When a change is substantial enough that unit tests alone won't prove it works\n  end-to-end — new or changed agent behavior, or anything touching the Slack/web\n  surfaces, orchestrator, directory, or cron flows — boot this worktree with the\n  `/dev-instance` skill and exercise it through a browser against the configured Slack\n  development workspace before opening a PR. Do this Slack QA in **Firefox**, never the\n  Slack Mac app, and don't ask permission first — do it on your own; don't wait to be\n  asked. Skip it for trivial refactors, docs, config, or pure-logic changes already\n  covered by tests.\n- **Demo every front-end change in the PR.** Anything an operator or user sees\n  rendered — admin/web/portal UI, Slack surfaces, emails — ships with a way for a\n  reviewer to see the result without booting it. Prefer a link to a live demo app\n  (e.g. the built UI served against a small mock API, published internally) so the\n  reviewer can click around the real thing; note in the PR what's mocked. Fall back\n  to screenshots only when a live demo isn't practical (e.g. Slack surfaces, emails),\n  and then show the after state (before/after for changes to something that existed),\n  rendered against realistic data.\n\n## Private forks\n\nOrganizations run qm from private forks of this repository. A private fork is a\nstandalone private repository whose history begins as a clone of qm. Everything\norganization-specific is confined to `deploy/layers/<org>/`, and every file outside\nthat directory, which these rules call core, stays byte-identical to upstream. Core\nhere covers the plugins, the CLI, the docs, and CI as much as the runtime under\n`src/`. A private fork is created with a plain clone and never with\nGitHub's fork feature, because a GitHub fork of a public repository cannot be made\nprivate and its commits stay fetchable by SHA from the public side. The README section\n\"Customize your instance\" gives the creation procedure.\n\nBefore you act, determine which repository this checkout is by running `git remote -v`.\nIf `origin` points at `yc-software/qm`, you are in upstream qm. If `origin`\npoints anywhere else, you are in a private fork, and five rules apply. Do not edit core;\na change to core belongs in upstream qm, and the `upstream-pr` skill sends it there\nwithout leaking organization context. Keep every organization-specific file under\n`deploy/layers/<org>/`. Sync from upstream with the `update-qm` skill, which merges and\nnever rebases. Pass `--repo` to every `gh` command, because `gh` may otherwise pick the\nupstream repository through the `upstream` remote and read or edit the wrong\nrepository's pull requests. Never reference an upstream issue or pull request by number\n(`yc-software/qm#123`) in a fork's PRs, issues, comments, or commit messages: GitHub\nmirrors such mentions onto the referenced upstream item as a permanent timeline event,\nso the fork's existence and the mentioning title become visible to whoever GitHub\ndecides may see them. Name upstream work in plain words instead.\n\n## Durable by default\n\nA recurring mistake: stashing state the system later relies on in process memory. The\ncore runs blue-green and multi-instance — an in-memory `Map` or ring buffer is\nper-instance and wiped by every deploy. Anything an operator or the system reads back\nlater (audit, logs, resolved config, queued or in-flight work) must live in a durable\nstore, never RAM alone. RAM-only is fine only as a cache in front of a durable store, or\nfor genuinely disposable, re-derivable state. If you're adding a log, audit, queue, or\nresolved config, back it with Postgres; the spec's data-model & durability section tracks the gaps.\n\n> `CLAUDE.md` is a symlink to `AGENTS.md`, so every tool (Claude Code, Codex,\n> Cursor, …) reads the same guidance from this one file. If a tool-specific\n> deviation ever becomes necessary, replace the symlink with a real file in the\n> commit that introduces the deviation.\n","category":"root","tokens":1963}]}