standardize-repo
Apply the harmon-init Copier template's conventions (DevOps tooling, CI/CD, lint, security, git hooks, Taskfile) to a repo. Use whenever the user wants to "apply harmon-init", "scaffold a new repo wit
SKILL.mdai/skills/repo/standardize-repo/SKILL.md
GitHubStandardize Repo (apply harmon-init conventions)
Bring a repo in line with the harmon-init Copier template — the shared baseline
of DevOps tooling, CI/CD, linting, secrets scanning, lefthook git hooks, and a
Taskfile.yml task runner. harmon-init is the template repo of harmon-platform
(siblings: harmon-devkit, harmon-infra); this skill is
how an agent consumes that template to scaffold new repos or standardize existing
ones. harmon-init is NOT an application — it is used via
Copier, so the heavy lifting is
copier copy / copier update, not hand-copying files.
Credential boundary
Keep secret and credential-store writes human-only. Use read-only checks to confirm that a credential is configured without revealing its value. If CI is blocked by a missing credential, report the exact maintainer action; never create, rotate, delete, or widen access to credentials, or weaken a workflow merely to make CI green.
Preconditions
Verify these before doing anything; stop and tell the user if one is unmet.
copier installed —
copier --version(needs>= 9.4.0, per_min_copier_version).harmon-init cloned locally at
~/git/harmon-init— required by every mode. If missing:git clone https://github.com/evanharmon1/harmon-init ~/git/harmon-init. The one exemption is narrow: audit mode's guarded drift helper (assets/diff-template.sh) snapshots the canonical remote itself and needs no checkout. The rest of audit mode — the catalog comparison, which is the bulk of the work — reads the checkout directly as$TEMPLATE, and it is the only source of truth for a never-templated repo, where the drift helper cannot run at all.task (go-task) on PATH —
task --version— for the verification gate.yq on PATH — reads and freezes the
.copier-answers.ymllineage tuple.gh authenticated (
gh auth status) —gh apirequires a credential even on public repositories, so this is needed for:- the GitHub side-effect steps (remote create, release init);
- update mode's legacy-baseline branch, taken whenever the recorded
_commitis tag-valued — it reads the GitHub release record; - the Code Security capability check before selecting CodeQL on a
private/internal repo (
mode-update.md§3,mode-audit.mddrift class G) — this one applies regardless of lineage, including full-hash baselines.
Plain local scaffolding does not need it, and neither does audit mode's legacy-baseline recovery — that path is
git-only (assets/diff-template.shresolves viagit ls-remote, nevergh api).
Mode routing
Detect the situation, then follow the matching reference file end to end.
| Situation | Mode | Reference |
|---|---|---|
| Target dir is empty / does not exist yet (new project) | new-repo | references/mode-new-repo.md |
| Target is an existing repo with git history (retrofit) | adopt-existing | references/mode-adopt-existing.md |
Repo already generated from harmon-init (v3+, has .copier-answers.yml) and user wants the latest template changes ("update", "keep in sync", "pull latest harmon-init") |
update | references/mode-update.md |
| User says "audit" / "check" / "what's missing" / "bring up to standard" / drift report | audit | references/mode-audit.md |
If it is ambiguous (e.g. a non-empty dir that is not a git repo), ask the user which
mode they want rather than guessing — copier copy vs copier update behave very
differently.
Cardinal copier rules (read before running any copier command)
These are load-bearing. Full rationale and edge cases in references/copier-gotchas.md.
Production scaffolds use the canonical GitHub URL at a remote-verified release ref. Select
HARMON_INIT_REF, verify that exact tag againstorigin, peel it once toHARMON_INIT_COMMIT, and pass that immutable commit to Copier using the guarded commands in the applicable mode reference. Then freeze the tuple:--vcs-refdoes not survive into the answers file. Copier derives_commitfromgit describe --tags --always, so a released tag lands in.copier-answers.ymlinstead of the peeled hash — discarding the immutable evidence the guard just established. Every mode that renders must promote_src_path/_committo the canonical URL andHARMON_INIT_COMMITafterward. Update mode must also resolve the recorded_commitonce, require maintainer-approved recovery when legacy tag-only lineage lacks immutable evidence, and run every trusted render from a read-only offline clone through process-scoped Git URL rewrites. Prove the target descends from the resolved baseline before rendering. This records durable lineage that another machine can resolve without allowing a retag between validation and trusted template execution. A local-path--vcs-ref=HEADrender is only for a disposable preview/test of unreleased template work. Copier may represent dirty local work with a throwaway commit that does not exist on GitHub; never promote that render by rewriting only_src_path. The recorded_src_pathand_commitare one lineage tuple: before changing a local path to the canonical URL, prove the recorded commit is reachable from that remote, or re-render/re-adopt from a released remote ref. An update must reject a non-canonical recorded source and pass the immutable commit derived from the remote-verifiedHARMON_INIT_REFso preview and apply cannot select different releases. Seecopier-gotchas.mdgotchas 1 and 8.Side-effectful answers default to
noincopier.yml(github_remote_create,github_release_init,bunch_add,obsidian_project_add,run_task_install). Leave them off unless the user explicitly asks; only flip them on with confirmation.Run non-interactively with
--data key=valuefor known answers and--defaultsfor the rest, so runs are reproducible and CI-safe. Use--trust(the template has_tasks). Example shape:copier copy https://github.com/evanharmon1/harmon-init.git ./new-project \ --vcs-ref="$HARMON_INIT_COMMIT" --trust \ --data project_name="My Project" --data project_type=general --defaultsThis is only the command shape; run the release-tag validation and derive
HARMON_INIT_COMMITinreferences/mode-new-repo.mdbefore executing it.Confirm the resolved answers before any
--trustrun.--trustexecutes the template's_tasks, so every non-interactive mode (update, adopt-existing, new-repo) first prints the complete resolved question → answer set withassets/confirm-answers.sh—CHANGEDagainst the recorded.copier-answers.yml,NEWwhere nothing is recorded,SENSITIVEwhere the answer grants trust, names a principal, or fires a side effect — waits for explicit human approval, records it with--confirm, and gates the trusted run on--check. The asset never runs copier. In the interactive new-repo form copier's own prompts are that checkpoint. Claude Code auto-mode's classifier may denycopier … --trustoutright (it also denies the--skip-tasksdiscovery renders): this checkpoint is where the user settles that — preferably by approving the single run at the prompt, or by adding aBash(copier update:*)/Bash(copier copy:*)permission rule, knowing it is a standing, prefix-wide grant that also authorizes every later trusted copier run. Agents never self-grant permissions, and a parallel worker prints the set, stops, and returns it to the parent/human instead of confirming. Questions whose default is a Jinja expression (code_owner,claude_authorized_members) show asUNRESOLVED— the gate never renders — and a sensitive one must be stated explicitly before--confirmaccepts.Validate after every apply. Re-running
copieror changing answers can churn files — confirm the result with the verification step below before committing.Optimize for regular rolling updates, not every historical migration path. harmon-init-managed repositories are expected to stay near the current release. Review new answers against the target repository and pass the decisions explicitly. Do not add or expect permanent version-pair migrations for unusual gaps or customizations; reconcile those case by case in the downstream PR.
The asked questions live in ~/git/harmon-init/copier.yml (e.g. project_name,
project_slug, project_description, github_org, project_type
[general / web-astro / web-app / iac / docs], snyk_scan_schedule
[off / weekly / daily], include_terraform, include_ansible, ci_runner,
license, use_codeql, codeql_languages, use_release_please, devcontainer,
use_codex_review, use_codex_cloud_review, use_coderabbit, git_init).
Read that file to
confirm names/choices/defaults before scaffolding — do not invent answers.
Standards catalog
The authoritative, itemized list of what "standardized" means — every tool, config
file, Taskfile target, hook, and CI workflow the template provides, and how to check
each — is references/standards-catalog.md. The audit mode and any manual
retrofit work off that catalog. Treat the generated template output (and that
catalog) as the source of truth, not memory.
Vendored skills
After every template apply or update — in new-repo, adopt-existing, update, or
audit remediation — complete this step before the repository gate. Follow the
"Vendor shared agent skills" item in harmon-init's docs/CHECKLIST.md for the
setup context; do not replace it with hand-copied skills, agents, or consumer-side
helpers. For vendoring and its checks, use only task sync:skills,
task verify:skills, task verify:skills:offline, and (in the in-sync case)
git ls-remote --tags SOURCE_REPO.
Read .skills-sync.yaml and its destination provenance. If the manifest is
absent — the repo opted out of skills sync (e.g. use_skills_sync=false, as
general and IaC scaffolds and skills-source repos may) — there is nothing to
vendor: record Vendored skills: not configured in the summary and skip the rest
of this step. Otherwise report one of these states and take only its matching
action:
Never vendored. The manifest exists but the skills destination has no
# managed:provenance line — or, when the manifest has anagents:block, its agents destination has none. Ask for an explicit yes before doing anything. Name both consequences of that yes:verify:skillswill become live intask ciand the CI lint job; and the vendoredgauntletandshepherdwill become the Dev Loop procedure underAGENTS.md. Only after an explicit yes, run:task sync:skills task verify:skills task verify:skills:offlineCommit the materialized result in the same standardize PR as
chore(skills): vendor harmon-devkit REF (CATEGORIES).Pin moved. Provenance is present, but
task verify:skills:offlinefails because the manifest pin and vendored ref differ (normally a Renovate pin bump). Do not change the pin again; materialize the existing requested pin and run:task sync:skills task verify:skills task verify:skills:offlineCommit that refresh in the same standardize PR as
chore(skills): refresh harmon-devkit OLD to NEW.In sync. Provenance is present and the offline verification passes. Run:
git ls-remote --tags SOURCE_REPOIf it shows a release newer than the pin, report it and offer to bump the pin, sync, and commit the refresh. Default to no: Renovate owns the bump, and a version pin must never move silently.
Vendored skills and agents produced by this step ride in the standardize PR.
They are part of its deliverable, not scratch output to discard or split into a
separate PR. In the final summary, state Vendored skills: <never vendored | pin moved | in sync> — <what you did>.
Verification
Complete the Vendored skills step above before running the repository gate.
After applying any mode, run the bundled check:
assets/verify-applied.sh <target-repo-dir>
It confirms the expected files/tooling landed and then runs the repo's own gate
(task verify = the repo's fast check/build/validate/guard set; task check for lint only;
task install:hooks to wire lefthook). Report what passed and surface any gaps
against references/standards-catalog.md. Never bypass hooks (--no-verify is
prohibited); commit on a feature branch — no direct commits to main.
Gate the staged rollout against the target policy. Before publication, read
the generated target's AGENTS.md. Use the draft-workbench lifecycle only when
that authoritative file defines draft publication and ready-for-review as the
human handoff. If it still defines an ordinary PR or stop-at-green handoff, the
selected harmon-init release predates this lifecycle. Do not let a newer
vendored integrate (or shepherd, in a target that has not yet migrated)
override it: select a compatible harmon-init release, or
follow the target policy and report that lifecycle adoption remains blocked.
When .coderabbit.yaml is present, also require
reviews.auto_review.drafts: true before relying on CodeRabbit as a gate; an
older generated false value is the same upgrade blocker, not permission to
promote early.
On a compatible target, open a draft PR. When the target has a vendored
integrate (or shepherd, in a target that has not yet migrated) skill,
follow that procedure through its complete
draft-time checks/review gate and final promotion.
If the target has no vendored integrate/shepherd skill, use this fallback instead: keep the PR
draft while work is active; after each push, bounded-poll every required check
to a terminal result and inspect reviews, top-level comments, and every inline
thread. Settle every finding and deferred PR-body checkbox, run the target's
full local gate on the exact clean commit before each fix push, and repeat until
the unchanged head is clean. Use the shepherd-round cap in the target's policy,
or four rounds when it states none: one fix push or one no-change adjudication
cycle is a round. Stop early when the sole blocker survives two consecutive
rounds unchanged, or immediately for a permission, secret, external-service, or
maintainer-decision blocker; every non-success stop remains draft.
Before promotion, establish that every required workflow and review app runs on
drafts or was explicitly dispatched and settled on the exact head. Treat
automation available only through pull_request.ready_for_review as a
configuration blocker: ready can notify human reviewers immediately and is not
a reversible automation probe. Freeze one final snapshot of the head, draft
state, checks, reviews, mergeability, deferred findings, and unanswered threads.
For the content half of that snapshot, use the integrate skill's readiness-gate
script (integrate/assets/readiness-gate.sh, per integrate/SKILL.md §6 — or
the equivalent shepherd/assets/readiness-gate.sh per shepherd/SKILL.md §6
in a target that has not yet migrated —
check prints the fingerprint on a pass, fingerprint recomputes it after
promotion) whenever that skill
is installed alongside this one — one implementation, not a re-derivation. When it is
not (this fallback exists precisely for targets without a vendored
integrate/shepherd skill,
and this skill can be installed without it), construct the fingerprint to the
same contract, which is stated here in full because the file may be absent:
fetch each component (PR title/body, reviews, top-level comments, inline
comments, GraphQL thread resolution) into a checked capture and abort on any
non-zero exit — never pipe unchecked gh calls into a hash, which turns a
failed fetch into a stable hash of the components that survived; pipe
--slurp output to a standalone jq (gh api refuses --slurp with
--jq, and --slurp is what makes --paginate page-safe); hash
content-bearing fields only (IDs, authors, bodies, comment updated_at,
review states and submitted_at, thread isResolved), in stable order
(sort_by(.id)), excluding the PR's own updated_at and the draft flag,
which promotion itself mutates. A locally constructed fingerprint is only
ever compared against itself within this session — pre-promotion against
post-promotion — so satisfying the contract, not byte-identity with the
integrate skill's own recipe's hash, is what correctness requires. A failed component
means the fingerprint is unknown, and unknown cannot promote: the PR stays
draft.
Promote that head with gh pr ready, confirm it is still the same open head and
is no longer draft, then stop. Reconcile the remote state even if promotion or
confirmation fails; if an open PR is ready on an unverified head, run
gh pr ready --undo and confirm it is draft before resuming or stopping. Never
merge, and never report the human handoff from a failed or indeterminate gate.
At both stages, watch every required check to a terminal green result and inspect every review thread. Apply feedback you agree with and reply with a concrete repository-specific rationale when you disagree. Never merge; promote only the unchanged clean draft. Report the human handoff only after the final ready promotion is confirmed.