agentleFS
chippingwaychippingway/chipping-orchestrator/.agents/skills/develop/SKILL.md

develop

Skill18 starsChanged 8 days agoApache-2.0View on GitHub

Project conventions and recurring gotchas for implementer agents working on chipping-orchestrator. Use before committing any change in orchestrator/, tests/, or docs/.

28 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use scope, sync and 9 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • YuriNachosSkill

    scope

    Configure claude-scope status line widgets for Claude Code. Use when user wants to customize widgets, change theme, reorder elements, or modify display style.

    Also in 6 projects that use this

  • MicrosoftSkill

    sync

    Sync the current session branch with its upstream branch, or publish the current session branch to a remote. Use when the user asks to sync a branch, pull latest changes, rebase onto upstream, push current branch, publish branch, or set upstream.

    Also in 6 projects that use this

  • nicolasestremSkill

    document

    Create focused documentation for specific components or features

    Also in 5 projects that use this

  • kt057Skill

    check

    lint, typecheck, test を一括実行して結果をサマリーする

    Also in 5 projects that use this

  • Harut8Skill

    architect

    Also in 9 projects that use this

  • AnthropicSkill

    debug

    Structured debugging session — reproduce, isolate, diagnose, and fix. Trigger with an error message or stack trace, "this works in staging but not prod", "something broke after the deploy", or when behavior diverges from expected and the cause isn't obvious.

    Also in 9 projects that use this

The file

Show its rules and text

We split this skill into the rules it gives an agent

20 rules. 0 are common, 14 are distinctive, and 6 are very specific to this project.

  • 0

    Common

    Most of the 23 edited versions we read keep these.

  • 14

    Distinctive

    This author's own choices. Worth a look.

  • 6

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Run the sync command above in every fresh worktree before checks: poetry run executes commands without installing or refreshing …

    line 25
  2. Very specific:

    Every source file (*.py, *.sh, pyproject.toml) places this pair immediately after any shebang, or at the beginning of the file when there …

    line 39
  3. Distinctive:

    Before committing, run each of these and fix what they report:

    line 59
  4. Very specific:

    Never split one module's names across several from ...

    line 85
  5. Distinctive:

    Start with any reproductions the reviewer provided, then the affected test modules.

    line 99
  6. Distinctive:

    Do not rerun a broad suite solely to extract or regroup diagnostics that the log already contains.

    line 103
  7. Distinctive:

    When you move a helper to a new module, move the test's patch target to that owner with it.

    line 161
  8. Very specific:

    Prefer extending the in-memory fakes in tests/support/github/ (reached through the tests/support/fakes.py bridge) over mocking PyGithub …

    line 179
  9. Distinctive:

    Keep a seam patch where a collaborator is deliberately stubbed and its effect cannot otherwise be observed — a network or database read, an …

    line 189
  10. Distinctive:

    Call counts and ordering stay where the count or the order is itself the contract: a forbidden push, a duplicate child or PR, repeated …

    line 192
  11. Distinctive:

    Before finalizing tests, do a redundancy pass:

    line 198
  12. Very specific:

    Run one scenario once and assert its outcomes together.

    line 200
  13. Distinctive:

    Prefer one focused helper/unit test that covers sibling branches over multiple tests with repeated setup.

    line 206
  14. Distinctive:

    Keep end-to-end tests only when they exercise an integration boundary that helper tests cannot cover.

    line 207
  15. Distinctive:

    Ensure assertions observe the behavior being fixed.

    line 208
  16. Distinctive:

    Remove incidental low-level assertions when existing tests already cover that behavior.

    line 211
  17. Distinctive:

    Write every comment against the current state of the code, as if it had always been this way:

    line 215
  18. Distinctive:

    Prefer stating why the code below exists — the invariant it protects, the non-local consumer it serves, the failure it prevents — over …

    line 217
  19. Very specific:

    No diff-relative wording: "previously", "the old X", "instead of a set", "no longer", "now sized to".

    line 225
  20. Distinctive:

    When you move, rename, or delete a symbol or module — a handler, helper, constant, or whole owner — grep for its name across these files …

    line 232

“Common” is measured: kept by at least 6 in 10 of the 23 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Developer skill — chipping-orchestrator

Environment and commands

The repo targets Python 3.12+ and installs from the lockfile with Poetry 2.5.1:

env -u VIRTUAL_ENV -u CONDA_PREFIX poetry sync                                   # create .venv/ with runtime + dev deps
env -u VIRTUAL_ENV -u CONDA_PREFIX poetry run ruff check orchestrator tests fuzz .github/scripts/docs_site.py
env -u VIRTUAL_ENV -u CONDA_PREFIX poetry run flake8 orchestrator tests fuzz .github/scripts/docs_site.py --select=WPS
env -u VIRTUAL_ENV -u CONDA_PREFIX poetry run pytest tests                       # run the test suite
env -u VIRTUAL_ENV -u CONDA_PREFIX poetry run python -m orchestrator run --once  # one polling tick then exit
env -u VIRTUAL_ENV -u CONDA_PREFIX poetry run python -m orchestrator run --log-level DEBUG

Run the sync command above in every fresh worktree before checks: poetry run executes commands without installing or refreshing dependencies. Add --with dashboard or --with docs when the change needs an optional group; use --with docs,dashboard to install both, and --with fuzz for the parser fuzz targets under fuzz/. Sync removes unselected optional groups; tests that need those dependencies then skip instead of failing, so a green suite can hide missing coverage. poetry install preserves packages already installed but does not upgrade packages exclusive to unselected optional groups. Select an existing Python 3.12+ interpreter with env -u VIRTUAL_ENV -u CONDA_PREFIX poetry env use /path/to/python when the default is unsuitable.

Prefix every manual Poetry command with env -u VIRTUAL_ENV -u CONDA_PREFIX, as in the examples above. The environment selection policy explains inherited activation and the Conda requirements for target repositories.

License headers

Every source file (*.py, *.sh, pyproject.toml) places this pair immediately after any shebang, or at the beginning of the file when there is no shebang:

# Copyright 2026 Geser Dugarov
# SPDX-License-Identifier: Apache-2.0

Commits

  • Conventional Commits: <type>: <subject> with one of feat, fix, chore, docs, refactor, test.
  • Subject line only — no body, no Co-Authored-By trailer, no extended description. One -m flag.
  • Imperative mood, short and specific. Match the style in git log --oneline -20.
  • Descriptive subject only — write no numeric suffix. The trailing (#N) on the subjects in that history is publication metadata the orchestrator appended when it published the change, not part of the style to match: never copy one, and never end a subject with the number of the issue being implemented. The orchestrator supplies the pull request reference itself, and issue linkage stays in the PR body.

Pre-push checklist

Before committing, run each of these and fix what they report:

  • .venv/bin/python -m ruff check orchestrator tests fuzz .github/scripts/docs_site.py — the lint contract is Ruff's own default rule set plus E501. [tool.ruff.lint] in pyproject.toml declares no select, so the run enforces whatever the ruff resolved in poetry.lock ships as its defaults; do not add one back, and do not answer a new diagnostic by narrowing the selection. Re-resolving that lock can bring rules with it — fix what they report, in the same commit as the bump. There is no tree-wide waiver either: the only suppressions are the exact-path entries under [tool.ruff.lint.per-file-ignores] and inline # noqa: <CODE> - <reason> directives, each naming the rule it covers and why, and tests/repository/test_noqa_directives.py fails on a bare # noqa or a file-wide # ruff: noqa. Recurring CI breakers:
    • F401 (unused import): if the name is meant to be a re-export from a package facade that binds its surface with imports (orchestrator/agents/, github/, scheduler/, observability/usage/), alias it with ... as <name> so ruff treats it as an explicit re-export instead of dead code. A name the initializer lists in __all__ — how orchestrator/workflow/ publishes its label and guard surface — is already exempt. Outside an initializer that alias also trips PLC0414, so the module has to be one of the exact paths waived under [tool.ruff.lint.per-file-ignores] in pyproject.toml; alias only a name the module never reads itself, and add the path in the same commit. tests/repository/test_reexport_aliases.py fails on anything else.
    • F541 (f-string without placeholders): use a plain string.
    • F841 (unused local).
    • E402 (module-level import not at top of file).
    • BLE001 (blind except Exception): only a handler that must catch blind gets a # noqa: BLE001 - <reason> naming what the catch protects; anything narrower catches the exception it means.
    • The defaults also carry the modernization and simplification families — UP, B, SIM, C4, RET, RUF — so a diagnostic from one of those is a rewrite, not a waiver.
  • .venv/bin/python -m ruff check orchestrator tests fuzz .github/scripts/docs_site.py --select=I001 --fix — this fixes I001, which the run above enforces; tests/repository/test_import_sorting.py fails on a block left unsorted too. Never split one module's names across several from ... import statements to duck WPS235 — the sorter merges every statement reading from the same module back into one.
  • .venv/bin/python -m flake8 orchestrator tests fuzz .github/scripts/docs_site.py --select=WPS — all WPS naming, complexity, consistency, bug-prevention, refactoring, and OOP rules must pass.
  • git diff --check — catches whitespace errors in unstaged changes.
  • git diff --cached --check — catches whitespace errors in staged changes.
  • git diff --check origin/main...HEAD — catches whitespace errors in committed branch changes.
  • .venv/bin/python -m pytest — full suite must pass. Do not assume any "known" failure is acceptable; if a test fails on your branch, first reproduce it on origin/main at the same SHA you branched from, and only then call it out in the PR as a baseline failure with the reproduction steps. Otherwise fix it.

Test execution

  • Start with any reproductions the reviewer provided, then the affected test modules. After a fix, rerun the failing test node IDs directly before broadening the checks.
  • Save complete combined stdout and stderr from each test run to a unique log file. For focused or extra pytest runs, use -ra --tb=short for a readable failure summary; inspect the saved log for failure names and tracebacks. Do not rerun a broad suite solely to extract or regroup diagnostics that the log already contains.
  • Preserve pytest's exit status in the shell command's result: capture it before displaying the saved log. A successful tail, grep, or head can mask a failed pytest command; streaming through head can also cut the producer short.
  • Once focused checks pass, run the complete pre-push checklist on the final tree. Rerun the full suite whenever the tree changes after it passed.

For example, a focused run that retains its diagnostics and returns pytest's actual exit status (replace the placeholder node ID with the failing test):

test_log=$(mktemp "${TMPDIR:-/tmp}/dev-tests.XXXXXX")
test_status=0

.venv/bin/python -m pytest \
  'tests/<package>/test_<module>.py::<TestClass>::test_<name>' \
  -q -ra --tb=short > "$test_log" 2>&1 || test_status=$?

tail -n 80 "$test_log"
printf 'Full test log: %s\n' "$test_log"
(exit "$test_status")

Workflow owners and stage modules

Most package initializers are markers. The deliberate public APIs retain their explicit __all__ surfaces and exact-path WPS410/WPS412 exclusions. orchestrator.workflow publishes the two label vocabularies, the transition guard, its predicate and exception, and the lazy per-repo tick entry point. Labels live on workflow/state.py, label parsing on workflow/label_reading.py, the graph on workflow/transitions.py, and write guards on workflow/transition_guard.py.

  • The workflow initializer imports no engine or stage. Its tick shim resolves workflow/engine/tick.py inside the call, so the GitHub and git layers can import labels and guards without an initialization cycle. tests/workflow/test_imports.py checks that direction, and tests/repository/test_package_exports.py holds the declared public surfaces and marker initializers.
  • Settings reloads and patches target orchestrator.config, the same module object all callers retain. config.RepoSpec is the public alias of config.models.RepoSpec; callers that need only the type may import its defining owner. Token resolution is defined on config.credentials.
  • Stage modules import the owner they borrow from at module scope — from orchestrator.git.worktrees import paths as _worktree_paths, from orchestrator.workflow.engine import guards as _guards — and call through that alias. Never reintroduce a call-time hop through the package initializer.
  • Tests patch the owner. tests/workflow/git_owners.py records which git module defines each seam (GIT_SEAM_OWNERS, seam_patch) and tests/workflow/patch_context.py installs every hermetic mock on that table plus the agent runner, raising rather than falling back when a name has no owner.
  • Stage-private helpers stay in the stage package that owns them. Shared helpers are read from their defining owner; copying or re-exporting one creates a second patch target that can drift from the running call.
  • Each owner declares its own log = logging.getLogger("orchestrator.workflow") with the channel spelled literally (workflow/transition_guard.py owns orchestrator.state_machine). Operator filters select on those names, so never derive one from __name__; tests/workflow/test_imports.py walks the package and checks it.
  • Preserve the current formats verbatim across a refactor: workflow labels, pinned-state JSON keys, comment marker text, watermark fields, event-emission shape. Live issues already carry these, so a "harmless rename" is a deliberate format change, not a refactor. Make one only when the issue asks for it, and follow C-03, which also explains why removing a historical format, alias, or call signature in this release needs no compatibility reader or migration.

Tests

  • When you move a helper to a new module, move the test's patch target to that owner with it. There is no second site to patch instead: the module the call site names is the only one a mock intercepts.
  • Tests mirror the runtime layout: a module under orchestrator/<package>/ is covered by tests/<package>/, and stage-handler tests live beside their owners under tests/workflow/stages/<stage>/. Put a new test in the module that already covers the behavior's owner; add a new module only when none does, and name it after the behavior it protects rather than after the symbol it calls.
  • Each stage package's tests are already split into focused modules — routing, the outcomes one tick can reach, the parks, drift, live pause — with the fixtures they share in a *_test_support.py beside them. Follow the split that is there instead of growing one omnibus module, and put a stage's shared fixtures in its own support module rather than in a sibling stage's.
  • Each tests package carries its package-level guards (clean-process import, import-cycle / layering direction, and public surface) in its own test_imports.py. A test-economy pass never trims them: one fresh process per owner and per environment is the floor, since importing several owners in one interpreter hides a cycle behind an already populated sys.modules.
  • Helpers that belong to no single stage get their own focused module under tests/workflow/, and tests/workflow/fixtures.py re-exports the ones a test spanning several of those leaves needs. Nothing lands at the tests/ root: a helper shared across domains goes under tests/support/, and a test covering the repository's own files or the root package goes under tests/repository/.
  • Prefer extending the in-memory fakes in tests/support/github/ (reached through the tests/support/fakes.py bridge) over mocking PyGithub directly. New behavior should land with tests in the matching stage file.
  • Assert what a change does, not which helper ran. Drive a stage handler through the in-memory GitHub client — or through a whole tick() — and read back the workflow label, pinned_data, posted comments, the PR, and what the next tick does; drive a dashboard section against the recording page doubles beside it in tests/observability/dashboard/ and read back the panel order, the filters and timezone the page was drawn with, and the data on screen. A test that patches a helper in the package under test and asserts call_args, object identity, or the order two same-package helpers ran in breaks on every refactor and says nothing about behavior.
  • Keep a seam patch where a collaborator is deliberately stubbed and its effect cannot otherwise be observed — a network or database read, an agent run, a renderer reaching for an optional dependency — and patch it on the defining owner, as above.
  • Call counts and ordering stay where the count or the order is itself the contract: a forbidden push, a duplicate child or PR, repeated charging, an extra API read or pinned-state write, timeout cleanup, write-before-publish ordering. tests/github/test_issue_polling.py asserting no per-issue detail GET is the model. Literal label, pinned-state key, comment marker, watermark, and event payload checks stay for the same reason — they pin the current formats C-03 covers, not implementation detail.
  • Before finalizing tests, do a redundancy pass:
    • List each added/modified test and the distinct behavior it protects.
    • Run one scenario once and assert its outcomes together. Where several methods share a setUp and differ only in which outcome they inspect, fold them into one test that keeps every assertion and its diagnostic message. Keep distinct scenarios apart: different failure inputs, crash windows, security boundaries, and side effects each earn their own run.
    • Merge tests that differ only by input shape or branch case into pytest.mark.parametrize cases or a small named loop, unless separate setup materially improves clarity.
    • Prefer one focused helper/unit test that covers sibling branches over multiple tests with repeated setup.
    • Keep end-to-end tests only when they exercise an integration boundary that helper tests cannot cover.
    • Ensure assertions observe the behavior being fixed. For resource-usage bugs (over-fetching, redundant API calls, retained state), add a direct assertion at the helper/producer level when final-result checks could pass for the wrong reason.
    • Remove incidental low-level assertions when existing tests already cover that behavior.

Comments

Write every comment against the current state of the code, as if it had always been this way:

  • Prefer stating why the code below exists — the invariant it protects, the non-local consumer it serves, the failure it prevents — over describing what it does. If a comment paraphrases an already-readable line (# cap the page size at what we still need above min(remaining, page_size)) or the assert below it, delete it or replace it with the reason.
  • Exception: a plain-language summary of genuinely dense code (tricky offset math, a multi-step comprehension or iterator chain, subtle ordering constraints) is fine even though it "restates" the code. The test is whether the comment is faster to understand than the code below it, not whether it repeats it.
  • No diff-relative wording: "previously", "the old X", "instead of a set", "no longer", "now sized to". Those sentences address the reviewer and go stale the moment the PR merges — put the before/after story in the commit message or PR description instead.
  • Same rule for test docstrings: describe the behavior the test pins down, not the bug or implementation it replaced.

Documentation drift

When you move, rename, or delete a symbol or module — a handler, helper, constant, or whole owner — grep for its name across these files and update every inventory entry, prose pointer, and docstring it leaves stale in the same commit:

  • docs/architecture.md and the focused pages under docs/architecture/ — the module-by-module inventory lives here and nowhere else, with one exception: docs/architecture/observability-modules.md maps observability/ and apps/ at the package boundary, so a move, rename, or deletion inside those two trees updates the affected owner and package docstrings rather than a map entry
  • docs/state-machine.md and the focused pages under docs/state-machine/
  • docs/workflow.md and the focused pages under docs/workflow/
  • the module docstrings at the top of the owners the symbol moved between, was renamed in, or was deleted from, and of the package initializers above them that describe where a name answers

AGENTS.md (and its CLAUDE.md symlink) is deliberately not on that list. It carries no module, owner, or test inventory, so a routine move, rename, or deletion of a symbol or module must leave it alone. Update it only when repository-wide agent instructions, safety rules, or documentation routing change.

Be precise about what a package does and does not publish — overstated claims like "every helper is re-exported" get flagged.

Documentation pages and links

The pages directly under docs/ are the stable addresses. Write a link — from the README, from AGENTS.md, from an issue, from a commit message — against one of those rather than against a page inside an area directory: a landing page is where its area's overview lives and stays put, while the pages beside it are split further as the area grows. A landing page is not a table of contents. It keeps a section for every part of its area, and where that part has grown a page of its own the section stays behind as a summary naming the owner, so a deep link written before the split, such as the fixing handler, still lands on that summary.

A new page under docs/ is listed twice, grouped the same way in both: under Every page in docs/README.md, and under nav: in mkdocs.yml. In the site a section's first page is its landing page, since the top bar links the section to it, so an area's overview goes first. tests/repository/test_doc_links.py checks both lists, and every relative path and #anchor in the docs, the README, AGENTS.md, CONTRIBUTING.md, and the skill files, without the documentation builder installed.

plans/ is working notes, not spec

Files under plans/ are human working notes, not authoritative implementation requirements. Implement what the issue asks for; do not treat a plans/ document — or a numbered "Proposal N" inside one — as a spec to satisfy, and do not cite one in code, comments, docstrings, or commit messages (that reference outlives the note and goes stale the moment it is revised or deleted). Leave files under plans/ untouched unless the current issue explicitly asks you to edit or remove one.

Dependencies

pyproject.toml pins PyGithub and psycopg[binary] as runtime deps; packaging, pytest, pytest-cov, ruff, and wemake-python-styleguide live in the dev group; the analytics dashboard's streamlit and plotly live in the separate dashboard group, and atheris, which only the targets under fuzz/ import, in the fuzz group, so the default poetry sync stays minimal. poetry.lock is the source of truth for exact versions and is committed — update it (env -u VIRTUAL_ENV -u CONDA_PREFIX poetry lock) whenever dependency declarations or group settings change. Version-only releases do not change the lock. Keep one lock entry per package and cap runtime major upgrades. Raise runtime lower bounds with manual updates; Dependabot's pip entry requests this with versioning-strategy: increase. Repository checks accept a lock-only update within the declared range. poetry.toml keeps environments in .venv/ and holds new releases for 14 days when resolving. Do not commit package sources or mirror URLs; the lock uses implicit PyPI. For security fixes younger than 14 days, follow the manual security-fix procedure.

Install the export plugin only when exporting for an audit or a release, using pipx inject poetry "poetry-plugin-export==<version>" with the exact pin from the vulnerability-scan workflow. Anything else needs justification.

Out of scope without explicit ask

  • Adding dependencies that the current issue did not request.
  • Reformatting unrelated files or churning whitespace.
  • "Future-proofing" abstractions for hypothetical features. Implement what the issue asks for and stop.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.