Imported from Innoguard-Cyber-Arch/csarc-repo-template (
AGENTS.md). Install upstream withnpx skills add Innoguard-Cyber-Arch/csarc-repo-template. Copyright stays with the author.
Repository instructions
Responsibility map
- GitHub Issues and pull requests define work, progress, and evidence. Approved specs and ADRs preserve durable context; add a plan only for cross-session, high-risk, or hard-to-recover work, and never store raw chat transcripts. Follow Journey 01 for work-item relationships and fields.
AGENTS.mdis the single source for AI working instructions;CLAUDE.mdonly imports it.- One writable task uses one Git branch and one worktree so concurrent changes stay isolated.
- Reusable validation lives in
scripts/and tests. During implementation and before an ordinary push, run focused checks for the owners touched by the change;./scripts/verify-fastremains an optional broad local diagnostic. In this repository's hosted mode, do not rerun./scripts/verify-template.shlocally merely because the selected tier isfull; the required hostedverifycheck selects the tier from trusted base code and executes the risk-owned entry point once on the exact candidate.scripts/check-trusted-verificationbinds that GitHub-hosted result to the repository, commit/tree, tier, scopes, command, toolchain, runner, result, and freshness. Run local full only for a documented fallback or an explicit diagnostic request. Local success is useful contributor feedback but never substitutes for the hosted check. Dependabot follows this same path with no bot-specific bypass. Checked-in files under.github/workflows/are the only active GitHub Actions. See CI/CD settings anddocs/ci-policy.mdfor the tier boundary and stage ownership. - Journey 08 and
docs/ci-policy.mdown review requirements, merge eligibility, configured admin bypass, and the Actions-outage governance-switch route; the former quota fallback is retired. Do not restate or invent exceptions here. - Copier owns template creation and updates. Follow Journey 09 and
docs/agent-install.mdfor existing-repository behavior.
Scope and sources of truth
- This file applies to the whole repository. Read a nearer
AGENTS.mdonly if a future subtree genuinely needs different commands or safety rules. - Three documents split by audience, each authoritative for its own layer:
README.mdtargets general users adopting the template (what it is, whether to use it, how to start); this file targets contributors and agents working in this repository (executable workflow rules);docs/index.htmlis the appendix for decision rationale and technical detail. Do not restate this file's workflow rules inREADME.md; link to it instead. - The approved product handbook (
docs/handbook/handbook.md, rendered by./scripts/build-handbookintodocs/handbook/index.html) is the source of product policy and user commitments; specs/ADRs carry exact contracts and this file plusdocs/ci-policy.mdcarry executable rules. A conflict with the handbook isdriftin the documentation review. Editing the handbook needs a new owner approval that replacesdocs/handbook/approved/in the same change; seedocs/adr/durable-project-memory.md. - Treat
copier.yml,template/,policies/, andprofiles/catalog.yamlas the product. template/is what downstream repositories receive. Root configuration governs this template repository itself.- Use root
docs/specs/for SDD current contracts;docs/README.mdmaps durable project memory. SECURITY.mdis repository-wide scanner policy;.github/SECURITY.mdis the human vulnerability-disclosure policy. Seedocs/security-scanner-readiness.mdfor provider capabilities, exact validation commands, scope, cost, and offline boundaries.- Use
docs/adr/for decisions. In updated projects, also search project-owneddocs/decisions/; never move or overwrite it automatically. - Edit the root presentation through
site/: bilingual Markdown belongs insite/content/, the pure-Python render engine lives inscripts/build_repo_site.py(with shared block parsing inscripts/repo_site_blocks.py), styles and interactions stay insite/static/, and shared glossary/navigation/config data live insite/data/. Run./scripts/build-repo-siteto rebuilddocs/index.html,docs/index.en.html, and thellms.txtindexes; do not hand-edit generated outputs.site/data/slide_inventory.jsonrecords the ordered bilingual slide keys, tracks, and audiences thatscripts/check-repo-site-inventorychecks; update it in the same change when a slide is added, removed, reordered, or re-tracked. The engine and the presentation template each carry an independent version insite/version.json, checked byscripts/check-repo-site-versions. - Compose each repo-site page from the existing declarative block syntax in
site/content/*.md, not new per-page CSS or HTML: it is parsed byscripts/repo_site_blocks.pyand rendered by named functions inscripts/build_repo_site.py(e.g.render_slide,render_detail,render_config_guidance), not Hugo shortcodes orsite/layouts/templates, which no longer exist.{{< slide key=… track=… >}}marks one page section;{{< basic >}}holds the default plain-language content most slides need;{{< legacy >}}is only for a slide that keeps bespoke fidelity/presentation styling (legacy="true"on the slide); simple structural content skips both wrappers and lets the slide body markdownify directly (see thefilesslide). Nest optional deeper technical content inside{{< basic >}}with{{< detail >}}(always-visible aside) or{{< disclosure >}}(collapsed<details>); render config examples with{{< config-guidance track=… >}}againstsite/data/config_examples.jsoninstead of hand-writing them. Pick the existing block that fits rather than inventing a one-off layout. Mirrorsite/content/_index.zh-tw.mdand_index.en.mdslide-by-slide (samekey/track, matching structure) and keep newsite/data/navigation.jsonlabels within the widthscripts/check-repo-site-navigationchecks.site/data/glossary.tomlonly feeds the bilingualllms.txtindex, not an in-page glossary widget. - Keep decision records, the deck, and checked-in paths aligned. Do not describe a capability as active unless the template creates and verifies it.
- Follow
docs/documentation-policy.mdfor the template/content boundary, i18n, README, and licensing. Before a non-Draft pull request is delivered, compare changed behavior and configuration with project-owned documentation, then recordalignedor reasonednot-applicableagainst the exact head;driftandinconclusiveblock delivery.
Working loop
- At task start, run only
git worktree list --porcelain; reserve unscoped cleanup for explicit maintenance. Creator cleanup after merge remains required. Before planning or opening an Issue or Milestone, list open Milestones and open Issues, then search open and closed Issues with two to four concrete problem or technology terms. Inspect the body, comments, and linked pull requests of credible matches; titles and labels alone are not decisions. Keep each query bounded to 20 candidates. - Use the work-item model in Journey 01. A Milestone is an optional dated delivery or release bucket; follow
docs/milestone-description.md. Repository Projects stay disabled. Whengithub_project_urlin.csarc/config.ymlnames an organization/user ProjectV2, Issues created withcsarc issue createare added with UTCProject start(creation date) andProject target(Milestone due date, else--target-date); after a Milestone or due-date change, or for an Issue created another way, runcsarc issue sync-project --issue <N>or--milestone <M>, which shows a diff and needs confirmation before overwriting a different date (SPEC-009 §10; verified only with stubs, not against a live ProjectV2). - Before creating the work item, present a short prior-decision summary when the user can respond. If creation is already authorized, record each relevant
#Nas preserved, superseded, or rejected with a reason in the Issue supplement or MilestoneReferences; when none are found, record the bounded queries used. When a user confirms a durable architecture, tooling, security, compatibility, or platform constraint, summarize it in the work item and update the matchingdocs/adr/record through the scoped pull request. Never store a raw conversation transcript or promote an unconfirmed inference to a decision. Never silently reverse an earlier decision. - Use the checked-in Issue form and pull request template whether creating through the UI, CLI, or API; do not create a second body format.
- Open or select one GitHub Issue before editing and use its acceptance criteria as scope. Record
betafor Milestone work andstablefor a Milestone tracker, standalone change, or hotfix; reject a conflicting declaration. State the locally required suite (channel floor plus path risk) and what hosted CI proves. Titles use 12-80 ASCII characters, at least three words, no type prefix, and no trailing period. Set one native Type, assignee, and applicable parent and Milestone at creation time; when research or a Feature expands into a dated delivery, the originating Feature Issue belongs to that Milestone too, and every resolving PR inherits the linked Issue's Milestone. On a Type-capable repository, do not repeat Bug, Feature, or Task as an Issue label; keep only orthogonal labels such asdocumentation,hotfix, orpromotion. Issue forms seed the lowercase classification label only as a portable fallback, and lifecycle automation removes it after native Type succeeds. A PR carries exactly one lowercase classification label derived from its linked Issue's Type, or from the fallback label when native Types are unavailable.scripts/gh-issue-createnudges (never blocks) when a Milestone is likely missing. Usescripts/gh-issue-editinstead of rawgh issue editfor body changes so an existing approval cannot be invalidated without a local warning; the wrapper is advisory and cannot intercept GitHub UI or direct API edits. Once a Milestone closes,gh issue edit --milestone <name>can no longer find it by name -- seedocs/ci-policy.md's Milestone safeguard section for thegh api ... --method PATCH -f milestone=<number>fallback. The creator is the default owner: UI creators assign themselves, while CLI and agents pass--assignee @me; change the assignee only for an explicit handoff. - If new work exceeds that Issue, stop and open a separate Issue; do not silently widen the current branch or pull request. When that new Issue surfaces from a problem discovered while working a Milestone Issue, default to keeping it inside that same Milestone (Milestone-tagged, based on its
dev/m<N>delivery branch) rather than opening it standalone. Open it standalone only when it clearly meets one of: it spans multiple Milestones or is a governance/tooling mechanism affecting all future Milestones, not this Milestone's own feature scope; it is an urgent production fix that cannot wait for the Milestone to close; or it originates from an external report (another collaborator or peer session) with no direct causal link to this Milestone's own work. When unsure which applies, default to keeping it in the Milestone — the exceptions are narrow, not a default escape hatch. - Check every acceptance-criteria box in the Issue, and every pull request checklist box, only once it carries real evidence, and finish all of them before opening a pull request or pushing a commit meant to satisfy the closing keyword — not incrementally, box by box, across separate pushes. Each push re-triggers the same PR policy gate; pushing a commit you already know is incomplete guarantees that gate fails, and doing this repeatedly is a retry storm, not progress (#430, PR #448 needed 49 pushes over 13 hours to learn this the hard way). Keep the pull request in draft while work is still incomplete: the acceptance-checklist gate does not enforce completeness on a draft, and revalidates in full the moment it is marked ready for review — see
docs/ci-policy.md's "Acceptance-checklist 驗證時機(#573)" section. Every work Issue carries the#### 風險與控制block in its 補充 (one row per risk, at least one control, the assignee as Owner;R0only for docs outsideAGENTS.md,SECURITY.md,.github/SECURITY.md, and the CI policy), and before Ready the pull request's one## Requirement evidencesection maps every acceptance criterion (the ordered top-level 完成條件 checkboxes, AC1..ACn) and every risk ID to exact-head evidence, a reasonedmanual:link, or a visibleaccepted: <reason>for a risk; never invent evidence or useR0oraccepted:to hide a real risk (docs/specs/SPEC-010-issue-risk-controls.md). Keep independent implementation and focused checks parallel, but serialize the expensive finalization window per destination base. In one parent/subagent tree, a worker reportsREADY_TO_FINALIZEwith its Issue, branch, head, and base, then yields while the parent chooses the next candidate. Independent sessions sharing one clone runscripts/finalization-queue announce --issue <N> --base <branch>from a clean worktree and proceed only whenstatusreportsready; a waiting agent reports the earlier Issue and yields instead of busy-polling. The expiring queue is advisory and never grants authorization or replaces the remote lifecycle lease. For CSARC-owned release-worthy work, the selected agent must then update from the current destination base, runpython3 scripts/release_policy.py prepare-candidate --sha HEAD --phase <beta|stable>, review the result, and commit only the governed version surfaces and CHANGELOG as the final commit in that same pull request. The highest Conventional Commit type on the branch must equal the PR title type, because the squash merge keeps only the title and the materialized version otherwise does not hold after merge;verify-delivery-version --pr-titlerejects a mismatch before merge (#1137). Milestone work usesbeta; Milestone promotion, standalone work, and hotfixes usestable. When the Milestone tracker declares### Checkpointsbefore approval, only each checkpoint's terminal Issue materializes and publishes the beta; other Milestone work merges without a version (deferred) and must not runprepare-candidate(seedocs/milestone-description.md). If exact materialization, current-base ancestry, evidence, or lifecycle authorization is missing, keep the pull request draft, preserve the warning, and do not merge; never defer version creation to a post-merge version pull request. - For a Milestone Issue, start from its one short-lived
dev/m<milestone>-short-slugdelivery branch. For an Issue without a Milestone, start from currentmain; if independent changes must soak or ship together, create a real Milestone instead of a catch-all branch. Usescripts/gh-issue-develop <issue> --base <base> --name type/<issue-number>-short-slugfor the native Development link and pre-creation name check; use its guarded--repair-from <old-branch>only before a pull request exists. GitHub closes an open pull request when its head branch is renamed, so never rename or delete an open PR's head as an automated repair. Followdocs/ci-policy.mdfor the explicitly authorizeddev/i*canary, synchronization, promotion, hotfix, and release-recovery routes. When a pull request is stacked on another work branch, retarget it to the shared integration branch as soon as the base pull request is ready to merge, before that branch is squash-merged and deleted. GitHub auto-closes (does not auto-retarget) a pull request whose base branch no longer exists; recovering it means opening a new pull request from the same head branch, which loses the original PR's number, reviews, and comment history. - Inspect the existing implementation, make the smallest coherent change, and preserve unrelated user work.
- Add or update the narrowest regression check that proves non-trivial behavior.
- Delegates run scoped or focused checks while iterating and before an ordinary push. CI selects fast or full automatically by changed paths and delivery stage (
docs/ci-policy.md); docs-only work is a fast scope optimization, not another tier. In hosted mode, the pull request owner does not rerun the aggregate fast or full suite locally solely because CI selected that tier; the hostedverifycheck executes it once on the exact candidate and provides the merge evidence. Use./scripts/verify-fastor an individualscripts/verify-stage-*only when a broader local diagnostic is useful. A documented Actions fallback or explicit maintainer diagnostic may still require local full, but that result never substitutes for hosted evidence outside the fallback's existing boundary. - Create an automated pull request directly as Draft with
scripts/pr_lifecycle.py create; it requires the checked-in PR body, a clean worktree, and a pushed exact head, so do not create a Ready PR and convert it back. Before any later automated PR Ready/Draft, authorization, metadata, or merge write, acquire the remote lease and usescripts/pr_lifecycle.py; otherwise remain read-only. This includes any configured admin-bypass PR (Issue #918):pr_lifecycle.py mergeis the first-class path there too, not a manualgh pr merge --adminexception. Follow Journey 08 rather than duplicating merge rules here. Pull request titles usetype(scope): summaryin ASCII: type is one offeat,fix,docs,refactor,test,build,ci,chore, orrevert; the scope is optional lowercase[a-z0-9._/-];!before the colon marks a breaking change; thetitlecheck enforces this. The squash commit and any release notes take this title, and release intent reads its type (!major,featminor,fixorrevertpatch, others none), so name the highest-impact type among the branch's commits. - Treat an Issue implementation as active through merge and post-merge closeout unless the user explicitly limits the task. After merge, confirm the exact head merged, the linked Issue reached its expected state, the configured release or explicit no-release decision completed with readback, the source branch and lifecycle lease were removed or intentionally retained, and no required external state remains pending. Only then leave the task worktree and run
./scripts/cleanup-worktrees --apply --worktree <path> origin/<pull-request-base>from another checkout; never remove another task's worktree or any dirty, locked, detached, unmerged, or unverifiable worktree. Clear the soft intent withscripts/finalization-queue leave --issue <N>after the lane is no longer needed. - Report
WAITINGwith the exact condition when review, CI, release, permission, or other external state is pending; reportBLOCKEDonly when no safe progress remains. ReportDONEonly after step 13, with the changed behavior, verification evidence, and any remaining limitation. A worker then reportsARCHIVE_READYand exits or yields; because Codex cannot archive a session while its task is running, the parent or client archives it after the final report rather than the worker claiming self-archive. - Open every new Issue through
scripts/gh-issue-create(a thin wrapper that runsscripts/validate-issue-titleon--titlebefore ever callinggh issue create), or at minimum runscripts/validate-issue-title "<title>"by hand first, so the step 5 title rule is caught locally before the Issue exists rather than after by the hosted Issue triage classification. - Before starting or resuming work on an existing branch or pull request, run
scripts/check-branch-fresh <branch>to confirm local still matchesorigin/<branch>'s current tip. Do not assume local reflects current state just because you worked there recently; origin may have advanced or been force-pushed/rebuilt by someone else since.
Writable agents use one branch and worktree per independent task. Reuse a host-managed worktree; never force a branch into multiple worktrees or remove one owned by another task or with uncommitted changes. Use local storage for active checkouts, worktrees, environments, and caches. If assigned a cloud-synced File Provider path, switch to a local checkout without routine user confirmation; preserve existing changes. Worktrees isolate files; integration still uses PR, CI, review, and final verification.
Never push directly to a delivery branch, invent successful evidence, create or dispatch release tags manually, or bypass the linked governance policy.
Duplicate triage may close an Issue without code changes when it links the canonical Issue and uses GitHub's native duplicate reason. If a change modifies an Issue or pull request body shape, migrate existing bodies before closing it; otherwise create and link a follow-up Issue first.
Commands
- Environment setup:
uv sync --locked --python 3.14. - Python iteration:
uv run ruff check <paths>,uv run ty check <paths>, anduv run pytest <test-path>. - Site source check:
./scripts/build-repo-site --check. - Security smoke:
./scripts/security-smokeselects four existing offline owner self-tests; it is not an AI security scan and is not part of every routine gate. Seedocs/security-scanner-readiness.mdfor the exact command inventory and limits. - Focused local checks: run the narrow owner checks for touched paths before an ordinary push; use
./scripts/verify-fastonly as an optional broad diagnostic. Hosted CI runs the selected risk-owned tier once on the exact candidate for merge evidence. - Full verification entry point:
./scripts/verify-template.sh; hosted CI invokes it automatically when the trusted plan selectsfull. Run it locally only for a documented fallback or explicit diagnostic (seedocs/ci-policy.md); a singlescripts/verify-stage-*script can recheck one stage but does not attest the aggregate result. - Inspect trusted hosted evidence after a run:
./scripts/check-trusted-verification <head-sha> --github-repo <owner/repo>. - Copilot review loop (
copilot_review: allowedin.csarc/config.yml): after each push,python3 scripts/review_gate.py status --repo <owner/repo> --pr <N>lists Copilot's findings on the current head and the unresolved threads; fix them locally, push, answer and resolve the threads, and repeat until Copilot's review of the exact head is clean and thereviewcheck passes, then merge throughscripts/pr_lifecycle.py. A maintainer approval of the exact head remains a valid alternative. Seedocs/ci-policy.md's "Copilot 審核模式(#752)" section. - Release execution:
release.ymlonly publishes a candidate already materialized and reviewed in the merged PR. Hosted publication is the default; when Actions or webhook delivery is unhealthy, run the samescripts/publish-releaselocally under the maintainer's admin identity. Never create a replacement version PR or a tag by hand; seedocs/ci-policy.md's release fallback section. - Milestone creation:
scripts/create-milestoneatomically creates the GitHub Milestone (with a real due date) and its tracker Issue together, replacing the old two-step manual UI flow;python3 scripts/sync_milestone_state.py preflight --repo <repo> --milestone <N>re-validates an existing Milestone's due date, tracker title, andLifecycle Issue: #Nlink before work is dispatched under it, instead of waiting for the first PR to failValidate Milestone approval— seedocs/milestone-description.md.
Editing boundaries
- Keep shared policy changes synchronized between root and
template/where both layers consume them. - Do not weaken generated-project checks to make template tests pass.
- Keep GitHub Actions pinned to full commit SHAs and retain the readable release tag in a comment.
- Do not hand-edit generated lockfiles; use uv or pnpm so integrity metadata stays valid.
- Do not create a separate GitHub repository for testing or validation. Use local temporary projects or this repository's Issues, branches, pull requests, and Actions.
- Do not add a language without executable create, existing-repository adoption, update, and native-toolchain verification. Deployment targets and platform integrations still require a real consuming repository.
- Comments in source code must be written in English. Leave formatting and lint details in their executable configuration instead of duplicating them here.
Platform capability and automation
- Keep desired automation declarative and testable; do not assume organization or enterprise administrator access.
- Never extract or persist
gh auth tokenas project configuration, require a personal token for the portable baseline, or treat a permission error as proof that a capability is available. - Report blocked or unavailable capability explicitly. Never claim a release, deployment, review gate, or other control succeeded when it was skipped or unsupported.
Safety
- Never commit secrets, tokens, private keys, or populated
.envfiles. - Review the plan output before applying repository settings; do not operate production or external infrastructure without explicit authorization.
- Do not bypass required checks or supply-chain verification. Journey 08 is the only source for the configured admin approval bypass, including its exact-head authorization and audit requirements.
- When a shell pipeline's result is read from
$?, the last stage of that pipeline must be the command actually being judged.cmd | tail -N; echo $?reportstail's exit code, notcmd's, and has produced false "it passed" claims in this repository's own Milestone 8 history. To keep both the output and the correct exit code, redirect to a file and check separately:cmd >log 2>&1; status=$?. For a pull request's checks specifically, usescripts/check-pr-policy-status(seedocs/ci-policy.md's "PR policy 逐 step 判讀(#513)" section) instead of greppinggh run view --logor trustinggh pr checks' job-level output by itself.
Code Review Rules
- Flag documentation or slide claims that do not match files the template actually creates.
- Flag changes that reduce required checks, permissions safety, artifact verification, or product-source preservation during Copier updates.
- Require tests for behavior changes and synchronized lockfile updates for dependency changes.
- Treat public interfaces, release behavior, workflow permissions, and secret handling as high-risk review areas.
