MIL-003: local project, framework submodule, hooks, templates and README #26

Merged
Tirsvad merged 1 commits from mil-003-scaffold-and-release into main 2026-10-05 09:55:14 +02:00
Owner

Third code phase of RepoFoundry: the local project, the framework submodule,
the framework's hooks and templates, and the full README.

Implements MIL-003 (tasks 1 to 5) and US-001.03 (UC-001 steps 8 to 10).

What the script does now

After the repositories and the mirror (MIL-002), --apply creates:

  1. The local project (#15): the directory, git init on main, the
    origin remote (and github if chosen) with no credential in any
    address
    , and, when the Gitea repository holds the license commit, that
    history (checkout -b main --track origin/main). No commit is made.
  2. The framework submodule (#16):
    ssh://git@<gitea host>:<port>/TirSystem/SQA-QC-Framework.git as
    framework. If git cannot fetch it, the message names the address and how
    to test SSH.
  3. Skills and git hooks (#17): install-skills.sh and
    install-git-hooks.sh from the framework, each only once; the plan gate
    (--enable-plan-gate) is optional.
  4. Templates (#18): AGENTS.md and docs/artifact-registry.md from the
    framework.
  5. README (#19): installation, configuration, usage, SSH prerequisite,
    token permissions, security decisions, error handling and recovery, code
    layout, stakeholders.

New optional config key FRAMEWORK_REPO (default
TirSystem/SQA-QC-Framework). Three new library files, one responsibility
each: git.sh, localproject.sh, framework.sh.

Nothing is overwritten without a yes

Each of these asks first (default no): using an existing directory, replacing
an existing core.hooksPath, replacing an existing AGENTS.md or
docs/artifact-registry.md. A remote that points elsewhere is never replaced;
git itself refuses to overwrite a file when the license history is checked out.

SSH

The framework comes over SSH. If the SSH test fails, the plan says so and
--apply asks whether to go on without the framework steps (default no);
they are then reported as skipped, and origin uses HTTPS. In that case the
Gitea history is fetched over HTTPS with the token handed to git through a
GIT_ASKPASS helper and the environment of that one command, never in a URL or
on a command line.

Verification

  • tests/run-tests.sh: 769 checks, 0 failed (run by the maintainer on
    Windows/Git Bash); shellcheck -x over the entry point and every library file
    and shfmt are clean.
  • The tests run real git against local bare repositories that stand in for
    Gitea and the framework (git's insteadOf rewrites the addresses), with a
    private git configuration and the real framework as the submodule. They check
    the remotes, the history, the submodule, the hooks, the plan gate refusing an
    unplanned commit, the templates, every "asks first" case, and that no token
    appears in any file of the new project.
  • A real bug found this way: PROJECT_ROOT is readonly in the script, so
    passing it to the framework scripts as a one-off prefix failed; it is now set
    with env, which also stops a PROJECT_ROOT in the caller's environment
    from redirecting the framework scripts. A test covers it.

Not verified yet (why this PR uses Refs, not Closes)

  • No run against real GitHub and Gitea repositories has happened: the API
    calls (creating repositories, the mirror) are verified against stubs, and the
    read-only preflight has run against the real hosts. Issue #20 (end-to-end
    test and final security review) is open for exactly this.
  • The two token scopes marked unconfirmed in the README, and the claim that a
    repository created with a license holds only LICENSE, are to be confirmed in
    that run.
  • The tests have only run on Windows (Git Bash) so far.

Notes for the reviewer

  • New behaviour is in localproject.sh, framework.sh, git.sh and the
    changes to apply.sh, plan.sh, steps.sh and hosts.sh.
  • The README.md is rewritten as the full guide; Status in it says what is
    still unverified.

Refs #15
Refs #16
Refs #17
Refs #18
Refs #19

🤖 Generated with Claude Code

Third code phase of RepoFoundry: the local project, the framework submodule, the framework's hooks and templates, and the full README. Implements MIL-003 (tasks 1 to 5) and US-001.03 (UC-001 steps 8 to 10). ## What the script does now After the repositories and the mirror (MIL-002), `--apply` creates: 1. **The local project (#15):** the directory, `git init` on `main`, the `origin` remote (and `github` if chosen) with **no credential in any address**, and, when the Gitea repository holds the license commit, that history (`checkout -b main --track origin/main`). No commit is made. 2. **The framework submodule (#16):** `ssh://git@<gitea host>:<port>/TirSystem/SQA-QC-Framework.git` as `framework`. If git cannot fetch it, the message names the address and how to test SSH. 3. **Skills and git hooks (#17):** `install-skills.sh` and `install-git-hooks.sh` from the framework, each only once; the plan gate (`--enable-plan-gate`) is optional. 4. **Templates (#18):** `AGENTS.md` and `docs/artifact-registry.md` from the framework. 5. **README (#19):** installation, configuration, usage, SSH prerequisite, token permissions, security decisions, error handling and recovery, code layout, stakeholders. New optional config key `FRAMEWORK_REPO` (default `TirSystem/SQA-QC-Framework`). Three new library files, one responsibility each: `git.sh`, `localproject.sh`, `framework.sh`. ## Nothing is overwritten without a yes Each of these asks first (default no): using an existing directory, replacing an existing `core.hooksPath`, replacing an existing `AGENTS.md` or `docs/artifact-registry.md`. A remote that points elsewhere is never replaced; git itself refuses to overwrite a file when the license history is checked out. ## SSH The framework comes over SSH. If the SSH test fails, the plan says so and `--apply` asks whether to go on **without** the framework steps (default no); they are then reported as skipped, and `origin` uses HTTPS. In that case the Gitea history is fetched over HTTPS with the token handed to git through a `GIT_ASKPASS` helper and the environment of that one command, never in a URL or on a command line. ## Verification - `tests/run-tests.sh`: 769 checks, 0 failed (run by the maintainer on Windows/Git Bash); `shellcheck -x` over the entry point and every library file and `shfmt` are clean. - The tests run **real git** against local bare repositories that stand in for Gitea and the framework (git's `insteadOf` rewrites the addresses), with a private git configuration and the real framework as the submodule. They check the remotes, the history, the submodule, the hooks, the plan gate refusing an unplanned commit, the templates, every "asks first" case, and that no token appears in any file of the new project. - A real bug found this way: `PROJECT_ROOT` is readonly in the script, so passing it to the framework scripts as a one-off prefix failed; it is now set with `env`, which also stops a `PROJECT_ROOT` in the caller's environment from redirecting the framework scripts. A test covers it. ## Not verified yet (why this PR uses `Refs`, not `Closes`) - **No run against real GitHub and Gitea repositories** has happened: the API calls (creating repositories, the mirror) are verified against stubs, and the read-only preflight has run against the real hosts. Issue #20 (end-to-end test and final security review) is open for exactly this. - The two token scopes marked unconfirmed in the README, and the claim that a repository created with a license holds only `LICENSE`, are to be confirmed in that run. - The tests have only run on Windows (Git Bash) so far. ## Notes for the reviewer - New behaviour is in `localproject.sh`, `framework.sh`, `git.sh` and the changes to `apply.sh`, `plan.sh`, `steps.sh` and `hosts.sh`. - The `README.md` is rewritten as the full guide; `Status` in it says what is still unverified. Refs #15 Refs #16 Refs #17 Refs #18 Refs #19 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Tirsvad added 1 commit 2026-10-05 09:54:54 +02:00
After the repositories and the mirror, the script now creates the local
project: the directory, git on main, credential-free origin (and github)
remotes, and the license history from Gitea. Then it adds the framework as
a submodule over SSH, installs its skills and git hooks once (plan gate
optional), and copies the AGENTS.md and artifact registry templates.

Nothing is overwritten without a yes: an existing directory, core.hooksPath,
AGENTS.md or docs/artifact-registry.md each ask first (default no). Without
SSH the framework steps can only be skipped, after a yes. No commit is made
in the new project. New optional config key FRAMEWORK_REPO.

New library files git.sh, localproject.sh and framework.sh. Tests run real
git against local bare repositories that stand in for Gitea and the
framework, with a private git configuration (769 checks). The README is now
the full guide.

Task: MIL-003#1
Task: MIL-003#2
Task: MIL-003#3
Task: MIL-003#4
Task: MIL-003#5
Refs #15
Refs #16
Refs #17
Refs #18
Refs #19

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Tirsvad merged commit c21a3c50f0 into main 2026-10-05 09:55:14 +02:00
Sign in to join this conversation.