Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c58c47d8e | ||
|
|
e23ef3a4b6 | ||
|
|
cc157816c7 | ||
|
|
e9872fa3ed | ||
|
|
c379dd4d75 | ||
|
|
4058ab4e3e | ||
|
|
1b1b6bec2e | ||
|
|
4287d218ae | ||
|
|
4f6204c58e | ||
|
|
08cb484498 | ||
|
|
b1c1fbf178 | ||
|
|
993722b742 | ||
|
|
b0925a51aa | ||
|
|
08d0371da5 |
@@ -8,7 +8,8 @@ RepoFoundry (`src/create-project.sh`) sets up a new project in one run:
|
|||||||
- and a **local project** with one credential-free remote, `origin` (Gitea), and the
|
- and a **local project** with one credential-free remote, `origin` (Gitea), and the
|
||||||
[SQA-QC-Framework](https://git.tirsystem.com/TirSystem/SQA-QC-Framework)
|
[SQA-QC-Framework](https://git.tirsystem.com/TirSystem/SQA-QC-Framework)
|
||||||
added as a git submodule, with its skills, git hooks (and optionally the plan
|
added as a git submodule, with its skills, git hooks (and optionally the plan
|
||||||
gate) and templates installed.
|
gate) and templates installed. The files it installs (`.claude`, `.agents` and
|
||||||
|
`AGENTS.md`) are excluded from git in the new project.
|
||||||
|
|
||||||
It is a Bash script. It asks for the repository name, description, visibility
|
It is a Bash script. It asks for the repository name, description, visibility
|
||||||
and owner (a user or an organization, separately on each host), shows a plan,
|
and owner (a user or an organization, separately on each host), shows a plan,
|
||||||
@@ -201,7 +202,8 @@ src/create-project.sh --apply # asks only "Create these now (y/n) [n]"
|
|||||||
|
|
||||||
`.env` is ignored by git. The script warns if it is readable by other users or
|
`.env` is ignored by git. The script warns if it is readable by other users or
|
||||||
not ignored by git. See [Token permissions](#token-permissions) for what each
|
not ignored by git. See [Token permissions](#token-permissions) for what each
|
||||||
token needs.
|
token needs, and [How to create the access tokens](howto/create-access-tokens.md)
|
||||||
|
for the steps, with pictures, to create the Gitea and the GitHub token.
|
||||||
|
|
||||||
`.env` is optional, and so is each key in it. A credential that is not
|
`.env` is optional, and so is each key in it. A credential that is not
|
||||||
provided (the file is missing, the key is absent or its value is empty) is
|
provided (the file is missing, the key is absent or its value is empty) is
|
||||||
@@ -258,6 +260,7 @@ Plan:
|
|||||||
Framework : add ssh://git@git.example.org:10022/Team/SQA-QC-Framework.git as a submodule
|
Framework : add ssh://git@git.example.org:10022/Team/SQA-QC-Framework.git as a submodule
|
||||||
Skills and hooks : install once; plan gate no
|
Skills and hooks : install once; plan gate no
|
||||||
Templates : AGENTS.md and docs/artifact-registry.md (you are asked before a file is replaced)
|
Templates : AGENTS.md and docs/artifact-registry.md (you are asked before a file is replaced)
|
||||||
|
Git excludes : /.claude /.agents /AGENTS.md go into .git/info/exclude (no tracked file changes)
|
||||||
```
|
```
|
||||||
|
|
||||||
Without `--apply` that is all that happens. With `--apply` the script asks
|
Without `--apply` that is all that happens. With `--apply` the script asks
|
||||||
@@ -271,7 +274,10 @@ Without `--apply` that is all that happens. With `--apply` the script asks
|
|||||||
repository holds the license commit, that history;
|
repository holds the license commit, that history;
|
||||||
5. the framework as the submodule `framework`;
|
5. the framework as the submodule `framework`;
|
||||||
6. the framework's skills and git hooks, and the plan gate if chosen;
|
6. the framework's skills and git hooks, and the plan gate if chosen;
|
||||||
7. `AGENTS.md` and `docs/artifact-registry.md` from the framework's templates.
|
7. `AGENTS.md` and `docs/artifact-registry.md` from the framework's templates;
|
||||||
|
8. `/.claude`, `/.agents` and `/AGENTS.md` added to the new project's
|
||||||
|
`.git/info/exclude`, so git does not list them (see
|
||||||
|
[The files git ignores](#the-files-git-ignores-in-the-new-project)).
|
||||||
|
|
||||||
No commit is made in the new project. Work on a branch there: the framework's
|
No commit is made in the new project. Work on a branch there: the framework's
|
||||||
hooks refuse commits on `main`.
|
hooks refuse commits on `main`.
|
||||||
@@ -297,6 +303,39 @@ it replaces an existing `core.hooksPath`, and before it replaces an existing
|
|||||||
replaces a remote that points somewhere else, and git itself refuses to
|
replaces a remote that points somewhere else, and git itself refuses to
|
||||||
overwrite a file when the license history is checked out.
|
overwrite a file when the license history is checked out.
|
||||||
|
|
||||||
|
### The files git ignores in the new project
|
||||||
|
|
||||||
|
The framework installs files that are copies, not the project's own work. After
|
||||||
|
the templates are copied, the script makes git ignore three paths in the new
|
||||||
|
project by adding them to its `.git/info/exclude`:
|
||||||
|
|
||||||
|
| Path | What it is |
|
||||||
|
| --- | --- |
|
||||||
|
| `/.claude` | the skills for the standalone Claude Code CLI (the whole folder) |
|
||||||
|
| `/.agents` | the skills for Codex CLI and other tools that read `.agents/skills` (the whole folder) |
|
||||||
|
| `/AGENTS.md` | the project instructions, copied from the framework's template |
|
||||||
|
|
||||||
|
- **Nothing is committed and no tracked file changes.** `.gitignore` is not
|
||||||
|
touched, and `framework`, `.gitmodules` and `docs/artifact-registry.md` stay
|
||||||
|
visible to git: they are part of the project.
|
||||||
|
- **The entries belong to this clone.** `.git/info/exclude` is never committed
|
||||||
|
or pushed, so a fresh clone has neither the entries nor these files. There,
|
||||||
|
run `git submodule update --init --recursive` and then
|
||||||
|
`bash framework/scripts/install-skills.sh` to make the skills again.
|
||||||
|
`AGENTS.md` cannot be made again that way: it is a copy of a template that
|
||||||
|
you edit, so what you add to it exists only in the clone where you wrote it.
|
||||||
|
- **The whole `.claude` and `.agents` folders are ignored,** not only their
|
||||||
|
`skills` folders, so anything else you keep there (settings, agents) is
|
||||||
|
ignored too.
|
||||||
|
- **A path git already tracks stays tracked,** because an exclusion does not
|
||||||
|
apply to a tracked file. The script never removes anything from git; the
|
||||||
|
summary names the path ("git tracks AGENTS.md, so it is not ignored"). Run
|
||||||
|
`git rm --cached` on it yourself if you want it ignored.
|
||||||
|
- **Without SSH to Gitea** the framework steps are skipped, and so is this one.
|
||||||
|
- **To track one of the paths anyway,** delete its line from
|
||||||
|
`.git/info/exclude` in the project and `git add` it. Running the script again
|
||||||
|
in that directory adds the line back.
|
||||||
|
|
||||||
## SSH access to Gitea
|
## SSH access to Gitea
|
||||||
|
|
||||||
The framework submodule is fetched over SSH on port **10022**
|
The framework submodule is fetched over SSH on port **10022**
|
||||||
@@ -325,6 +364,9 @@ Both tokens go in `.env` (never in `config.env`, never in a remote URL). The
|
|||||||
script sends them only in a request header, through a private temporary file,
|
script sends them only in a request header, through a private temporary file,
|
||||||
and never prints them.
|
and never prints them.
|
||||||
|
|
||||||
|
New to this? [How to create the access tokens](howto/create-access-tokens.md)
|
||||||
|
walks through both, step by step, with pictures.
|
||||||
|
|
||||||
### GitHub token (`GITHUB_PAT`, only when you choose GitHub)
|
### GitHub token (`GITHUB_PAT`, only when you choose GitHub)
|
||||||
|
|
||||||
The same token has two jobs: it creates the repository, and it is the
|
The same token has two jobs: it creates the repository, and it is the
|
||||||
@@ -406,6 +448,7 @@ step, `2` a usage error.
|
|||||||
| A step fails after another succeeded | stops and prints what exists, what failed and how to continue | fix the cause and run the **same command again with `--apply`**: what was created is offered for reuse |
|
| A step fails after another succeeded | stops and prints what exists, what failed and how to continue | fix the cause and run the **same command again with `--apply`**: what was created is offered for reuse |
|
||||||
| The mirror is refused (disabled, interval too short) | keeps the repositories and reports it | change `MIRROR_INTERVAL` or ask the Gitea administrator, then run again |
|
| The mirror is refused (disabled, interval too short) | keeps the repositories and reports it | change `MIRROR_INTERVAL` or ask the Gitea administrator, then run again |
|
||||||
| The framework submodule cannot be fetched | reports the address and how to test SSH | fix your SSH access, run again |
|
| The framework submodule cannot be fetched | reports the address and how to test SSH | fix your SSH access, run again |
|
||||||
|
| Git already tracks `.claude`, `.agents` or `AGENTS.md` in the project | leaves it tracked and names it in the summary; the other paths are excluded | `git rm --cached` it if you want it ignored |
|
||||||
| `sync_on_commit` was ignored by Gitea | warns; the mirror syncs on its interval | enable it in the repository settings if needed |
|
| `sync_on_commit` was ignored by Gitea | warns; the mirror syncs on its interval | enable it in the repository settings if needed |
|
||||||
|
|
||||||
A partial run is reported like this:
|
A partial run is reported like this:
|
||||||
@@ -449,6 +492,10 @@ web interface and the project directory by hand.
|
|||||||
copy.
|
copy.
|
||||||
- **The framework needs SSH.** Without SSH access to Gitea the framework steps
|
- **The framework needs SSH.** Without SSH access to Gitea the framework steps
|
||||||
can only be skipped.
|
can only be skipped.
|
||||||
|
- **The ignored framework files are not shared.** `.claude`, `.agents` and
|
||||||
|
`AGENTS.md` are excluded in the clone the script made, not in the repository,
|
||||||
|
so another clone does not have them (see
|
||||||
|
[The files git ignores](#the-files-git-ignores-in-the-new-project)).
|
||||||
- **Tested on Windows (Git Bash) only so far.** Running the tests on Linux and
|
- **Tested on Windows (Git Bash) only so far.** Running the tests on Linux and
|
||||||
macOS is an open follow-up.
|
macOS is an open follow-up.
|
||||||
|
|
||||||
@@ -480,9 +527,9 @@ file. The files are loaded from that directory only, by a fixed path.
|
|||||||
| `plan.sh` | printing what the script is about to do |
|
| `plan.sh` | printing what the script is about to do |
|
||||||
| `repositories.sh` | creating the GitHub and Gitea repositories |
|
| `repositories.sh` | creating the GitHub and Gitea repositories |
|
||||||
| `mirror.sh` | the Gitea to GitHub push mirror |
|
| `mirror.sh` | the Gitea to GitHub push mirror |
|
||||||
| `git.sh` | running git for the new project without prompts or tokens on a command line |
|
| `git.sh` | running git for the new project without prompts or tokens on a command line, and adding entries to its `.git/info/exclude` |
|
||||||
| `localproject.sh` | the local directory, git repository and remotes |
|
| `localproject.sh` | the local directory, git repository and remotes |
|
||||||
| `framework.sh` | the framework submodule, skills, hooks and templates |
|
| `framework.sh` | the framework submodule, skills, hooks and templates, and the git excludes for the files it installs |
|
||||||
| `apply.sh` | confirmations and the apply flow; the only code that changes anything |
|
| `apply.sh` | confirmations and the apply flow; the only code that changes anything |
|
||||||
| `cli.sh` | usage text and option parsing |
|
| `cli.sh` | usage text and option parsing |
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ document of a type. `Primary File` may contain a glob (e.g.
|
|||||||
| BC | Business Case | docs/business-case.md | 002 |
|
| BC | Business Case | docs/business-case.md | 002 |
|
||||||
| SA | Stakeholder Analysis | docs/stakeholder-analysis.md | 002 |
|
| SA | Stakeholder Analysis | docs/stakeholder-analysis.md | 002 |
|
||||||
| PP | Project Plan | docs/project-plan.md | 002 |
|
| PP | Project Plan | docs/project-plan.md | 002 |
|
||||||
| MIL | Milestone / Gateway | docs/milestones/*.md | 009 |
|
| MIL | Milestone / Gateway | docs/milestones/*.md | 010 |
|
||||||
| US | User Story | docs/user-stories.md | 002 |
|
| US | User Story | docs/user-stories.md | 002 |
|
||||||
| UC | Use Case | docs/uc-*/uc.md | 003 |
|
| UC | Use Case | docs/uc-*/uc.md | 003 |
|
||||||
| SSD | System Sequence Diagram | docs/uc-*/ssd.md | 003 |
|
| SSD | System Sequence Diagram | docs/uc-*/ssd.md | 003 |
|
||||||
@@ -24,7 +24,7 @@ document of a type. `Primary File` may contain a glob (e.g.
|
|||||||
| DCD | Design Class Diagram | docs/dcd.md | 004 |
|
| DCD | Design Class Diagram | docs/dcd.md | 004 |
|
||||||
| DICT | Domain Dictionary (PO and IT terms) | docs/dictionary.md | 002 |
|
| DICT | Domain Dictionary (PO and IT terms) | docs/dictionary.md | 002 |
|
||||||
| UCD | Use Case Diagram | docs/use-case-diagram.md | 002 |
|
| UCD | Use Case Diagram | docs/use-case-diagram.md | 002 |
|
||||||
| RC | SQA Review Record | docs/sqa/reviews/rc-*.md | 032 |
|
| RC | SQA Review Record | docs/sqa/reviews/rc-*.md | 033 |
|
||||||
| TM | Traceability Matrix | docs/sqa/traceability-matrix.md | 002 |
|
| TM | Traceability Matrix | docs/sqa/traceability-matrix.md | 002 |
|
||||||
|
|
||||||
## Languages
|
## Languages
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
## Version History
|
## Version History
|
||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | Objective 11, scope item and criterion 11: the configuration files default to the working folder's, then the checkout's | [0ab5006] |
|
| 2026-10-08 | Deprecated | Jens Tirsvad Nielsen | S02 | Objective 4: the local project has one remote, origin; no github remote, because a push to origin reaches GitHub through the mirror (MIL-008) | [039a28c] |
|
||||||
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | Objective 4: the local project has one remote, origin; no github remote, because a push to origin reaches GitHub through the mirror (MIL-008) | [039a28c] |
|
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | Objective 5 and scope: the installed `.claude`, `.agents` and `AGENTS.md` are excluded from git in the new project (MIL-009) | [08cb484] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ One repeatable, reviewed procedure gives every new project the same secure basel
|
|||||||
2. Create a Gitea repository under a chosen user or organization, empty, or with a license: the one set in `config.env` (`PROJECT_LICENSE`), or AGPL-3.0 when GitHub is chosen, the project is public and none is set.
|
2. Create a Gitea repository under a chosen user or organization, empty, or with a license: the one set in `config.env` (`PROJECT_LICENSE`), or AGPL-3.0 when GitHub is chosen, the project is public and none is set.
|
||||||
3. When GitHub was chosen, configure the Gitea repository as a push mirror to GitHub (direction Gitea to GitHub).
|
3. When GitHub was chosen, configure the Gitea repository as a push mirror to GitHub (direction Gitea to GitHub).
|
||||||
4. Create the local project directory with one remote, `origin` (Gitea), containing no credential. There is no `github` remote: a push to `origin` reaches GitHub through the push mirror.
|
4. Create the local project directory with one remote, `origin` (Gitea), containing no credential. There is no `github` remote: a push to `origin` reaches GitHub through the push mirror.
|
||||||
5. Add the SQA-QC-Framework as the `framework` submodule with its own submodules (the `qc` checklists) fetched, install its skills and git hooks, and copy its templates, optionally enabling the plan gate.
|
5. Add the SQA-QC-Framework as the `framework` submodule with its own submodules (the `qc` checklists) fetched, install its skills and git hooks, and copy its templates, optionally enabling the plan gate. Exclude the installed `.claude`, `.agents` and `AGENTS.md` from git in the new project, through its `.git/info/exclude`, so that no tracked file changes.
|
||||||
6. Never print a token or put one in a URL, a remote or a log, write one to disk only in the new project's own `.env` and only after the Maintainer agrees, and never overwrite existing files or directories without consent.
|
6. Never print a token or put one in a URL, a remote or a log, write one to disk only in the new project's own `.env` and only after the Maintainer agrees, and never overwrite existing files or directories without consent.
|
||||||
7. Document installation, configuration, usage, security decisions and error handling in clear English for GitHub readers.
|
7. Document installation, configuration, usage, security decisions and error handling in clear English for GitHub readers.
|
||||||
8. Let the Maintainer preset the project details in `config.env`, so that a detail that is set there is not asked again.
|
8. Let the Maintainer preset the project details in `config.env`, so that a detail that is set there is not asked again.
|
||||||
@@ -60,6 +60,7 @@ One repeatable, reviewed procedure gives every new project the same secure basel
|
|||||||
- Partial-failure reporting with a documented way to continue.
|
- Partial-failure reporting with a documented way to continue.
|
||||||
- Starting through a command link: the script finds its own files from the link, the new project lands in the folder it was started in, and `./config.env` and `./.env` there are read before the checkout's (confirmed before the first request).
|
- Starting through a command link: the script finds its own files from the link, the new project lands in the folder it was started in, and `./config.env` and `./.env` there are read before the checkout's (confirmed before the first request).
|
||||||
- Fetching the framework's own submodules (`git submodule update --init --recursive`), so the `qc` checklists are present.
|
- Fetching the framework's own submodules (`git submodule update --init --recursive`), so the `qc` checklists are present.
|
||||||
|
- Excluding `.claude`, `.agents` and `AGENTS.md` from git in the new project through its `.git/info/exclude`.
|
||||||
- Documentation of the SSH prerequisite for the submodule (Gitea SSH on port `10022`).
|
- Documentation of the SSH prerequisite for the submodule (Gitea SSH on port `10022`).
|
||||||
|
|
||||||
### Out of Scope
|
### Out of Scope
|
||||||
@@ -153,5 +154,5 @@ Proceed — the procedure is small, well bounded and removes a repeated, securit
|
|||||||
|
|
||||||
[SA-001]: ./stakeholder-analysis.md
|
[SA-001]: ./stakeholder-analysis.md
|
||||||
[UCD-001]: ./use-case-diagram.md
|
[UCD-001]: ./use-case-diagram.md
|
||||||
[0ab5006]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/0ab50068bf9e5be82a801af9dbe5b763eeaf7f31
|
|
||||||
[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03
|
[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03
|
||||||
|
[08cb484]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/commit/08cb484498bab3d9480decda9df89e9564438185
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
## Version History
|
## Version History
|
||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | .env is optional (as in UC-001 extension 2b): only config.env is required; a .env found nowhere means the token is asked | [24f1507] |
|
| 2026-10-08 | Deprecated | Jens Tirsvad Nielsen | S02 | LocalProjectBuilder.build() no longer takes the GitHub repository; a Local Project has one Remote, origin (MIL-008) | [039a28c] |
|
||||||
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | LocalProjectBuilder.build() no longer takes the GitHub repository; a Local Project has one Remote, origin (MIL-008) | [039a28c] |
|
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | FrameworkInstaller.excludeFromGit() and InstallResult.trackedPaths: `.claude`, `.agents` and `AGENTS.md` are excluded from git; UC-001 P15 (MIL-009) | [08cb484] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -75,6 +75,7 @@ class LocalProjectBuilder {
|
|||||||
}
|
}
|
||||||
class FrameworkInstaller {
|
class FrameworkInstaller {
|
||||||
+install(project : LocalProject, enablePlanGate : Boolean) : InstallResult
|
+install(project : LocalProject, enablePlanGate : Boolean) : InstallResult
|
||||||
|
-excludeFromGit(project : LocalProject) : String [0..*]
|
||||||
}
|
}
|
||||||
class SummaryReport {
|
class SummaryReport {
|
||||||
+compose(request : ProjectRequest) : Summary
|
+compose(request : ProjectRequest) : Summary
|
||||||
@@ -183,7 +184,9 @@ class Template {
|
|||||||
-name : String
|
-name : String
|
||||||
-isCopied : Boolean
|
-isCopied : Boolean
|
||||||
}
|
}
|
||||||
class InstallResult <<dto>>
|
class InstallResult <<dto>> {
|
||||||
|
-trackedPaths : String [0..*]
|
||||||
|
}
|
||||||
class Summary {
|
class Summary {
|
||||||
-createdItems : String [0..*]
|
-createdItems : String [0..*]
|
||||||
-skippedItems : String [0..*]
|
-skippedItems : String [0..*]
|
||||||
@@ -272,7 +275,7 @@ Repository "0..*" --> "1" Visibility
|
|||||||
| `GiteaClient` | Git Host (Gitea) | Hides the Gitea API and its token; creates the repository and the push mirror. | none beyond `GitHost` (uses `Configuration`) | `GiteaClient`, `hasLicense`, `createRepository`, `addPushMirror`, `requestSync` |
|
| `GiteaClient` | Git Host (Gitea) | Hides the Gitea API and its token; creates the repository and the push mirror. | none beyond `GitHost` (uses `Configuration`) | `GiteaClient`, `hasLicense`, `createRepository`, `addPushMirror`, `requestSync` |
|
||||||
| `GitHubClient` | Git Host (GitHub) | Hides the GitHub API and its token; creates the empty repository. | none beyond `GitHost` (uses `Configuration`) | `GitHubClient`, `createEmptyRepository` |
|
| `GitHubClient` | Git Host (GitHub) | Hides the GitHub API and its token; creates the empty repository. | none beyond `GitHost` (uses `Configuration`) | `GitHubClient`, `createEmptyRepository` |
|
||||||
| `LocalProjectBuilder` | Local Project, Remote | Creates the project directory, its git repository and its credential-free remotes. | none | `build` |
|
| `LocalProjectBuilder` | Local Project, Remote | Creates the project directory, its git repository and its credential-free remotes. | none | `build` |
|
||||||
| `FrameworkInstaller` | Framework, Framework Setup, Template | Adds the framework submodule, installs skills and hooks once, and copies the templates without overwriting. | none | `install` |
|
| `FrameworkInstaller` | Framework, Framework Setup, Template | Adds the framework submodule, installs skills and hooks once, copies the templates without overwriting, and excludes `.claude`, `.agents` and `AGENTS.md` from git through `.git/info/exclude`. | none | `install`, `excludeFromGit` |
|
||||||
| `SummaryReport` | Summary | Composes the report of what was created, skipped or failed. | none | `compose` |
|
| `SummaryReport` | Summary | Composes the report of what was created, skipped or failed. | none | `compose` |
|
||||||
| `Run` | none (system concept) | Holds the state of one execution. | `isApply` | none |
|
| `Run` | none (system concept) | Holds the state of one execution. | `isApply` | none |
|
||||||
| `Configuration` | Configuration | Holds the service addresses, the credentials and any preset project details. | `giteaUrl`, `giteaApiUrl`, `githubWebUrl`, `githubApiUrl`, `giteaSshPort`, `mirrorInterval`, `frameworkRepo`, `presetDetails` | none |
|
| `Configuration` | Configuration | Holds the service addresses, the credentials and any preset project details. | `giteaUrl`, `giteaApiUrl`, `githubWebUrl`, `githubApiUrl`, `giteaSshPort`, `mirrorInterval`, `frameworkRepo`, `presetDetails` | none |
|
||||||
@@ -293,7 +296,7 @@ Repository "0..*" --> "1" Visibility
|
|||||||
| `HookSetup` | Framework Setup | Records the skills and hooks installed and the plan gate state. | `areSkillsInstalled`, `areHooksInstalled`, `isPlanGateEnabled` | none |
|
| `HookSetup` | Framework Setup | Records the skills and hooks installed and the plan gate state. | `areSkillsInstalled`, `areHooksInstalled`, `isPlanGateEnabled` | none |
|
||||||
| `EnvFile` | Credentials File | The `.env` of the project: a copy of the credentials it needs. | `address`, `keys` | none |
|
| `EnvFile` | Credentials File | The `.env` of the project: a copy of the credentials it needs. | `address`, `keys` | none |
|
||||||
| `Template` | Template | A framework file copied into the project. | `name`, `isCopied` | none |
|
| `Template` | Template | A framework file copied into the project. | `name`, `isCopied` | none |
|
||||||
| `InstallResult` | none (carries the result of one operation) | Returns the submodule, the hook setup and the templates of `install`. | none | none |
|
| `InstallResult` | none (carries the result of one operation) | Returns the submodule, the hook setup and the templates of `install`, and the paths git already tracks that could not be excluded. | `trackedPaths` | none |
|
||||||
| `Summary` | Summary | The report returned to the Maintainer; it contains no credential. | `createdItems`, `skippedItems`, `nextSteps` | none |
|
| `Summary` | Summary | The report returned to the Maintainer; it contains no credential. | `createdItems`, `skippedItems`, `nextSteps` | none |
|
||||||
| `Visibility` | none (enumeration of a Project and Repository attribute) | The two allowed visibilities. | `private`, `public` | none |
|
| `Visibility` | none (enumeration of a Project and Repository attribute) | The two allowed visibilities. | `private`, `public` | none |
|
||||||
|
|
||||||
@@ -323,6 +326,7 @@ Repository "0..*" --> "1" Visibility
|
|||||||
| `GitHubClient.createEmptyRepository(request) : GitHubRepository` | [SD-001] `createEmptyRepository(request)`; P5 |
|
| `GitHubClient.createEmptyRepository(request) : GitHubRepository` | [SD-001] `createEmptyRepository(request)`; P5 |
|
||||||
| `LocalProjectBuilder.build(directory, source, sshPassed) : LocalProject` | [SD-001] `build(directory, giteaRepository, sshPassed)`; P7, P8, P9 |
|
| `LocalProjectBuilder.build(directory, source, sshPassed) : LocalProject` | [SD-001] `build(directory, giteaRepository, sshPassed)`; P7, P8, P9 |
|
||||||
| `FrameworkInstaller.install(project, enablePlanGate) : InstallResult` | [SD-001] `install(localProject, enablePlanGate)`; P10, P11, P12 |
|
| `FrameworkInstaller.install(project, enablePlanGate) : InstallResult` | [SD-001] `install(localProject, enablePlanGate)`; P10, P11, P12 |
|
||||||
|
| `FrameworkInstaller.excludeFromGit(project) : String [0..*]` | [SD-001] `excludeFromGit(localProject)`; P15 |
|
||||||
| `SummaryReport.compose(request) : Summary` | [SD-001] `compose(projectRequest)`; P13 |
|
| `SummaryReport.compose(request) : Summary` | [SD-001] `compose(projectRequest)`; P13 |
|
||||||
|
|
||||||
## Pattern Annotations
|
## Pattern Annotations
|
||||||
@@ -334,7 +338,7 @@ Repository "0..*" --> "1" Visibility
|
|||||||
| Pure Fabrication (GRASP) | `ConfigLoader`, `ToolChecker`, `CredentialCollector`, `EnvFileWriter`, `Preflight`, `LocalProjectBuilder`, `FrameworkInstaller`, `SummaryReport` | No domain concept owns these responsibilities; small units keep cohesion high |
|
| Pure Fabrication (GRASP) | `ConfigLoader`, `ToolChecker`, `CredentialCollector`, `EnvFileWriter`, `Preflight`, `LocalProjectBuilder`, `FrameworkInstaller`, `SummaryReport` | No domain concept owns these responsibilities; small units keep cohesion high |
|
||||||
| Creator (GRASP) | `ConfigLoader` creates `Configuration`; `GiteaClient` creates `GiteaRepository` and `PushMirror` | The creating class holds the data needed to build the object |
|
| Creator (GRASP) | `ConfigLoader` creates `Configuration`; `GiteaClient` creates `GiteaRepository` and `PushMirror` | The creating class holds the data needed to build the object |
|
||||||
| Protection from variations (GRASP) | `GiteaClient`, `GitHubClient`, `ProjectRequest` | The optional GitHub path is decided by the controller; the clients do not know it |
|
| Protection from variations (GRASP) | `GiteaClient`, `GitHubClient`, `ProjectRequest` | The optional GitHub path is decided by the controller; the clients do not know it |
|
||||||
| Data Transfer Object (GoF-style) | `InstallResult` | Carries the three results of `install` in one return value |
|
| Data Transfer Object (GoF-style) | `InstallResult` | Carries the results of `install` (the submodule, the hook setup, the templates and the tracked paths) in one return value |
|
||||||
|
|
||||||
## Dependency Check
|
## Dependency Check
|
||||||
|
|
||||||
@@ -373,5 +377,5 @@ SOLID check: no class has more than one reason to change (one host API, one kind
|
|||||||
[SD-001]: ./uc-001/sd.md
|
[SD-001]: ./uc-001/sd.md
|
||||||
[MIL-005]: ./milestones/mil-005-credentials.md
|
[MIL-005]: ./milestones/mil-005-credentials.md
|
||||||
[DICT-001]: ./dictionary.md
|
[DICT-001]: ./dictionary.md
|
||||||
[24f1507]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/24f15070fc73fb06e61865141fe0b825ea9e821e
|
|
||||||
[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03
|
[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03
|
||||||
|
[08cb484]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/commit/08cb484498bab3d9480decda9df89e9564438185
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
## Version History
|
## Version History
|
||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | Added Command Link, Checkout and Working Folder (DM-003, UC-002) | [1cd27f7] |
|
| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | `ConfigFiles` named as a system concept without a PO term | [0ab5006] |
|
||||||
| 2026-10-07 | Accepted | Jens Tirsvad Nielsen | S02 | `ConfigFiles` named as a system concept without a PO term | [0ab5006] |
|
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | Framework Setup and Template: the folders that hold the skills and the copy of AGENTS.md are ignored by git (MIL-009) | [08cb484] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -36,8 +36,8 @@ Maps each Product Owner (PO) term to its professional IT term. PO language: Engl
|
|||||||
| Local Project | en | LocalProject | The project directory on the Maintainer's machine. | DM, UC | OC, SD, DCD |
|
| Local Project | en | LocalProject | The project directory on the Maintainer's machine. | DM, UC | OC, SD, DCD |
|
||||||
| Remote | en | Remote | A named link from a local project to a repository. | DM, UC | OC, SD, DCD |
|
| Remote | en | Remote | A named link from a local project to a repository. | DM, UC | OC, SD, DCD |
|
||||||
| Framework | en | Submodule | The SQA-QC-Framework added to a local project; the IT term names how it is attached. | DM, UC | OC, SD, DCD |
|
| Framework | en | Submodule | The SQA-QC-Framework added to a local project; the IT term names how it is attached. | DM, UC | OC, SD, DCD |
|
||||||
| Framework Setup | en | HookSetup | The skills and git hooks installed from the framework, with the plan gate on or off. | DM, UC | OC, SD, DCD |
|
| Framework Setup | en | HookSetup | The skills and git hooks installed from the framework, with the plan gate on or off; the folders that hold the skills are ignored by git. | DM, UC | OC, SD, DCD |
|
||||||
| Template | en | Template | A framework file copied into a project. | DM, UC | OC, SD, DCD |
|
| Template | en | Template | A framework file copied into a project; the copy of `AGENTS.md` is ignored by git. | DM, UC | OC, SD, DCD |
|
||||||
| Credentials File | en | EnvFile | The file in the local project that holds a copy of the credentials the project needs; owner-only and ignored by git. | DM, UC | OC, SD, DCD |
|
| Credentials File | en | EnvFile | The file in the local project that holds a copy of the credentials the project needs; owner-only and ignored by git. | DM, UC | OC, SD, DCD |
|
||||||
| Command Link | en | CommandLink | A name on the shell's search path that leads to the script; made by the Maintainer, only followed by the system (no design class). | DM, UC | OC, SD, DCD |
|
| Command Link | en | CommandLink | A name on the shell's search path that leads to the script; made by the Maintainer, only followed by the system (no design class). | DM, UC | OC, SD, DCD |
|
||||||
| Checkout | en | Checkout | The folder that holds RepoFoundry and its default `config.env` and `.env`. | DM, UC | OC, SD, DCD |
|
| Checkout | en | Checkout | The folder that holds RepoFoundry and its default `config.env` and `.env`. | DM, UC | OC, SD, DCD |
|
||||||
@@ -68,5 +68,5 @@ Maps each Product Owner (PO) term to its professional IT term. PO language: Engl
|
|||||||
[DM-002]: ./domain-model.md
|
[DM-002]: ./domain-model.md
|
||||||
[OC-001]: ./uc-001/oc.md
|
[OC-001]: ./uc-001/oc.md
|
||||||
[DCD-001]: ./uc-001/dcd.md
|
[DCD-001]: ./uc-001/dcd.md
|
||||||
[1cd27f7]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/1cd27f77ed844773a969210a11de0d8bb98ac98f
|
|
||||||
[0ab5006]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/0ab50068bf9e5be82a801af9dbe5b763eeaf7f31
|
[0ab5006]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/0ab50068bf9e5be82a801af9dbe5b763eeaf7f31
|
||||||
|
[08cb484]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/commit/08cb484498bab3d9480decda9df89e9564438185
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
## Version History
|
## Version History
|
||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | Default configuration files: --config and --env, else ./config.env and ./.env in the working folder, else the checkout's | [0ab5006] |
|
| 2026-10-08 | Deprecated | Jens Tirsvad Nielsen | S02 | A Local Project has one Remote, origin, no longer one or two (MIL-008) | [039a28c] |
|
||||||
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | A Local Project has one Remote, origin, no longer one or two (MIL-008) | [039a28c] |
|
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | Framework Setup and Template: the folders that hold the skills and the copy of AGENTS.md are ignored by git (UC-001, MIL-009) | [08cb484] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -151,8 +151,8 @@ WorkingFolder "1" --> "0..*" LocalProject : is the base of
|
|||||||
| Local Project | The project directory on the Maintainer's machine | directory | [UC-001] step 8 "local project" |
|
| Local Project | The project directory on the Maintainer's machine | directory | [UC-001] step 8 "local project" |
|
||||||
| Remote | A named link from a Local Project to a Repository (`origin`) | name, address | [UC-001] step 8 "remote" |
|
| Remote | A named link from a Local Project to a Repository (`origin`) | name, address | [UC-001] step 8 "remote" |
|
||||||
| Framework | The SQA-QC-Framework added to a Local Project | name, address | [UC-001] step 9 "framework submodule" |
|
| Framework | The SQA-QC-Framework added to a Local Project | name, address | [UC-001] step 9 "framework submodule" |
|
||||||
| Framework Setup | The skills and git hooks installed from the Framework, with the plan gate on or off | plan gate enabled | [UC-001] step 9 "skills and hooks", "plan gate" |
|
| Framework Setup | The skills and git hooks installed from the Framework, with the plan gate on or off; the folders that hold the skills (`.claude`, `.agents`) are ignored by git | plan gate enabled | [UC-001] step 9 "skills and hooks", "plan gate", "excludes from git" |
|
||||||
| Template | A file the Framework provides to copy into a project (`AGENTS.md`, artifact registry) | name | [UC-001] step 9 "templates" |
|
| Template | A file the Framework provides to copy into a project (`AGENTS.md`, artifact registry); the copy of `AGENTS.md` is ignored by git | name | [UC-001] step 9 "templates", "excludes from git" |
|
||||||
| Credentials File | The file in a Local Project that holds a copy of the Access Tokens (and the GitHub account name) the project needs; readable by its owner only and ignored by git | address | [UC-001] step 9 "credentials file" |
|
| Credentials File | The file in a Local Project that holds a copy of the Access Tokens (and the GitHub account name) the project needs; readable by its owner only and ignored by git | address | [UC-001] step 9 "credentials file" |
|
||||||
| Command Link | A name in a folder on the shell's search path that leads to the script in the Checkout | name, folder | [UC-002] step 1 "command link" |
|
| Command Link | A name in a folder on the shell's search path that leads to the script in the Checkout | name, folder | [UC-002] step 1 "command link" |
|
||||||
| Checkout | The folder that holds RepoFoundry: the script, its own files and by default `config.env` and `.env` | path | [UC-002] step 4 "checkout" |
|
| Checkout | The folder that holds RepoFoundry: the script, its own files and by default `config.env` and `.env` | path | [UC-002] step 4 "checkout" |
|
||||||
@@ -207,5 +207,5 @@ WorkingFolder "1" --> "0..*" LocalProject : is the base of
|
|||||||
[SSD-001]: ./uc-001/ssd.md
|
[SSD-001]: ./uc-001/ssd.md
|
||||||
[DICT-001]: ./dictionary.md
|
[DICT-001]: ./dictionary.md
|
||||||
[DM-001]: ./uc-001/dm.md
|
[DM-001]: ./uc-001/dm.md
|
||||||
[0ab5006]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/0ab50068bf9e5be82a801af9dbe5b763eeaf7f31
|
|
||||||
[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03
|
[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03
|
||||||
|
[08cb484]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/commit/08cb484498bab3d9480decda9df89e9564438185
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
# MIL-009 Framework Files Excluded from Git
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | MIL-009 |
|
||||||
|
| CrossReference | [BC-001], [US-001], [UC-001], [OC-001], [DCD-002] |
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | Initial version | [08cb484] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Decide whether the files the framework installs into a new project, `.claude`, `.agents` and `AGENTS.md`, stay out of that project's git history. The skills in `.claude` and `.agents` are copies made by the framework's installer, and `AGENTS.md` is copied from a framework template. Git should not list them as untracked or offer them to a commit. They are excluded the way the project's `.env` already is: in `.git/info/exclude`, which belongs to the clone, is never committed and changes no tracked file.
|
||||||
|
|
||||||
|
## Deliverable
|
||||||
|
|
||||||
|
`create-project.sh` that, once the framework's skills and the templates are in place, adds `/.claude`, `/.agents` and `/AGENTS.md` to `.git/info/exclude` of the new project, as its own step ("Git excludes") that shows in the dry-run plan and in the summary. The documents agree with it: Business Case objective 5, US-001.03, UC-001 (postcondition, step 9, extension 9f and a rule), OC-001 (P15 and two exceptions), SD-001, DCD-001 and DCD-002, DM-001 and DM-002, and the dictionary. `README.md` says which files are excluded and why, and how to track one anyway. The tests cover the cases below. The version is raised to 0.3.2, and release `v0.3.2` is tagged on Gitea after the pull request is merged.
|
||||||
|
|
||||||
|
The exclusion is not applied when the framework steps are skipped (no SSH to Gitea): nothing was installed. A path that git already tracks stays tracked: the script never runs `git rm`, and the summary names the path, because an exclude entry does not apply to a tracked file. `framework`, `.gitmodules` and `docs/artifact-registry.md` are not excluded; the submodule and the registry are part of the project. The files of this repository (RepoFoundry itself) are unchanged.
|
||||||
|
|
||||||
|
## Go / No-Go Criteria
|
||||||
|
|
||||||
|
| # | Criterion (objectively checkable) | Go | No-Go |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 1 | After a run with the framework steps, `git check-ignore` reports `.claude`, `.agents` and `AGENTS.md` as ignored in the new project, and `git status --porcelain` lists none of them although they exist | Tests pass | Any of the three listed or not ignored |
|
||||||
|
| 2 | The entries are written only to `.git/info/exclude`: no `.gitignore` is created or changed, no tracked file changes and nothing is committed | Tests pass | Any other file changed |
|
||||||
|
| 3 | A second run writes no entry twice, keeps the existing lines of `.git/info/exclude` each on its own line (also when the file has no final newline), and writes nothing for a path that is already ignored | Tests pass | A duplicate, a merged line or a lost line |
|
||||||
|
| 4 | A path that git already tracks is neither untracked nor changed, and the summary names it as not ignored | Tests pass | A path untracked, or the summary silent |
|
||||||
|
| 5 | With the framework steps skipped (no SSH to Gitea) nothing is added to `.git/info/exclude` and the step reports `skipped` | Tests pass | An entry written |
|
||||||
|
| 6 | `framework`, `.gitmodules` and `docs/artifact-registry.md` are not ignored in the new project | Tests pass | Any of them ignored |
|
||||||
|
| 7 | The dry run lists the "Git excludes" step with the three entries and changes nothing; the summary reports the step in the same words | Tests pass | A change in a dry run, or the step missing |
|
||||||
|
| 8 | The `.env` exclusion behaves as before: added only after the yes, once, with the same comment line | Tests pass | A changed result |
|
||||||
|
| 9 | The README, Business Case, UC-001, OC-001, SD-001, DCD-001, DCD-002, DM-001 and DM-002 describe the exclusion and agree with the code; the documents the model does not change say so | Reviewed by S02 | A document that contradicts the code |
|
||||||
|
| 10 | All acceptance criteria of US-001.03 in [US-001] are met | Verified | Any unmet |
|
||||||
|
| 11 | `create-project.sh --version` prints `RepoFoundry 0.3.2` | Tests pass | Another version |
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
| Depends on | Reason |
|
||||||
|
| --- | --- |
|
||||||
|
| [MIL-003] | The framework, skills and templates steps are the ones that install the files |
|
||||||
|
| [MIL-005] | The `.git/info/exclude` code written for the project's `.env` is reused |
|
||||||
|
|
||||||
|
## Traceability
|
||||||
|
|
||||||
|
| Business Case objective / KPI / user story | Reference |
|
||||||
|
| --- | --- |
|
||||||
|
| User story US-001.03 | [US-001] |
|
||||||
|
| Objective 5 (the framework, its skills and its templates in the new project) | [BC-001] |
|
||||||
|
|
||||||
|
## Ownership
|
||||||
|
|
||||||
|
| Role | Stakeholder ID (SA) |
|
||||||
|
| --- | --- |
|
||||||
|
| Owner | S01 |
|
||||||
|
| Approving reviewer | S02 |
|
||||||
|
|
||||||
|
## Target Date
|
||||||
|
|
||||||
|
2026-12-23 — proposed; the Business Case sets no deadline.
|
||||||
|
|
||||||
|
## Tasks
|
||||||
|
|
||||||
|
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| 1 | Update the analysis and design documents | Business Case objective 5 and scope, the acceptance criteria of US-001.03, UC-001 (postcondition, step 9, extension 9f for a tracked path, and a rule), OC-001 (postcondition P15 and two exceptions), SD-001 (`excludeFromGit` inside `install`), DCD-001 and DCD-002 (`FrameworkInstaller.excludeFromGit`, `InstallResult.trackedPaths`), and the definitions of Framework Setup and Template in DM-001, DM-002 and the dictionary. | No | |
|
||||||
|
| 2 | Add the Git excludes step | Move the work of `exclude_env_file` (`src/lib/envfile.sh`) into a helper that adds a list of entries to `.git/info/exclude`: one comment line, a fresh line first, no entry that `git check-ignore` already reports, a check afterwards. `exclude_env_file` keeps its behavior and uses it. Add a function in `src/lib/framework.sh` that excludes `/.claude`, `/.agents` and `/AGENTS.md`, called from `create_all` (`src/lib/apply.sh`) after `copy_templates`, with its own label in `PLAN_STEPS` (`src/lib/constants.sh`) and a line in the dry-run plan (`src/lib/plan.sh`). It is skipped when `is_framework_skipped` and it names any path git tracks. Step 9 of [UC-001] and P12 of [OC-001]. | Yes | [UC-001] |
|
||||||
|
| 3 | Describe the excluded files in the README | Add the step to the overview and the numbered run steps, and the new line to the sample plan output. Say which paths are excluded and why (they come from the framework and are made again by `bash framework/scripts/install-skills.sh`), that nothing is committed or changed in a tracked file, that the entries live in `.git/info/exclude` and so are not shared with a clone, and how to track one anyway (remove its line from `.git/info/exclude`). | No | |
|
||||||
|
| 4 | Test the excludes | In the style of `tests/test-credentials.sh`: the three paths ignored and absent from `git status` after a run; a second run adds nothing; a file without a final newline keeps its lines; a tracked `AGENTS.md` stays tracked and is named; framework steps skipped writes nothing; `framework`, `.gitmodules` and `docs/artifact-registry.md` not ignored; the dry run changes nothing; the existing `.env` exclude tests still pass. | No | |
|
||||||
|
| 5 | Bump the version to 0.3.2 | Set `VERSION` in `src/lib/constants.sh` to 0.3.2 and the `--version` check in `tests/test-security.sh` to match. Release `v0.3.2` is tagged on Gitea from the merge commit once the pull request is merged. | No | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[BC-001]: ../business-case.md
|
||||||
|
[US-001]: ../user-stories.md
|
||||||
|
[UC-001]: ../uc-001/uc.md
|
||||||
|
[OC-001]: ../uc-001/oc.md
|
||||||
|
[DCD-002]: ../dcd.md
|
||||||
|
[MIL-003]: ./mil-003-scaffold-and-release.md
|
||||||
|
[MIL-005]: ./mil-005-credentials.md
|
||||||
|
[08cb484]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/commit/08cb484498bab3d9480decda9df89e9564438185
|
||||||
@@ -4,23 +4,23 @@
|
|||||||
| Key | Value |
|
| Key | Value |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| ID | PP-001 |
|
| ID | PP-001 |
|
||||||
| CrossReference | [BC-001], [SA-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007], [MIL-008], [US-001] |
|
| CrossReference | [BC-001], [SA-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007], [MIL-008], [MIL-009], [US-001] |
|
||||||
|
|
||||||
## Version History
|
## Version History
|
||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | Added phase MIL-007 (proposed dates 2026-12-07 to 2026-12-11); MIL-006 deliverable names the public-only AGPL-3.0 default | [1cd27f7] |
|
| 2026-10-08 | Deprecated | Jens Tirsvad Nielsen | S02 | Added phase MIL-008 (proposed dates 2026-12-14 to 2026-12-18): the local project has origin as its only remote | [039a28c] |
|
||||||
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | Added phase MIL-008 (proposed dates 2026-12-14 to 2026-12-18): the local project has origin as its only remote | [039a28c] |
|
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | Added phase MIL-009 (proposed dates 2026-12-21 to 2026-12-23): the framework files .claude, .agents and AGENTS.md are excluded from git | [08cb484] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Purpose
|
## Purpose
|
||||||
|
|
||||||
Schedule the eight phases that deliver RepoFoundry (`create-project.sh` and its documentation) in dependency order. The Business Case sets no deadline, so the dates below are proposals for S01 to confirm.
|
Schedule the nine phases that deliver RepoFoundry (`create-project.sh` and its documentation) in dependency order. The Business Case sets no deadline, so the dates below are proposals for S01 to confirm.
|
||||||
|
|
||||||
## Planning Assumptions
|
## Planning Assumptions
|
||||||
|
|
||||||
- Week 1 starts 2026-10-05; the plan ends by 2026-12-18 (the last three phases are proposed).
|
- Week 1 starts 2026-10-05; the plan ends by 2026-12-23 (the last four phases are proposed).
|
||||||
- Phase length: two weeks.
|
- Phase length: two weeks.
|
||||||
- S01 and S02 review each phase through a pull request, as described in [SA-001]. For now one person holds both roles.
|
- S01 and S02 review each phase through a pull request, as described in [SA-001]. For now one person holds both roles.
|
||||||
- The PO language is English, so no translated copies are kept.
|
- The PO language is English, so no translated copies are kept.
|
||||||
@@ -37,6 +37,7 @@ Schedule the eight phases that deliver RepoFoundry (`create-project.sh` and its
|
|||||||
| Project License | [MIL-006] | 2026-11-30 to 2026-12-04 | 2026-12-04 | S01 | US-001.06 | PROJECT_LICENSE in config.env; AGPL-3.0 default only for a public GitHub project | |
|
| Project License | [MIL-006] | 2026-11-30 to 2026-12-04 | 2026-12-04 | S01 | US-001.06 | PROJECT_LICENSE in config.env; AGPL-3.0 default only for a public GitHub project | |
|
||||||
| Framework Checklists and Usage | [MIL-007] | 2026-12-07 to 2026-12-11 | 2026-12-11 | S01 | US-001.07 | qc fetched with the framework; global command; README usage | |
|
| Framework Checklists and Usage | [MIL-007] | 2026-12-07 to 2026-12-11 | 2026-12-11 | S01 | US-001.07 | qc fetched with the framework; global command; README usage | |
|
||||||
| Gitea Is the Only Remote | [MIL-008] | 2026-12-14 to 2026-12-18 | 2026-12-18 | S01 | US-001.03 | The local project has `origin` only; GitHub is reached through the mirror | |
|
| Gitea Is the Only Remote | [MIL-008] | 2026-12-14 to 2026-12-18 | 2026-12-18 | S01 | US-001.03 | The local project has `origin` only; GitHub is reached through the mirror | |
|
||||||
|
| Framework Files Excluded from Git | [MIL-009] | 2026-12-21 to 2026-12-23 | 2026-12-23 | S01 | US-001.03 | `.claude`, `.agents` and `AGENTS.md` excluded from git in the new project | |
|
||||||
|
|
||||||
```plantuml
|
```plantuml
|
||||||
@startgantt
|
@startgantt
|
||||||
@@ -57,6 +58,8 @@ Project starts 2026-10-05
|
|||||||
[Framework Checklists and Usage Go/No-Go] happens 2026-12-11
|
[Framework Checklists and Usage Go/No-Go] happens 2026-12-11
|
||||||
[Gitea Is the Only Remote] starts 2026-12-14 and ends 2026-12-18
|
[Gitea Is the Only Remote] starts 2026-12-14 and ends 2026-12-18
|
||||||
[Gitea Is the Only Remote Go/No-Go] happens 2026-12-18
|
[Gitea Is the Only Remote Go/No-Go] happens 2026-12-18
|
||||||
|
[Framework Files Excluded from Git] starts 2026-12-21 and ends 2026-12-23
|
||||||
|
[Framework Files Excluded from Git Go/No-Go] happens 2026-12-23
|
||||||
@endgantt
|
@endgantt
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -76,11 +79,12 @@ Project starts 2026-10-05
|
|||||||
| Framework's own submodules fetched | [MIL-007] |
|
| Framework's own submodules fetched | [MIL-007] |
|
||||||
| README usage from the target folder and as a global command | [MIL-007] |
|
| README usage from the target folder and as a global command | [MIL-007] |
|
||||||
| The local project has `origin` as its only remote | [MIL-008] |
|
| The local project has `origin` as its only remote | [MIL-008] |
|
||||||
|
| `.claude`, `.agents` and `AGENTS.md` excluded from git in the new project | [MIL-009] |
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
```
|
```
|
||||||
MIL-001 → MIL-002 → MIL-003 → MIL-004 → MIL-005 → MIL-006 → MIL-007 → MIL-008
|
MIL-001 → MIL-002 → MIL-003 → MIL-004 → MIL-005 → MIL-006 → MIL-007 → MIL-008 → MIL-009
|
||||||
```
|
```
|
||||||
|
|
||||||
A No-Go moves every later date by the time needed to rework the failed criteria.
|
A No-Go moves every later date by the time needed to rework the failed criteria.
|
||||||
@@ -112,11 +116,12 @@ A No-Go moves every later date by the time needed to rework the failed criteria.
|
|||||||
[MIL-006]: ./milestones/mil-006-project-license.md
|
[MIL-006]: ./milestones/mil-006-project-license.md
|
||||||
[MIL-007]: ./milestones/mil-007-framework-checklists.md
|
[MIL-007]: ./milestones/mil-007-framework-checklists.md
|
||||||
[MIL-008]: ./milestones/mil-008-gitea-only-remote.md
|
[MIL-008]: ./milestones/mil-008-gitea-only-remote.md
|
||||||
|
[MIL-009]: ./milestones/mil-009-exclude-framework-files.md
|
||||||
[US-001]: ./user-stories.md
|
[US-001]: ./user-stories.md
|
||||||
[UC-001]: ./uc-001/uc.md
|
[UC-001]: ./uc-001/uc.md
|
||||||
[SSD-001]: ./uc-001/ssd.md
|
[SSD-001]: ./uc-001/ssd.md
|
||||||
[Milestone 43]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/milestone/43
|
[Milestone 43]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/milestone/43
|
||||||
[Milestone 44]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/milestone/44
|
[Milestone 44]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/milestone/44
|
||||||
[Milestone 45]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/milestone/45
|
[Milestone 45]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/milestone/45
|
||||||
[1cd27f7]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/1cd27f77ed844773a969210a11de0d8bb98ac98f
|
|
||||||
[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03
|
[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03
|
||||||
|
[08cb484]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/commit/08cb484498bab3d9480decda9df89e9564438185
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
# SQA Review Record: Framework files excluded from git
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | RC-032 |
|
||||||
|
| CrossReference | [MIL-009], [QC-MIL-001], [MIL-003], [MIL-005], [BC-001], [US-001], [UC-001], [OC-001], [SD-001], [DCD-001], [DCD-002], [DM-001], [DM-002], [DICT-001], [PP-001] |
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | Initial version: draft for S02's decision | [1b1b6be] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Artifact Under Review
|
||||||
|
|
||||||
|
- Instance reviewed: [MIL-009], and the changes it causes in [BC-001], [US-001], [UC-001], [OC-001], [SD-001], [DCD-001], [DCD-002], [DM-001], [DM-002], [DICT-001], [PP-001] and [TM-001].
|
||||||
|
- Why: a new project gets `.claude` and `.agents` (the framework's skills, made by `install-skills.sh`) and `AGENTS.md` (copied from a framework template). The request is that git excludes these three in the new project after the framework is installed. The phase adds that step, using the `.git/info/exclude` mechanism that [MIL-005] already uses for the project's `.env`.
|
||||||
|
- Checklist used: [QC-MIL-001] for [MIL-009]. The other artifacts were changed, not created; their change is checked below.
|
||||||
|
- Review date: 2026-10-08
|
||||||
|
|
||||||
|
## Checklist Results (QC-MIL-001)
|
||||||
|
|
||||||
|
| # | Criterion | Status | Evidence/Notes |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 1 | A concrete deliverable is defined for every gate | Pass | The script with a new "Git excludes" step that writes `/.claude`, `/.agents` and `/AGENTS.md` to `.git/info/exclude`, shown in the dry-run plan and the summary; the documents that agree with it; the README; the tests; version 0.3.2 and release `v0.3.2`. The cases that are not excluded (framework steps skipped, a tracked path, `framework`, `.gitmodules`, the registry) are stated. |
|
||||||
|
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Eleven criteria, each with an objective Go and No-Go: ignored and absent from `git status`, only `.git/info/exclude` written, a second run and a file without a final newline, a tracked path, framework steps skipped, paths that must stay visible, dry run and summary, the `.env` exclusion unchanged, the documents in agreement, the acceptance criteria of US-001.03, and the version. Criteria 9 and 10 are "Reviewed by S02" and "Verified", as in [MIL-007] and [MIL-008]. |
|
||||||
|
| 3 | Dependencies on other milestones are explicitly mapped | Pass | [MIL-003] (the framework, skills and templates steps install the files) and [MIL-005] (the `.git/info/exclude` code is reused), each with its reason. |
|
||||||
|
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Objective 5 of [BC-001], which this phase extends, and US-001.03. No success criterion fits, so none is cited. |
|
||||||
|
| 5 | Milestone owner and approving reviewer are identified | Pass | Owner S01, approving reviewer S02. |
|
||||||
|
| 6 | Milestone has a defined target date consistent with project constraints | Pass | 2026-12-23, proposed in [PP-001]; the window 2026-12-21 (Monday) to 2026-12-23 (Wednesday) follows [MIL-008], which ends Friday 2026-12-18. The Business Case sets no deadline. |
|
||||||
|
|
||||||
|
## Change checks on the other artifacts
|
||||||
|
|
||||||
|
| Artifact | Change | Status | Evidence/Notes |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| [BC-001] | Objective 5 and one in-scope item name the exclusion | Pass | The out-of-scope list (no first commit) is consistent: nothing is committed. |
|
||||||
|
| [US-001] | US-001.03 acceptance criterion; [MIL-009] in the CrossReference and the Traces row | Pass | One given/when/then. No new story: the behavior belongs to the local-project story, so the count of seven stories is unchanged. |
|
||||||
|
| [UC-001] | Postcondition, step 9, extension 9f, and a rule for step 9 | Pass | The rule fixes the mechanism (`.git/info/exclude`, never `.gitignore`), the whole folders, the paths that stay visible, and a tracked path. |
|
||||||
|
| [OC-001] | P15 and two exceptions | Pass | P15 is appended, so P1 to P14 and the references to them in [SD-001], [DCD-001] and [DCD-002] still hold. |
|
||||||
|
| [SD-001] | Self-message `excludeFromGit(localProject)` in `install`, return `installResult (trackedPaths)`, coverage row P15 | Pass | The pattern is the one already used for `requestSync`. Diagram not rendered (see action items). |
|
||||||
|
| [DCD-001], [DCD-002] | `FrameworkInstaller.excludeFromGit`, `InstallResult.trackedPaths`, the class table, the method traceability and the DTO sentence | Pass | Names and signature match [SD-001]. Diagram not rendered (see action items). |
|
||||||
|
| [DM-001], [DM-002], [DICT-001] | Definitions of Framework Setup and Template | Pass | No new concept or attribute, as for Credentials File ("ignored by git"). The use-case model, the project model and the dictionary say the same. |
|
||||||
|
| [PP-001] | Phase [MIL-009], its window, the Gantt, the scope coverage, the dependency chain, "nine phases" and the end date | Pass | Proposed dates 2026-12-21 to 2026-12-23. |
|
||||||
|
| [TM-001] | Row for [MIL-009] and this record; Last Reviewed updated for each changed artifact | Pass | See the matrix. |
|
||||||
|
|
||||||
|
Mechanical checks run for this review: every link definition of the changed files points at an existing file and none is unused; the Gantt dates fall on the weekdays named above; [MIL-009] has 11 criteria and 5 tasks; `sync-project.sh --milestone MIL-009` parses it (milestone 87, issues #65 to #69 created on Gitea); the new names (`excludeFromGit`, `trackedPaths`, P15) are the same in every document that uses them.
|
||||||
|
|
||||||
|
Not covered by this review: the code, the README and the tests (tasks 2 to 5 of [MIL-009]) do not exist yet. Criteria 1 to 8, 10 and 11 of [MIL-009] are checked at its gate, not here; criterion 9 is checked then too.
|
||||||
|
|
||||||
|
## Consequences S02 accepts with a Go
|
||||||
|
|
||||||
|
- The whole folders `.claude` and `.agents` are excluded, as requested, not only their `skills` folders. Anything else a project keeps there (settings, agents) is not tracked either.
|
||||||
|
- The entries live in `.git/info/exclude`, which belongs to the clone. A fresh clone has neither the entries nor the files. The skills can be made again with `install-skills.sh`; `AGENTS.md` cannot, because it is a copy of a template that the project edits.
|
||||||
|
|
||||||
|
## Overall Verdict
|
||||||
|
|
||||||
|
Go — every criterion of the checklist passes and the changed documents agree with each other. One check was not done: the PlantUML diagrams of [SD-001], [DCD-001] and [DCD-002] were not rendered, because no PlantUML server is configured and the framework does not choose one. Drafted by Claude Code for S02; the author and reviewer are the same person for now, as in [RC-031]. S02 gave the Go in chat on 2026-10-08, accepted the consequences listed above, and waived the diagram check; the Version History rows of [MIL-009] and the changed documents were set to `Accepted` and the rows before them to `Deprecated`.
|
||||||
|
|
||||||
|
## Action Items
|
||||||
|
|
||||||
|
| Action | Owner | Due |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| None. The diagram check was waived by S02 in chat on 2026-10-08; the three diagrams stay unrendered, and a syntax error found later is fixed in the document concerned | - | - |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[MIL-009]: ../../milestones/mil-009-exclude-framework-files.md
|
||||||
|
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
|
||||||
|
[MIL-003]: ../../milestones/mil-003-scaffold-and-release.md
|
||||||
|
[MIL-005]: ../../milestones/mil-005-credentials.md
|
||||||
|
[MIL-007]: ../../milestones/mil-007-framework-checklists.md
|
||||||
|
[MIL-008]: ../../milestones/mil-008-gitea-only-remote.md
|
||||||
|
[BC-001]: ../../business-case.md
|
||||||
|
[US-001]: ../../user-stories.md
|
||||||
|
[UC-001]: ../../uc-001/uc.md
|
||||||
|
[OC-001]: ../../uc-001/oc.md
|
||||||
|
[SD-001]: ../../uc-001/sd.md
|
||||||
|
[DCD-001]: ../../uc-001/dcd.md
|
||||||
|
[DCD-002]: ../../dcd.md
|
||||||
|
[DM-001]: ../../uc-001/dm.md
|
||||||
|
[DM-002]: ../../domain-model.md
|
||||||
|
[DICT-001]: ../../dictionary.md
|
||||||
|
[PP-001]: ../../project-plan.md
|
||||||
|
[TM-001]: ../traceability-matrix.md
|
||||||
|
[RC-031]: ./rc-031-gitea-only-remote.md
|
||||||
|
[1b1b6be]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/commit/1b1b6bec2effe5f566479ef94fcc5bc73a9fd609
|
||||||
@@ -9,8 +9,8 @@
|
|||||||
## Version History
|
## Version History
|
||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | Added review RC-030 (.env optional) | [24f1507] |
|
| 2026-10-08 | Deprecated | Jens Tirsvad Nielsen | S02 | Added MIL-009 (framework files excluded from git); not yet reviewed | [08cb484] |
|
||||||
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | Added MIL-008 with its review RC-031 (Gitea is the only remote) | [039a28c] |
|
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | Added review RC-032 (MIL-009: framework files excluded from git), Go | [1b1b6be] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -24,9 +24,9 @@ updated whenever an artifact instance is created or reviewed.
|
|||||||
|
|
||||||
| Artifact Instance | Type | Upstream (Backward Link) | Downstream (Forward Link) | Last Reviewed (RC-ID) |
|
| Artifact Instance | Type | Upstream (Backward Link) | Downstream (Forward Link) | Last Reviewed (RC-ID) |
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
| [BC-001] | BC | - | [SA-001], [PP-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007], [MIL-008], [US-001], [UCD-001] | [RC-010], [RC-018], [RC-020], [RC-022], [RC-029], [RC-031] |
|
| [BC-001] | BC | - | [SA-001], [PP-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007], [MIL-008], [MIL-009], [US-001], [UCD-001] | [RC-010], [RC-018], [RC-020], [RC-022], [RC-029], [RC-031], [RC-032] |
|
||||||
| [SA-001] | SA | [BC-001] | [UCD-001], [UC-001], [DICT-001] | [RC-013] |
|
| [SA-001] | SA | [BC-001] | [UCD-001], [UC-001], [DICT-001] | [RC-013] |
|
||||||
| [PP-001] | PP | [BC-001], [SA-001] | [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007], [MIL-008] | [RC-012], [RC-018], [RC-020], [RC-022], [RC-031] |
|
| [PP-001] | PP | [BC-001], [SA-001] | [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007], [MIL-008], [MIL-009] | [RC-012], [RC-018], [RC-020], [RC-022], [RC-031], [RC-032] |
|
||||||
| [MIL-001] | MIL | [BC-001], [PP-001] | [US-001] | [RC-011], [RC-016] |
|
| [MIL-001] | MIL | [BC-001], [PP-001] | [US-001] | [RC-011], [RC-016] |
|
||||||
| [MIL-002] | MIL | [BC-001], [PP-001] | [US-001] | [RC-014], [RC-017] |
|
| [MIL-002] | MIL | [BC-001], [PP-001] | [US-001] | [RC-014], [RC-017] |
|
||||||
| [MIL-003] | MIL | [BC-001], [PP-001] | [US-001] | [RC-015], [RC-017], [RC-031] |
|
| [MIL-003] | MIL | [BC-001], [PP-001] | [US-001] | [RC-015], [RC-017], [RC-031] |
|
||||||
@@ -35,9 +35,10 @@ updated whenever an artifact instance is created or reviewed.
|
|||||||
| [MIL-006] | MIL | [BC-001], [PP-001] | [US-001] | [RC-022] |
|
| [MIL-006] | MIL | [BC-001], [PP-001] | [US-001] | [RC-022] |
|
||||||
| [MIL-007] | MIL | [BC-001], [PP-001] | [US-001], [UC-002] | [RC-022], [RC-029], [RC-030] |
|
| [MIL-007] | MIL | [BC-001], [PP-001] | [US-001], [UC-002] | [RC-022], [RC-029], [RC-030] |
|
||||||
| [MIL-008] | MIL | [BC-001], [PP-001] | [US-001] | [RC-031] |
|
| [MIL-008] | MIL | [BC-001], [PP-001] | [US-001] | [RC-031] |
|
||||||
|
| [MIL-009] | MIL | [BC-001], [PP-001] | [US-001] | [RC-032] |
|
||||||
| [UCD-001] | UCD | [BC-001], [SA-001] | [US-001], [UC-001], [UC-002] | [RC-009], [RC-023] |
|
| [UCD-001] | UCD | [BC-001], [SA-001] | [US-001], [UC-001], [UC-002] | [RC-009], [RC-023] |
|
||||||
| [US-001] | US | [BC-001], [UCD-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007], [MIL-008] | [UC-001] | [RC-001], [RC-020], [RC-022], [RC-029], [RC-030], [RC-031] |
|
| [US-001] | US | [BC-001], [UCD-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007], [MIL-008], [MIL-009] | [UC-001] | [RC-001], [RC-020], [RC-022], [RC-029], [RC-030], [RC-031], [RC-032] |
|
||||||
| [UC-001] | UC | [UCD-001], [US-001], [SA-001] | [SSD-001], [DM-001] | [RC-002], [RC-020], [RC-023], [RC-031] |
|
| [UC-001] | UC | [UCD-001], [US-001], [SA-001] | [SSD-001], [DM-001] | [RC-002], [RC-020], [RC-023], [RC-031], [RC-032] |
|
||||||
| [UC-002] | UC | [UCD-001], [US-001], [SA-001], [BC-001] | [SSD-002], [DM-003] | [RC-023], [RC-029], [RC-030] |
|
| [UC-002] | UC | [UCD-001], [US-001], [SA-001], [BC-001] | [SSD-002], [DM-003] | [RC-023], [RC-029], [RC-030] |
|
||||||
| [SSD-002] | SSD | [UC-002], [DM-003] | [OC-002] | [RC-024], [RC-029] |
|
| [SSD-002] | SSD | [UC-002], [DM-003] | [OC-002] | [RC-024], [RC-029] |
|
||||||
| [DM-003] | DM | [UC-002], [UCD-001], [SSD-002], [DICT-001], [DM-001] | [OC-002], [DCD-003] | [RC-025], [RC-029] |
|
| [DM-003] | DM | [UC-002], [UCD-001], [SSD-002], [DICT-001], [DM-001] | [OC-002], [DCD-003] | [RC-025], [RC-029] |
|
||||||
@@ -45,13 +46,13 @@ updated whenever an artifact instance is created or reviewed.
|
|||||||
| [SD-002] | SD | [OC-002], [DCD-003] | [DCD-003] | [RC-027], [RC-029] |
|
| [SD-002] | SD | [OC-002], [DCD-003] | [DCD-003] | [RC-027], [RC-029] |
|
||||||
| [DCD-003] | DCD | [DM-003], [SD-002], [DICT-001], [UC-002], [DCD-001] | [DCD-002] | [RC-028], [RC-029], [RC-030] |
|
| [DCD-003] | DCD | [DM-003], [SD-002], [DICT-001], [UC-002], [DCD-001] | [DCD-002] | [RC-028], [RC-029], [RC-030] |
|
||||||
| [SSD-001] | SSD | [UC-001] | [OC-001] | [RC-003], [RC-020] |
|
| [SSD-001] | SSD | [UC-001] | [OC-001] | [RC-003], [RC-020] |
|
||||||
| [DM-001] | DM | [UC-001], [SSD-001] | [DM-002], [DICT-001], [OC-001], [DCD-001] | [RC-004], [RC-020], [RC-031] |
|
| [DM-001] | DM | [UC-001], [SSD-001] | [DM-002], [DICT-001], [OC-001], [DCD-001] | [RC-004], [RC-020], [RC-031], [RC-032] |
|
||||||
| [DM-002] | DM | [DM-001] | [DICT-001], [DCD-001], [DCD-002] | [RC-005], [RC-020], [RC-025], [RC-029], [RC-031] |
|
| [DM-002] | DM | [DM-001] | [DICT-001], [DCD-001], [DCD-002] | [RC-005], [RC-020], [RC-025], [RC-029], [RC-031], [RC-032] |
|
||||||
| [DICT-001] | DICT | [BC-001], [SA-001], [DM-001], [DM-002] | [OC-001], [SD-001] | [RC-008], [RC-020], [RC-025], [RC-029] |
|
| [DICT-001] | DICT | [BC-001], [SA-001], [DM-001], [DM-002] | [OC-001], [SD-001] | [RC-008], [RC-020], [RC-025], [RC-029], [RC-032] |
|
||||||
| [OC-001] | OC | [SSD-001], [DM-001] | [SD-001] | [RC-006], [RC-020], [RC-026], [RC-031] |
|
| [OC-001] | OC | [SSD-001], [DM-001] | [SD-001] | [RC-006], [RC-020], [RC-026], [RC-031], [RC-032] |
|
||||||
| [SD-001] | SD | [OC-001] | [DCD-001] | [RC-007], [RC-020], [RC-021], [RC-031] |
|
| [SD-001] | SD | [OC-001] | [DCD-001] | [RC-007], [RC-020], [RC-021], [RC-031], [RC-032] |
|
||||||
| [DCD-001] | DCD | [UC-001], [DM-001], [DM-002], [OC-001], [SD-001], [DICT-001] | [DCD-002] | [RC-021], [RC-031] |
|
| [DCD-001] | DCD | [UC-001], [DM-001], [DM-002], [OC-001], [SD-001], [DICT-001] | [DCD-002] | [RC-021], [RC-031], [RC-032] |
|
||||||
| [DCD-002] | DCD | [DCD-001], [DCD-003], [DM-002], [DICT-001] | - | [RC-021], [RC-028], [RC-029], [RC-030], [RC-031] |
|
| [DCD-002] | DCD | [DCD-001], [DCD-003], [DM-002], [DICT-001] | - | [RC-021], [RC-028], [RC-029], [RC-030], [RC-031], [RC-032] |
|
||||||
|
|
||||||
## Coverage Notes
|
## Coverage Notes
|
||||||
|
|
||||||
@@ -71,6 +72,7 @@ updated whenever an artifact instance is created or reviewed.
|
|||||||
[MIL-006]: ../milestones/mil-006-project-license.md
|
[MIL-006]: ../milestones/mil-006-project-license.md
|
||||||
[MIL-007]: ../milestones/mil-007-framework-checklists.md
|
[MIL-007]: ../milestones/mil-007-framework-checklists.md
|
||||||
[MIL-008]: ../milestones/mil-008-gitea-only-remote.md
|
[MIL-008]: ../milestones/mil-008-gitea-only-remote.md
|
||||||
|
[MIL-009]: ../milestones/mil-009-exclude-framework-files.md
|
||||||
[RC-018]: ./reviews/rc-018-mil-004.md
|
[RC-018]: ./reviews/rc-018-mil-004.md
|
||||||
[RC-019]: ./reviews/rc-019-mil-004-code.md
|
[RC-019]: ./reviews/rc-019-mil-004-code.md
|
||||||
[RC-020]: ./reviews/rc-020-mil-005.md
|
[RC-020]: ./reviews/rc-020-mil-005.md
|
||||||
@@ -85,6 +87,7 @@ updated whenever an artifact instance is created or reviewed.
|
|||||||
[RC-029]: ./reviews/rc-029-default-config-files.md
|
[RC-029]: ./reviews/rc-029-default-config-files.md
|
||||||
[RC-030]: ./reviews/rc-030-env-optional.md
|
[RC-030]: ./reviews/rc-030-env-optional.md
|
||||||
[RC-031]: ./reviews/rc-031-gitea-only-remote.md
|
[RC-031]: ./reviews/rc-031-gitea-only-remote.md
|
||||||
|
[RC-032]: ./reviews/rc-032-exclude-framework-files.md
|
||||||
[DCD-001]: ../uc-001/dcd.md
|
[DCD-001]: ../uc-001/dcd.md
|
||||||
[DCD-002]: ../dcd.md
|
[DCD-002]: ../dcd.md
|
||||||
[UCD-001]: ../use-case-diagram.md
|
[UCD-001]: ../use-case-diagram.md
|
||||||
@@ -119,5 +122,5 @@ updated whenever an artifact instance is created or reviewed.
|
|||||||
[RC-015]: ./reviews/rc-015-mil-003.md
|
[RC-015]: ./reviews/rc-015-mil-003.md
|
||||||
[RC-016]: ./reviews/rc-016-create-project-sh.md
|
[RC-016]: ./reviews/rc-016-create-project-sh.md
|
||||||
[RC-017]: ./reviews/rc-017-e2e-security-review.md
|
[RC-017]: ./reviews/rc-017-e2e-security-review.md
|
||||||
[24f1507]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/24f15070fc73fb06e61865141fe0b825ea9e821e
|
[08cb484]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/commit/08cb484498bab3d9480decda9df89e9564438185
|
||||||
[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03
|
[1b1b6be]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/commit/1b1b6bec2effe5f566479ef94fcc5bc73a9fd609
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
## Version History
|
## Version History
|
||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | Note that DCD-003 and DCD-002 supersede the signature of startProjectCreation | [0b0a3b4] |
|
| 2026-10-08 | Deprecated | Jens Tirsvad Nielsen | S02 | LocalProjectBuilder.build() no longer takes the GitHub repository; a Local Project has one Remote, origin (MIL-008) | [039a28c] |
|
||||||
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | LocalProjectBuilder.build() no longer takes the GitHub repository; a Local Project has one Remote, origin (MIL-008) | [039a28c] |
|
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | FrameworkInstaller.excludeFromGit() and InstallResult.trackedPaths: `.claude`, `.agents` and `AGENTS.md` are excluded from git; P15 (MIL-009) | [08cb484] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -79,6 +79,7 @@ class LocalProjectBuilder {
|
|||||||
}
|
}
|
||||||
class FrameworkInstaller {
|
class FrameworkInstaller {
|
||||||
+install(project : LocalProject, enablePlanGate : Boolean) : InstallResult
|
+install(project : LocalProject, enablePlanGate : Boolean) : InstallResult
|
||||||
|
-excludeFromGit(project : LocalProject) : String [0..*]
|
||||||
}
|
}
|
||||||
class SummaryReport {
|
class SummaryReport {
|
||||||
+compose(request : ProjectRequest) : Summary
|
+compose(request : ProjectRequest) : Summary
|
||||||
@@ -167,7 +168,9 @@ class Template {
|
|||||||
-name : String
|
-name : String
|
||||||
-isCopied : Boolean
|
-isCopied : Boolean
|
||||||
}
|
}
|
||||||
class InstallResult <<dto>>
|
class InstallResult <<dto>> {
|
||||||
|
-trackedPaths : String [0..*]
|
||||||
|
}
|
||||||
class Summary {
|
class Summary {
|
||||||
-createdItems : String [0..*]
|
-createdItems : String [0..*]
|
||||||
-skippedItems : String [0..*]
|
-skippedItems : String [0..*]
|
||||||
@@ -245,7 +248,7 @@ Repository "0..*" --> "1" Visibility
|
|||||||
| `GiteaClient` | Git Host (Gitea) | Hides the Gitea API and its token; creates the repository and the push mirror. | none beyond `GitHost` (uses `Configuration`) | `GiteaClient`, `hasLicense`, `createRepository`, `addPushMirror`, `requestSync` |
|
| `GiteaClient` | Git Host (Gitea) | Hides the Gitea API and its token; creates the repository and the push mirror. | none beyond `GitHost` (uses `Configuration`) | `GiteaClient`, `hasLicense`, `createRepository`, `addPushMirror`, `requestSync` |
|
||||||
| `GitHubClient` | Git Host (GitHub) | Hides the GitHub API and its token; creates the empty repository. | none beyond `GitHost` (uses `Configuration`) | `GitHubClient`, `createEmptyRepository` |
|
| `GitHubClient` | Git Host (GitHub) | Hides the GitHub API and its token; creates the empty repository. | none beyond `GitHost` (uses `Configuration`) | `GitHubClient`, `createEmptyRepository` |
|
||||||
| `LocalProjectBuilder` | Local Project, Remote | Creates the project directory, its git repository and its credential-free remotes. | none | `build` |
|
| `LocalProjectBuilder` | Local Project, Remote | Creates the project directory, its git repository and its credential-free remotes. | none | `build` |
|
||||||
| `FrameworkInstaller` | Framework, Framework Setup, Template | Adds the framework submodule, installs skills and hooks once, and copies the templates without overwriting. | none | `install` |
|
| `FrameworkInstaller` | Framework, Framework Setup, Template | Adds the framework submodule, installs skills and hooks once, copies the templates without overwriting, and excludes `.claude`, `.agents` and `AGENTS.md` from git through `.git/info/exclude`. | none | `install`, `excludeFromGit` |
|
||||||
| `SummaryReport` | Summary | Composes the report of what was created, skipped or failed. | none | `compose` |
|
| `SummaryReport` | Summary | Composes the report of what was created, skipped or failed. | none | `compose` |
|
||||||
| `Run` | none (system concept) | Holds the state of one execution. | `isApply` | none |
|
| `Run` | none (system concept) | Holds the state of one execution. | `isApply` | none |
|
||||||
| `Configuration` | Configuration | Holds the service addresses, the credentials and any preset project details. | `giteaUrl`, `giteaApiUrl`, `githubWebUrl`, `githubApiUrl`, `giteaSshPort`, `mirrorInterval`, `frameworkRepo`, `presetDetails` | none |
|
| `Configuration` | Configuration | Holds the service addresses, the credentials and any preset project details. | `giteaUrl`, `giteaApiUrl`, `githubWebUrl`, `githubApiUrl`, `giteaSshPort`, `mirrorInterval`, `frameworkRepo`, `presetDetails` | none |
|
||||||
@@ -266,7 +269,7 @@ Repository "0..*" --> "1" Visibility
|
|||||||
| `HookSetup` | Framework Setup | Records the skills and hooks installed and the plan gate state. | `areSkillsInstalled`, `areHooksInstalled`, `isPlanGateEnabled` | none |
|
| `HookSetup` | Framework Setup | Records the skills and hooks installed and the plan gate state. | `areSkillsInstalled`, `areHooksInstalled`, `isPlanGateEnabled` | none |
|
||||||
| `EnvFile` | Credentials File | The `.env` of the project: a copy of the credentials it needs. | `address`, `keys` | none |
|
| `EnvFile` | Credentials File | The `.env` of the project: a copy of the credentials it needs. | `address`, `keys` | none |
|
||||||
| `Template` | Template | A framework file copied into the project. | `name`, `isCopied` | none |
|
| `Template` | Template | A framework file copied into the project. | `name`, `isCopied` | none |
|
||||||
| `InstallResult` | none (carries the result of one operation) | Returns the submodule, the hook setup and the templates of `install`. | none | none |
|
| `InstallResult` | none (carries the result of one operation) | Returns the submodule, the hook setup and the templates of `install`, and the paths git already tracks that could not be excluded. | `trackedPaths` | none |
|
||||||
| `Summary` | Summary | The report returned to the Maintainer; it contains no credential. | `createdItems`, `skippedItems`, `nextSteps` | none |
|
| `Summary` | Summary | The report returned to the Maintainer; it contains no credential. | `createdItems`, `skippedItems`, `nextSteps` | none |
|
||||||
| `Visibility` | none (enumeration of a Project and Repository attribute) | The two allowed visibilities. | `private`, `public` | none |
|
| `Visibility` | none (enumeration of a Project and Repository attribute) | The two allowed visibilities. | `private`, `public` | none |
|
||||||
|
|
||||||
@@ -293,6 +296,7 @@ Repository "0..*" --> "1" Visibility
|
|||||||
| `GitHubClient.createEmptyRepository(request) : GitHubRepository` | [SD-001] `createEmptyRepository(request)`; P5 |
|
| `GitHubClient.createEmptyRepository(request) : GitHubRepository` | [SD-001] `createEmptyRepository(request)`; P5 |
|
||||||
| `LocalProjectBuilder.build(directory, source, sshPassed) : LocalProject` | [SD-001] `build(directory, giteaRepository, sshPassed)`; P7, P8, P9 |
|
| `LocalProjectBuilder.build(directory, source, sshPassed) : LocalProject` | [SD-001] `build(directory, giteaRepository, sshPassed)`; P7, P8, P9 |
|
||||||
| `FrameworkInstaller.install(project, enablePlanGate) : InstallResult` | [SD-001] `install(localProject, enablePlanGate)`; P10, P11, P12 |
|
| `FrameworkInstaller.install(project, enablePlanGate) : InstallResult` | [SD-001] `install(localProject, enablePlanGate)`; P10, P11, P12 |
|
||||||
|
| `FrameworkInstaller.excludeFromGit(project) : String [0..*]` | [SD-001] `excludeFromGit(localProject)`; P15 |
|
||||||
| `SummaryReport.compose(request) : Summary` | [SD-001] `compose(projectRequest)`; P13 |
|
| `SummaryReport.compose(request) : Summary` | [SD-001] `compose(projectRequest)`; P13 |
|
||||||
|
|
||||||
## Pattern Annotations
|
## Pattern Annotations
|
||||||
@@ -304,7 +308,7 @@ Repository "0..*" --> "1" Visibility
|
|||||||
| Pure Fabrication (GRASP) | `ConfigLoader`, `ToolChecker`, `CredentialCollector`, `EnvFileWriter`, `Preflight`, `LocalProjectBuilder`, `FrameworkInstaller`, `SummaryReport` | No domain concept owns these responsibilities; small units keep cohesion high |
|
| Pure Fabrication (GRASP) | `ConfigLoader`, `ToolChecker`, `CredentialCollector`, `EnvFileWriter`, `Preflight`, `LocalProjectBuilder`, `FrameworkInstaller`, `SummaryReport` | No domain concept owns these responsibilities; small units keep cohesion high |
|
||||||
| Creator (GRASP) | `ConfigLoader` creates `Configuration`; `GiteaClient` creates `GiteaRepository` and `PushMirror` | The creating class holds the data needed to build the object |
|
| Creator (GRASP) | `ConfigLoader` creates `Configuration`; `GiteaClient` creates `GiteaRepository` and `PushMirror` | The creating class holds the data needed to build the object |
|
||||||
| Protection from variations (GRASP) | `GiteaClient`, `GitHubClient`, `ProjectRequest` | The optional GitHub path is decided by the controller; the clients do not know it |
|
| Protection from variations (GRASP) | `GiteaClient`, `GitHubClient`, `ProjectRequest` | The optional GitHub path is decided by the controller; the clients do not know it |
|
||||||
| Data Transfer Object (GoF-style) | `InstallResult` | Carries the three results of `install` in one return value |
|
| Data Transfer Object (GoF-style) | `InstallResult` | Carries the results of `install` (the submodule, the hook setup, the templates and the tracked paths) in one return value |
|
||||||
|
|
||||||
## Dependency Check
|
## Dependency Check
|
||||||
|
|
||||||
@@ -341,5 +345,5 @@ SOLID check: no class has more than one reason to change (one host API, one kind
|
|||||||
[DCD-002]: ../dcd.md
|
[DCD-002]: ../dcd.md
|
||||||
[DCD-003]: ../uc-002/dcd.md
|
[DCD-003]: ../uc-002/dcd.md
|
||||||
[UC-002]: ../uc-002/uc.md
|
[UC-002]: ../uc-002/uc.md
|
||||||
[0b0a3b4]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/0b0a3b419a1157b23bddd2f8957a08adaf6974a6
|
|
||||||
[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03
|
[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03
|
||||||
|
[08cb484]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/commit/08cb484498bab3d9480decda9df89e9564438185
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
## Version History
|
## Version History
|
||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | License: the AGPL-3.0 default needs GitHub and a public project | [1cd27f7] |
|
| 2026-10-08 | Deprecated | Jens Tirsvad Nielsen | S02 | A Local Project has one Remote, origin, no longer one or two (MIL-008) | [039a28c] |
|
||||||
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | A Local Project has one Remote, origin, no longer one or two (MIL-008) | [039a28c] |
|
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | Framework Setup and Template: the folders that hold the skills and the copy of AGENTS.md are ignored by git (MIL-009) | [08cb484] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -135,8 +135,8 @@ Summary "1" --> "1" Project : reports on
|
|||||||
| Local Project | The project directory on the Maintainer's machine | directory | [UC-001] step 8 "local project" |
|
| Local Project | The project directory on the Maintainer's machine | directory | [UC-001] step 8 "local project" |
|
||||||
| Remote | A named link from a Local Project to a Repository (`origin`) | name, address | [UC-001] step 8 "remote" |
|
| Remote | A named link from a Local Project to a Repository (`origin`) | name, address | [UC-001] step 8 "remote" |
|
||||||
| Framework | The SQA-QC-Framework added to a Local Project | name, address | [UC-001] step 9 "framework submodule" |
|
| Framework | The SQA-QC-Framework added to a Local Project | name, address | [UC-001] step 9 "framework submodule" |
|
||||||
| Framework Setup | The skills and git hooks installed from the Framework, with the plan gate on or off | plan gate enabled | [UC-001] step 9 "skills and hooks", "plan gate" |
|
| Framework Setup | The skills and git hooks installed from the Framework, with the plan gate on or off; the folders that hold the skills (`.claude`, `.agents`) are ignored by git | plan gate enabled | [UC-001] step 9 "skills and hooks", "plan gate", "excludes from git" |
|
||||||
| Template | A file the Framework provides to copy into a project (`AGENTS.md`, artifact registry) | name | [UC-001] step 9 "templates" |
|
| Template | A file the Framework provides to copy into a project (`AGENTS.md`, artifact registry); the copy of `AGENTS.md` is ignored by git | name | [UC-001] step 9 "templates", "excludes from git" |
|
||||||
| Credentials File | The file in a Local Project that holds a copy of the Access Tokens (and the GitHub account name) the project needs; readable by its owner only and ignored by git | address | [UC-001] step 9 "credentials file" |
|
| Credentials File | The file in a Local Project that holds a copy of the Access Tokens (and the GitHub account name) the project needs; readable by its owner only and ignored by git | address | [UC-001] step 9 "credentials file" |
|
||||||
| Summary | The report of what was created, skipped or failed and how to continue | created items, skipped items, next steps | [UC-001] step 10 "summary" |
|
| Summary | The report of what was created, skipped or failed and how to continue | created items, skipped items, next steps | [UC-001] step 10 "summary" |
|
||||||
|
|
||||||
@@ -180,5 +180,5 @@ Summary "1" --> "1" Project : reports on
|
|||||||
[SSD-001]: ./ssd.md
|
[SSD-001]: ./ssd.md
|
||||||
[DICT-001]: ../dictionary.md
|
[DICT-001]: ../dictionary.md
|
||||||
[DM-002]: ../domain-model.md
|
[DM-002]: ../domain-model.md
|
||||||
[1cd27f7]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/1cd27f77ed844773a969210a11de0d8bb98ac98f
|
|
||||||
[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03
|
[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03
|
||||||
|
[08cb484]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/commit/08cb484498bab3d9480decda9df89e9564438185
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
## Version History
|
## Version History
|
||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | Note that OC-002 and DCD-002 supersede the signature of startProjectCreation | [0b0a3b4] |
|
| 2026-10-08 | Deprecated | Jens Tirsvad Nielsen | S02 | P9: no other remote is associated with the local project (MIL-008) | [039a28c] |
|
||||||
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | P9: no other remote is associated with the local project (MIL-008) | [039a28c] |
|
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | P15 and two exceptions: `.claude`, `.agents` and `AGENTS.md` are excluded from git; a tracked path is reported (MIL-009) | [08cb484] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -77,6 +77,7 @@ Concepts below use the IT terms of [DICT-001] for the PO concepts of [DM-001]. `
|
|||||||
- P12. `AGENTS.md` and `docs/artifact-registry.md` exist in the `LocalProject`, each either newly copied from the framework templates or left as it was because the Maintainer declined to replace it.
|
- P12. `AGENTS.md` and `docs/artifact-registry.md` exist in the `LocalProject`, each either newly copied from the framework templates or left as it was because the Maintainer declined to replace it.
|
||||||
- P13. A `Summary` instance was created listing every created item, every skipped item and the next step for anything that failed, and is returned. It contains no credential.
|
- P13. A `Summary` instance was created listing every created item, every skipped item and the next step for anything that failed, and is returned. It contains no credential.
|
||||||
- P14. If `writeEnvFile`, an `EnvFile` named `.env` was associated with the `LocalProject`, holding only the `Credential`s the project needs (the Gitea token, and the GitHub token and account name when `githubOwner` is present). It is readable by its owner only and excluded from git without a change to any tracked file, and no `Credential` is shown in any output. If `writeEnvFile` is false, no `EnvFile` was created. An existing `.env` is left as it was unless the Maintainer agreed to replace it.
|
- P14. If `writeEnvFile`, an `EnvFile` named `.env` was associated with the `LocalProject`, holding only the `Credential`s the project needs (the Gitea token, and the GitHub token and account name when `githubOwner` is present). It is readable by its owner only and excluded from git without a change to any tracked file, and no `Credential` is shown in any output. If `writeEnvFile` is false, no `EnvFile` was created. An existing `.env` is left as it was unless the Maintainer agreed to replace it.
|
||||||
|
- P15. If the `Submodule` and the `HookSetup` were created (P10, P11), the paths `.claude`, `.agents` and `AGENTS.md` of the `LocalProject` are excluded from git: each has an entry in the `.git/info/exclude` of the `LocalProject`, whether or not the path exists yet and whether or not the Maintainer declined replacing `AGENTS.md` (P12). No tracked file was changed and no commit was made. A path that git already tracks stays tracked, and the `Summary` lists it as not excluded. `framework`, `.gitmodules` and `docs/artifact-registry.md` are not excluded.
|
||||||
|
|
||||||
**Exceptions**
|
**Exceptions**
|
||||||
|
|
||||||
@@ -91,6 +92,8 @@ Concepts below use the IT terms of [DICT-001] for the PO concepts of [DM-001]. `
|
|||||||
| A different `core.hooksPath` exists and the Maintainer declines replacing it (P11) | Hooks are not installed and this is listed in the `Summary` |
|
| A different `core.hooksPath` exists and the Maintainer declines replacing it (P11) | Hooks are not installed and this is listed in the `Summary` |
|
||||||
| The framework's own submodules cannot be fetched (P10) | The `Summary` lists the `framework` `Submodule` as added, its own submodules as failed, and the command `git submodule update --init --recursive` to run by hand |
|
| The framework's own submodules cannot be fetched (P10) | The `Summary` lists the `framework` `Submodule` as added, its own submodules as failed, and the command `git submodule update --init --recursive` to run by hand |
|
||||||
| SSH to port 10022 fails and the `Submodule` cannot be added (P10) | The `Summary` lists the repositories as created, the submodule as failed, and the SSH prerequisite |
|
| SSH to port 10022 fails and the `Submodule` cannot be added (P10) | The `Summary` lists the repositories as created, the submodule as failed, and the SSH prerequisite |
|
||||||
|
| SSH to port 10022 fails and the Maintainer goes on without the framework (P10, P11, P12, P15) | No `Submodule`, `HookSetup` or template is created and no path is excluded; the `Summary` lists each of these steps as skipped |
|
||||||
|
| `.claude`, `.agents` or `AGENTS.md` is already tracked by git (P15) | The path stays tracked and is listed in the `Summary` as not excluded; the other paths are excluded |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -101,5 +104,5 @@ Concepts below use the IT terms of [DICT-001] for the PO concepts of [DM-001]. `
|
|||||||
[OC-002]: ../uc-002/oc.md
|
[OC-002]: ../uc-002/oc.md
|
||||||
[DCD-002]: ../dcd.md
|
[DCD-002]: ../dcd.md
|
||||||
[UC-002]: ../uc-002/uc.md
|
[UC-002]: ../uc-002/uc.md
|
||||||
[0b0a3b4]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/0b0a3b419a1157b23bddd2f8957a08adaf6974a6
|
|
||||||
[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03
|
[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03
|
||||||
|
[08cb484]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/commit/08cb484498bab3d9480decda9df89e9564438185
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
## Version History
|
## Version History
|
||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | Note that SD-002 and DCD-002 supersede the signature of startProjectCreation | [0b0a3b4] |
|
| 2026-10-08 | Deprecated | Jens Tirsvad Nielsen | S02 | build() no longer receives the GitHub repository and returns a local project with the remote origin; P9 (MIL-008) | [039a28c] |
|
||||||
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | build() no longer receives the GitHub repository and returns a local project with the remote origin; P9 (MIL-008) | [039a28c] |
|
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | install() excludes the installed files from git with excludeFromGit() and returns the tracked paths; P15 (MIL-009) | [08cb484] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -154,7 +154,8 @@ deactivate LB
|
|||||||
create FI
|
create FI
|
||||||
PC -> FI : install(localProject, enablePlanGate)
|
PC -> FI : install(localProject, enablePlanGate)
|
||||||
activate FI
|
activate FI
|
||||||
FI --> PC : installResult
|
FI -> FI : excludeFromGit(localProject)
|
||||||
|
FI --> PC : installResult (trackedPaths)
|
||||||
deactivate FI
|
deactivate FI
|
||||||
|
|
||||||
opt writeEnvFile
|
opt writeEnvFile
|
||||||
@@ -209,6 +210,7 @@ destroy SR
|
|||||||
| P12 AGENTS.md and registry copied or kept | `install(...)` returning `templates` |
|
| P12 AGENTS.md and registry copied or kept | `install(...)` returning `templates` |
|
||||||
| P13 Summary created and returned | `compose(request)` and the final return |
|
| P13 Summary created and returned | `compose(request)` and the final return |
|
||||||
| P14 EnvFile created with the needed credentials, owner-only, ignored by git, or none when declined | `write(localProject, configuration, githubOwner present)` inside `opt writeEnvFile` |
|
| P14 EnvFile created with the needed credentials, owner-only, ignored by git, or none when declined | `write(localProject, configuration, githubOwner present)` inside `opt writeEnvFile` |
|
||||||
|
| P15 `.claude`, `.agents` and `AGENTS.md` excluded from git; a tracked path reported | `excludeFromGit(localProject)` inside `install(...)`, and `installResult (trackedPaths)` for the `Summary` |
|
||||||
|
|
||||||
### Responsibility Check
|
### Responsibility Check
|
||||||
|
|
||||||
@@ -221,5 +223,5 @@ destroy SR
|
|||||||
[SD-002]: ../uc-002/sd.md
|
[SD-002]: ../uc-002/sd.md
|
||||||
[DCD-002]: ../dcd.md
|
[DCD-002]: ../dcd.md
|
||||||
[UC-002]: ../uc-002/uc.md
|
[UC-002]: ../uc-002/uc.md
|
||||||
[0b0a3b4]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/0b0a3b419a1157b23bddd2f8957a08adaf6974a6
|
|
||||||
[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03
|
[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03
|
||||||
|
[08cb484]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/commit/08cb484498bab3d9480decda9df89e9564438185
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
## Version History
|
## Version History
|
||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | License rule: the AGPL-3.0 default needs GitHub and a public project (step 6, rule 6); step 9 and extension 9e fetch the framework's own submodules | [1cd27f7] |
|
| 2026-10-08 | Deprecated | Jens Tirsvad Nielsen | S02 | Postcondition, step 8 and its rule: origin is the only remote; no github remote (MIL-008) | [039a28c] |
|
||||||
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | Postcondition, step 8 and its rule: origin is the only remote; no github remote (MIL-008) | [039a28c] |
|
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | Postcondition, step 9, extension 9f and a rule: `.claude`, `.agents` and `AGENTS.md` are excluded from git (MIL-009) | [08cb484] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -34,6 +34,7 @@
|
|||||||
- A repository exists on Gitea under the chosen owner. It is empty, or it holds the license file that applies: the license set in `config.env`, or AGPL-3.0 when the Maintainer chose GitHub, the project is public and no license is set.
|
- A repository exists on Gitea under the chosen owner. It is empty, or it holds the license file that applies: the license set in `config.env`, or AGPL-3.0 when the Maintainer chose GitHub, the project is public and no license is set.
|
||||||
- When the Maintainer chose to create a GitHub repository, an empty repository exists on GitHub under the chosen owner, the Gitea repository is a push mirror to it, and the license file, if any, reaches GitHub through the mirror.
|
- When the Maintainer chose to create a GitHub repository, an empty repository exists on GitHub under the chosen owner, the Gitea repository is a push mirror to it, and the license file, if any, reaches GitHub through the mirror.
|
||||||
- A local project directory exists with one credential-free remote, `origin` (Gitea), the `framework` submodule, installed skills and hooks, and the copied templates.
|
- A local project directory exists with one credential-free remote, `origin` (Gitea), the `framework` submodule, installed skills and hooks, and the copied templates.
|
||||||
|
- Git ignores `.claude`, `.agents` and `AGENTS.md` in the local project, through the project's own `.git/info/exclude`; no tracked file is changed.
|
||||||
- When the Maintainer agreed, the local project has a `.env` that holds only the credentials the project needs, is readable by its owner only and is ignored by git.
|
- When the Maintainer agreed, the local project has a `.env` that holds only the credentials the project needs, is readable by its owner only and is ignored by git.
|
||||||
- The Maintainer has a summary of what was created.
|
- The Maintainer has a summary of what was created.
|
||||||
|
|
||||||
@@ -47,7 +48,7 @@
|
|||||||
6. The system creates the Gitea repository. If a license applies, the repository is created with its license file and so is not empty; otherwise it is empty. The license that applies is the one set in `config.env` (`PROJECT_LICENSE`; `none` means no license); when none is set it is AGPL-3.0 if the Maintainer chose GitHub and the project is public, and none otherwise. The license is never asked.
|
6. The system creates the Gitea repository. If a license applies, the repository is created with its license file and so is not empty; otherwise it is empty. The license that applies is the one set in `config.env` (`PROJECT_LICENSE`; `none` means no license); when none is set it is AGPL-3.0 if the Maintainer chose GitHub and the project is public, and none otherwise. The license is never asked.
|
||||||
7. Optional: if GitHub was chosen, the system configures the Gitea repository as a push mirror to GitHub and verifies it. A license file in the Gitea repository is pushed to GitHub by the mirror.
|
7. Optional: if GitHub was chosen, the system configures the Gitea repository as a push mirror to GitHub and verifies it. A license file in the Gitea repository is pushed to GitHub by the mirror.
|
||||||
8. The system creates the local project with the `origin` remote. It adds no `github` remote: a push to `origin` reaches GitHub through the mirror of step 7.
|
8. The system creates the local project with the `origin` remote. It adds no `github` remote: a push to `origin` reaches GitHub through the mirror of step 7.
|
||||||
9. The system adds the framework submodule and fetches its own submodules (the `qc` checklists), installs its skills and hooks (and the plan gate if chosen) and copies the templates. If the Maintainer agrees, it also creates the project's own `.env` with the credentials the project needs.
|
9. The system adds the framework submodule and fetches its own submodules (the `qc` checklists), installs its skills and hooks (and the plan gate if chosen) and copies the templates. It then excludes `.claude`, `.agents` and `AGENTS.md` from git. If the Maintainer agrees, it also creates the project's own `.env` with the credentials the project needs.
|
||||||
10. The system reports a summary of what was created.
|
10. The system reports a summary of what was created.
|
||||||
|
|
||||||
### Extensions (Alternative / Exception Flows)
|
### Extensions (Alternative / Exception Flows)
|
||||||
@@ -78,6 +79,8 @@
|
|||||||
1. The system asks before replacing it; on no, it keeps it and reports it.
|
1. The system asks before replacing it; on no, it keeps it and reports it.
|
||||||
- 9e. The framework's own submodules cannot be fetched:
|
- 9e. The framework's own submodules cannot be fetched:
|
||||||
1. The system stops the step, reports what exists and names the command to run by hand, `git submodule update --init --recursive`, without showing a credential.
|
1. The system stops the step, reports what exists and names the command to run by hand, `git submodule update --init --recursive`, without showing a credential.
|
||||||
|
- 9f. Git already tracks one of `.claude`, `.agents` and `AGENTS.md`:
|
||||||
|
1. The system leaves it tracked, because an exclusion does not apply to a tracked file, and names the path in the summary as not ignored.
|
||||||
|
|
||||||
### Special Requirements / Business Rules
|
### Special Requirements / Business Rules
|
||||||
|
|
||||||
@@ -93,6 +96,7 @@
|
|||||||
| 7 | The mirror direction is Gitea to GitHub; the GitHub repository stays empty and receives its content from the mirror |
|
| 7 | The mirror direction is Gitea to GitHub; the GitHub repository stays empty and receives its content from the mirror |
|
||||||
| 8 | `origin` is the only remote, with or without GitHub, and a remote already in the directory, such as a `github` remote made by an earlier version, is never removed or replaced. `origin` uses HTTPS derived from `GITEA_URL`, or SSH when the SSH test in step 4 passed; when the Gitea repository is not empty (GitHub chosen) the local project is created by fetching it, not by an unrelated `git init` history |
|
| 8 | `origin` is the only remote, with or without GitHub, and a remote already in the directory, such as a `github` remote made by an earlier version, is never removed or replaced. `origin` uses HTTPS derived from `GITEA_URL`, or SSH when the SSH test in step 4 passed; when the Gitea repository is not empty (GitHub chosen) the local project is created by fetching it, not by an unrelated `git init` history |
|
||||||
| 8, 9 | Nothing is overwritten or deleted without consent, and no commit is made |
|
| 8, 9 | Nothing is overwritten or deleted without consent, and no commit is made |
|
||||||
|
| 9 | `.claude`, `.agents` and `AGENTS.md` are excluded from git only when the framework steps ran, whether or not the files were newly made, through the project's `.git/info/exclude` (never `.gitignore`, so no tracked file changes and nothing is shared with a clone), once, anchored to the project root, and the whole folders `.claude` and `.agents` are excluded, not only their `skills` folders. `framework`, `.gitmodules` and `docs/artifact-registry.md` are not excluded. A path git already tracks is never untracked or changed |
|
||||||
|
|
||||||
### Open Issues
|
### Open Issues
|
||||||
|
|
||||||
@@ -104,5 +108,5 @@
|
|||||||
[US-001]: ../user-stories.md
|
[US-001]: ../user-stories.md
|
||||||
[SA-001]: ../stakeholder-analysis.md
|
[SA-001]: ../stakeholder-analysis.md
|
||||||
[DM-001]: ./dm.md
|
[DM-001]: ./dm.md
|
||||||
[1cd27f7]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/1cd27f77ed844773a969210a11de0d8bb98ac98f
|
|
||||||
[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03
|
[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03
|
||||||
|
[08cb484]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/commit/08cb484498bab3d9480decda9df89e9564438185
|
||||||
|
|||||||
@@ -4,13 +4,13 @@
|
|||||||
| Key | Value |
|
| Key | Value |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| ID | US-001 |
|
| ID | US-001 |
|
||||||
| CrossReference | [BC-001], [UCD-001], [UC-002], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007], [MIL-008] |
|
| CrossReference | [BC-001], [UCD-001], [UC-002], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007], [MIL-008], [MIL-009] |
|
||||||
|
|
||||||
## Version History
|
## Version History
|
||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | US-002: only config.env is required; a .env found nowhere means the token is asked | [24f1507] |
|
| 2026-10-08 | Deprecated | Jens Tirsvad Nielsen | S02 | US-001.03: one remote, origin; no github remote (MIL-008) | [039a28c] |
|
||||||
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | US-001.03: one remote, origin; no github remote (MIL-008) | [039a28c] |
|
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | US-001.03: `.claude`, `.agents` and `AGENTS.md` are excluded from git; MIL-009 added to CrossReference | [08cb484] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -58,11 +58,12 @@ The epic is split into seven stories, one per milestone (US-001.01 to US-001.07)
|
|||||||
|
|
||||||
- Given the repositories exist, when the script finishes, then the project directory has one remote, `origin` (Gitea), with or without GitHub, containing no credential; there is no `github` remote, because a push to `origin` reaches GitHub through the mirror.
|
- Given the repositories exist, when the script finishes, then the project directory has one remote, `origin` (Gitea), with or without GitHub, containing no credential; there is no `github` remote, because a push to `origin` reaches GitHub through the mirror.
|
||||||
- Given the project directory, when the script finishes, then the framework, its skills and git hooks (and the plan gate if chosen) and the copied templates are in place.
|
- Given the project directory, when the script finishes, then the framework, its skills and git hooks (and the plan gate if chosen) and the copied templates are in place.
|
||||||
|
- Given the framework steps ran, when the script finishes, then git ignores `.claude`, `.agents` and `AGENTS.md` in the project through `.git/info/exclude`: no `.gitignore` or tracked file is changed, nothing is committed, and a path git already tracks stays tracked and is named in the summary.
|
||||||
- Given a directory or file already exists, when the script would replace it, then it asks first.
|
- Given a directory or file already exists, when the script would replace it, then it asks first.
|
||||||
|
|
||||||
| Traces to | Size | INVEST exceptions |
|
| Traces to | Size | INVEST exceptions |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| [UC-001] steps 8 to 10, [MIL-003] | fits one phase | Independent: needs the repositories of US-001.02 |
|
| [UC-001] steps 8 to 10, [MIL-003], [MIL-009] | fits one phase | Independent: needs the repositories of US-001.02 |
|
||||||
|
|
||||||
### US-001.04 — Create a new project: preset the details
|
### US-001.04 — Create a new project: preset the details
|
||||||
|
|
||||||
@@ -166,6 +167,7 @@ Valuable, Negotiable, Estimable, Small and Testable hold for each story. Indepen
|
|||||||
[MIL-006]: ./milestones/mil-006-project-license.md
|
[MIL-006]: ./milestones/mil-006-project-license.md
|
||||||
[MIL-007]: ./milestones/mil-007-framework-checklists.md
|
[MIL-007]: ./milestones/mil-007-framework-checklists.md
|
||||||
[MIL-008]: ./milestones/mil-008-gitea-only-remote.md
|
[MIL-008]: ./milestones/mil-008-gitea-only-remote.md
|
||||||
|
[MIL-009]: ./milestones/mil-009-exclude-framework-files.md
|
||||||
[PP-001]: ./project-plan.md
|
[PP-001]: ./project-plan.md
|
||||||
[24f1507]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/24f15070fc73fb06e61865141fe0b825ea9e821e
|
|
||||||
[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03
|
[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03
|
||||||
|
[08cb484]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/commit/08cb484498bab3d9480decda9df89e9564438185
|
||||||
|
|||||||
@@ -0,0 +1,236 @@
|
|||||||
|
# How to create the access tokens RepoFoundry needs
|
||||||
|
|
||||||
|
RepoFoundry talks to two hosts and needs one token for each:
|
||||||
|
|
||||||
|
| Token | Key | Needed | Type |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| Gitea access token | `GITEA_TOKEN` | always | an access token with scopes |
|
||||||
|
| GitHub personal access token | `GITHUB_PAT` | only when you choose GitHub | a **classic** personal access token (PAT) |
|
||||||
|
|
||||||
|
This guide shows both, step by step. The red numbers in each picture match the
|
||||||
|
numbered steps next to it.
|
||||||
|
|
||||||
|
> **About the pictures.** They are drawings of the pages, not screenshots, so
|
||||||
|
> that they show no account data. Names, colors and the position of a control
|
||||||
|
> can differ a little in your version of Gitea or GitHub. The words in bold in
|
||||||
|
> the steps are the labels to look for. A new token is shown as dots in the
|
||||||
|
> pictures; on your screen you see its real value.
|
||||||
|
|
||||||
|
The full list of what each token may do is in
|
||||||
|
[Token permissions](../README.md#token-permissions) in the README. This guide
|
||||||
|
is the click-by-click version of it.
|
||||||
|
|
||||||
|
Contents:
|
||||||
|
|
||||||
|
1. [Create a Gitea access token](#1-create-a-gitea-access-token)
|
||||||
|
2. [Create a GitHub personal access token (classic)](#2-create-a-github-personal-access-token-classic)
|
||||||
|
3. [Give the tokens to RepoFoundry](#3-give-the-tokens-to-repofoundry)
|
||||||
|
4. [Keep the tokens safe](#4-keep-the-tokens-safe)
|
||||||
|
5. [If something goes wrong](#5-if-something-goes-wrong)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Create a Gitea access token
|
||||||
|
|
||||||
|
The examples use `https://git.tirsystem.com`. If your Gitea runs elsewhere, use
|
||||||
|
the address you set as `GITEA_URL` in `config.env`.
|
||||||
|
|
||||||
|
### Step 1. Open your settings
|
||||||
|
|
||||||
|
Sign in to Gitea. Click your **avatar** in the top-right corner (1), then
|
||||||
|
choose **Settings** (2).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Step 2. Open "Applications"
|
||||||
|
|
||||||
|
In the menu on the left, click **Applications** (1).
|
||||||
|
|
||||||
|
You can also go straight there: `<your Gitea address>/user/settings/applications`.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Step 3. Fill in the token form
|
||||||
|
|
||||||
|
Scroll to **Generate New Token** and fill it in:
|
||||||
|
|
||||||
|
1. **Token Name:** a name you will recognise later, for example `RepoFoundry`.
|
||||||
|
2. **Repository and Organization Access:** choose **All (public, private, and
|
||||||
|
limited)**. A token that is limited to **Public only** cannot see private
|
||||||
|
repositories or organizations, so creating a private project would fail.
|
||||||
|
3. **Select permissions:** set these three to **Read and Write** and leave
|
||||||
|
every other line at **No Access**:
|
||||||
|
|
||||||
|
| Permission | Level | Why RepoFoundry needs it |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `organization` | Read and Write | look up the owner and your rights in it, create repositories in an organization |
|
||||||
|
| `repository` | Read and Write | create the repository and manage its push mirror |
|
||||||
|
| `user` | Read and Write | read which account the token belongs to, and create a repository under **your own** account |
|
||||||
|
|
||||||
|
4. Click **Generate Token**.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
> **Only creating projects in organizations?** Then `user` can stay at **Read**.
|
||||||
|
> `Read and Write` on `user` is needed only to create a repository under your
|
||||||
|
> own account; without it Gitea answers `required=[write:user]`.
|
||||||
|
|
||||||
|
### Step 4. Copy the token now
|
||||||
|
|
||||||
|
Gitea shows the new token **once**, in a green message at the top of the page
|
||||||
|
(1). Copy it (use the copy button if your version has one, or select the text
|
||||||
|
and press Ctrl+C, Cmd+C on a Mac) and keep it for
|
||||||
|
[step 3 of this guide](#3-give-the-tokens-to-repofoundry). The new token is now
|
||||||
|
in the list below it (2), with its permissions, but the list never shows its
|
||||||
|
value again.
|
||||||
|
|
||||||
|
If you lose the value, delete that token and generate a new one.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Create a GitHub personal access token (classic)
|
||||||
|
|
||||||
|
Skip this part when you will not create a GitHub repository (`USE_GITHUB=no` or
|
||||||
|
answering no when asked). `GITHUB_PAT` is then not needed.
|
||||||
|
|
||||||
|
Use a **classic** token. RepoFoundry has not been tested with fine-grained
|
||||||
|
tokens, because GitHub documents no fine-grained permission for creating a
|
||||||
|
repository.
|
||||||
|
|
||||||
|
### Step 1. Open your settings
|
||||||
|
|
||||||
|
Sign in to GitHub. Click your **profile picture** in the top-right corner (1),
|
||||||
|
then **Settings** (2).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Step 2. Open "Developer settings"
|
||||||
|
|
||||||
|
In the left sidebar, scroll to the bottom and click **Developer settings** (1).
|
||||||
|
It is the last entry.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Step 3. Choose "Tokens (classic)"
|
||||||
|
|
||||||
|
1. In the left sidebar, open **Personal access tokens** and click **Tokens
|
||||||
|
(classic)** (1).
|
||||||
|
2. Click **Generate new token** (2).
|
||||||
|
3. In the menu that opens, choose **Generate new token (classic)** (3). Not
|
||||||
|
the first entry, which is the fine-grained kind.
|
||||||
|
|
||||||
|
GitHub may ask you to confirm your password or a two-factor code. Do that
|
||||||
|
yourself; nobody else should type it.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
> Direct address: `https://github.com/settings/tokens/new`
|
||||||
|
|
||||||
|
### Step 4. Fill in the form
|
||||||
|
|
||||||
|
1. **Note:** a name you will recognise later, for example `RepoFoundry`.
|
||||||
|
2. **Expiration:** pick a date. A shorter life limits the damage if the token
|
||||||
|
leaks; you then create a new token when it ends.
|
||||||
|
3. **Select scopes:** tick the scopes below and nothing else.
|
||||||
|
|
||||||
|
| Scope | Tick it when | Why |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `repo` | always (private or public projects) | creates the repository, and is the password Gitea uses to push the mirror |
|
||||||
|
| `public_repo` instead of `repo` | **only** public projects | enough to create and push a public repository; ticking `repo` already includes it |
|
||||||
|
| `read:org` | only if the script says you do not belong to your organization | lets the script check your membership of an organization owner |
|
||||||
|
|
||||||
|
Ticking `repo` also ticks its five sub-scopes (`repo:status`,
|
||||||
|
`repo_deployment`, `public_repo`, `repo:invite`, `security_events`); that is
|
||||||
|
expected. Leave `workflow`, `write:packages` and the rest unticked.
|
||||||
|
|
||||||
|
4. Scroll down and click **Generate token** (4).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
> **`read:org` and `admin:org`.** The README records that the check worked with
|
||||||
|
> a token that had `repo` and `admin:org`, and that `read:org` alone is
|
||||||
|
> untested. Try `read:org` first. `admin:org` gives far more power than
|
||||||
|
> RepoFoundry needs, so use it only if `read:org` is not enough.
|
||||||
|
|
||||||
|
### Step 5. Copy the token now
|
||||||
|
|
||||||
|
GitHub shows the token **once**, in a green box at the top (1). Click the copy
|
||||||
|
icon next to it. It starts with `ghp_`. Keep it for
|
||||||
|
[step 3 of this guide](#3-give-the-tokens-to-repofoundry).
|
||||||
|
|
||||||
|
If the owner of the new repository is an organization that uses SAML single
|
||||||
|
sign-on, the token must also be authorised for that organization: in the token
|
||||||
|
list click **Configure SSO** (2) next to the token and then **Authorize**
|
||||||
|
for the organization.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Give the tokens to RepoFoundry
|
||||||
|
|
||||||
|
Choose one way. Both keep the token out of `config.env` (a token there is
|
||||||
|
rejected).
|
||||||
|
|
||||||
|
**Option A: type it when asked (nothing is stored).** Do nothing in advance.
|
||||||
|
RepoFoundry asks for `Gitea access token` at the start, and for
|
||||||
|
`GitHub personal access token` and `GitHub account name` once you choose
|
||||||
|
GitHub. What you type is not shown on the screen. Paste only the token, with no
|
||||||
|
spaces, no line break and no quote marks.
|
||||||
|
|
||||||
|
**Option B: keep them in `.env` (convenient, plain text on disk).** In the
|
||||||
|
RepoFoundry folder:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
chmod 600 .env # Linux and macOS: only you can read it
|
||||||
|
```
|
||||||
|
|
||||||
|
Open `.env` and fill in the values; replace the text in angle brackets and
|
||||||
|
remove the brackets:
|
||||||
|
|
||||||
|
```text
|
||||||
|
GITEA_TOKEN=<the Gitea token>
|
||||||
|
GITHUB_PAT=<the GitHub token>
|
||||||
|
GITHUB_USER=<your GitHub account name>
|
||||||
|
```
|
||||||
|
|
||||||
|
`GITHUB_PAT` and `GITHUB_USER` are needed only when you create a GitHub
|
||||||
|
repository. Git ignores `.env`. Never commit it, send it, or paste it into a
|
||||||
|
chat or an issue.
|
||||||
|
|
||||||
|
Then check the setup with a dry run, which only reads from the hosts and
|
||||||
|
creates nothing:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
src/create-project.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Keep the tokens safe
|
||||||
|
|
||||||
|
- A token is a password. Anyone who has it can do what it allows.
|
||||||
|
- Give each token only the access in this guide, and an expiration date.
|
||||||
|
- Do not paste a token in a command line, a URL, a commit, an issue or a chat.
|
||||||
|
- If a token may have leaked, delete it at once and make a new one:
|
||||||
|
- Gitea: **Settings**, **Applications**, then **Delete** on that token.
|
||||||
|
- GitHub: **Settings**, **Developer settings**, **Personal access tokens**,
|
||||||
|
**Tokens (classic)**, then **Delete** on that token.
|
||||||
|
- When a token expires, create a new one the same way and replace it in `.env`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. If something goes wrong
|
||||||
|
|
||||||
|
| What you see | Likely cause | What to do |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `authentication failed: the token is missing, expired or invalid` | the token was mistyped, has expired or was deleted | create a new token and use it |
|
||||||
|
| `the token is valid but not allowed to do this (check its scopes)` | a permission is missing | Gitea: set `organization`, `repository` and `user` to **Read and Write**. GitHub: tick `repo` |
|
||||||
|
| Gitea answers `required=[write:user]` | the project is being created under your own account | set `user` to **Read and Write** |
|
||||||
|
| `Gitea owner '...' is neither your account (...) nor an organization the token can see` | the token is limited to **Public only**, or the owner name is wrong | make the token **All (public, private, and limited)**, or fix the owner |
|
||||||
|
| `GitHub owner '...' is neither your account (...) nor an organization you belong to (or the token lacks the read:org scope)` | the token cannot see the organization | tick `read:org`, and authorise the token for the organization if it uses single sign-on |
|
||||||
|
| the pasted token is refused again and again | spaces, a line break or quote marks came with the paste | copy it again and paste only the token |
|
||||||
|
| `GITHUB_USER is '...' but the token belongs to '...'` | a warning: the name in `.env` is not the account of the token | no action needed; RepoFoundry uses the account the token belongs to |
|
||||||
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 7.5 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
@@ -19,6 +19,7 @@ create_all() {
|
|||||||
add_framework
|
add_framework
|
||||||
install_framework
|
install_framework
|
||||||
copy_templates
|
copy_templates
|
||||||
|
exclude_framework_files
|
||||||
create_env_file
|
create_env_file
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,8 +30,12 @@ readonly HINT_LICENSE="use a Gitea license key (letters, digits, '.', '+' or '-'
|
|||||||
readonly HINT_DIRECTORY="must not be empty, start with '-' or contain control characters"
|
readonly HINT_DIRECTORY="must not be empty, start with '-' or contain control characters"
|
||||||
readonly HINT_TOKEN="8 to 255 letters, digits or _ . ~ + / = -"
|
readonly HINT_TOKEN="8 to 255 letters, digits or _ . ~ + / = -"
|
||||||
readonly ENV_FILE_NAME=".env"
|
readonly ENV_FILE_NAME=".env"
|
||||||
|
# What the framework installs into the new project that git must not list: the
|
||||||
|
# folders of the skills and the copy of AGENTS.md, anchored to the project
|
||||||
|
# root. They go into .git/info/exclude of the new project.
|
||||||
|
readonly FRAMEWORK_EXCLUDES=(/.claude /.agents /AGENTS.md)
|
||||||
readonly PLAN_STEPS=("GitHub repository" "Gitea repository" "Push mirror"
|
readonly PLAN_STEPS=("GitHub repository" "Gitea repository" "Push mirror"
|
||||||
"Local project" "Framework" "Skills and hooks" "Templates" "Project .env")
|
"Local project" "Framework" "Skills and hooks" "Templates" "Git excludes" "Project .env")
|
||||||
# shellcheck disable=SC2034 # read through namerefs (parse_env_file)
|
# shellcheck disable=SC2034 # read through namerefs (parse_env_file)
|
||||||
readonly CONFIG_KEYS=(GITHUB_API_URL GITHUB_WEB_URL GITEA_URL GITEA_API_URL
|
readonly CONFIG_KEYS=(GITHUB_API_URL GITHUB_WEB_URL GITEA_URL GITEA_API_URL
|
||||||
GITEA_SSH_PORT MIRROR_INTERVAL FRAMEWORK_REPO
|
GITEA_SSH_PORT MIRROR_INTERVAL FRAMEWORK_REPO
|
||||||
|
|||||||
@@ -26,19 +26,8 @@ env_file_key_list() {
|
|||||||
# file: the entry goes into .git/info/exclude, which is never committed. It
|
# file: the entry goes into .git/info/exclude, which is never committed. It
|
||||||
# does nothing when .env is already ignored.
|
# does nothing when .env is already ignored.
|
||||||
exclude_env_file() {
|
exclude_env_file() {
|
||||||
local dir="$1" gitdir exclude
|
local dir="$1"
|
||||||
if git_project "$dir" check-ignore -q -- "$ENV_FILE_NAME"; then
|
exclude_from_git "$dir" "RepoFoundry: the credentials file of this project" "$ENV_FILE_NAME" ||
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
gitdir="$(git_project "$dir" rev-parse --absolute-git-dir)"
|
|
||||||
exclude="$gitdir/info/exclude"
|
|
||||||
mkdir -p -- "$gitdir/info"
|
|
||||||
# Start on a fresh line when the file does not end with one.
|
|
||||||
if [[ -s $exclude && -n "$(tail -c 1 -- "$exclude")" ]]; then
|
|
||||||
printf '\n' >>"$exclude"
|
|
||||||
fi
|
|
||||||
printf '%s\n' "# RepoFoundry: the credentials file of this project" "$ENV_FILE_NAME" >>"$exclude"
|
|
||||||
git_project "$dir" check-ignore -q -- "$ENV_FILE_NAME" ||
|
|
||||||
die "could not make git ignore $ENV_FILE_NAME in $dir; nothing was written to it"
|
die "could not make git ignore $ENV_FILE_NAME in $dir; nothing was written to it"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#
|
#
|
||||||
# Part of create-project.sh: sourced by it, never run on its own.
|
# Part of create-project.sh: sourced by it, never run on its own.
|
||||||
#
|
#
|
||||||
# Provides: is_framework_skipped, init_framework_submodules, add_framework, run_framework_script, install_skills, install_hooks, install_framework, copy_template, copy_templates
|
# Provides: is_framework_skipped, init_framework_submodules, add_framework, run_framework_script, install_skills, install_hooks, install_framework, copy_template, copy_templates, exclude_framework_files
|
||||||
|
|
||||||
# is_framework_skipped: succeed when the framework steps are left out because
|
# is_framework_skipped: succeed when the framework steps are left out because
|
||||||
# SSH to Gitea is not available (the Maintainer agreed to that).
|
# SSH to Gitea is not available (the Maintainer agreed to that).
|
||||||
@@ -165,3 +165,39 @@ copy_templates() {
|
|||||||
notes="$notes; ${STATE[template_note]}"
|
notes="$notes; ${STATE[template_note]}"
|
||||||
finish_step "$label" "created" "($notes)"
|
finish_step "$label" "created" "($notes)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# exclude_framework_files: make git ignore .claude, .agents and AGENTS.md in
|
||||||
|
# the new project, through its .git/info/exclude (never .gitignore, so no
|
||||||
|
# tracked file changes and nothing is committed). Only when the framework
|
||||||
|
# steps ran. A path git already tracks stays tracked: an exclusion does not
|
||||||
|
# apply to it, so the step names it.
|
||||||
|
exclude_framework_files() {
|
||||||
|
local label="Git excludes" dir="${PROJECT[directory]}" entry path tracked=() note written
|
||||||
|
if is_framework_skipped; then
|
||||||
|
finish_step "$label" "skipped" "(no SSH access to Gitea)"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
begin_step "$label"
|
||||||
|
exclude_from_git "$dir" "RepoFoundry: the files installed from the framework" "${FRAMEWORK_EXCLUDES[@]}" ||
|
||||||
|
die "could not make git ignore the framework files in $dir; check $dir/.git/info/exclude"
|
||||||
|
written="$REPLY"
|
||||||
|
for entry in "${FRAMEWORK_EXCLUDES[@]}"; do
|
||||||
|
path="${entry#/}"
|
||||||
|
if [[ -n "$(git_project "$dir" ls-files -- "$path")" ]]; then
|
||||||
|
tracked+=("$path")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if ((written == 0)); then
|
||||||
|
note="${FRAMEWORK_EXCLUDES[*]} already excluded"
|
||||||
|
else
|
||||||
|
note="${FRAMEWORK_EXCLUDES[*]} added to .git/info/exclude"
|
||||||
|
fi
|
||||||
|
if ((${#tracked[@]})); then
|
||||||
|
note="$note; git tracks ${tracked[*]}, so it is not ignored"
|
||||||
|
fi
|
||||||
|
if ((written == 0)); then
|
||||||
|
finish_step "$label" "reused" "($note)"
|
||||||
|
else
|
||||||
|
finish_step "$label" "created" "($note)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#
|
#
|
||||||
# Part of create-project.sh: sourced by it, never run on its own.
|
# Part of create-project.sh: sourced by it, never run on its own.
|
||||||
#
|
#
|
||||||
# Provides: git_project, fetch_origin
|
# Provides: git_project, exclude_from_git, fetch_origin
|
||||||
|
|
||||||
# git_project DIR ARGS...: run git in DIR. Prompts are switched off and stdin
|
# git_project DIR ARGS...: run git in DIR. Prompts are switched off and stdin
|
||||||
# is closed (git must not eat the answers meant for later prompts), so a
|
# is closed (git must not eat the answers meant for later prompts), so a
|
||||||
@@ -16,6 +16,40 @@ git_project() {
|
|||||||
git -C "$dir" "$@" </dev/null
|
git -C "$dir" "$@" </dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# exclude_from_git DIR COMMENT ENTRY...: make git ignore each ENTRY in DIR
|
||||||
|
# without touching a tracked file: the entries go into .git/info/exclude,
|
||||||
|
# which is never committed. An entry that already takes effect (checked by its
|
||||||
|
# pattern, so a tracked path counts) is left out, and with none left nothing
|
||||||
|
# is written. The comment line goes above the entries that are written. The
|
||||||
|
# number of entries written is left in REPLY; the return status is 1 when an
|
||||||
|
# entry still does not take effect afterwards.
|
||||||
|
exclude_from_git() {
|
||||||
|
local dir="$1" comment="$2" gitdir exclude entry path missing=()
|
||||||
|
shift 2
|
||||||
|
for entry in "$@"; do
|
||||||
|
path="${entry#/}"
|
||||||
|
if ! git_project "$dir" check-ignore --no-index -q -- "${path%/}"; then
|
||||||
|
missing+=("$entry")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
REPLY="${#missing[@]}"
|
||||||
|
if ((REPLY == 0)); then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
gitdir="$(git_project "$dir" rev-parse --absolute-git-dir)"
|
||||||
|
exclude="$gitdir/info/exclude"
|
||||||
|
mkdir -p -- "$gitdir/info"
|
||||||
|
# Start on a fresh line when the file does not end with one.
|
||||||
|
if [[ -s $exclude && -n "$(tail -c 1 -- "$exclude")" ]]; then
|
||||||
|
printf '\n' >>"$exclude"
|
||||||
|
fi
|
||||||
|
printf '%s\n' "# $comment" "${missing[@]}" >>"$exclude"
|
||||||
|
for entry in "${missing[@]}"; do
|
||||||
|
path="${entry#/}"
|
||||||
|
git_project "$dir" check-ignore --no-index -q -- "${path%/}" || return 1
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
# fetch_origin DIR: fetch the Gitea repository into the project. Over SSH the
|
# fetch_origin DIR: fetch the Gitea repository into the project. Over SSH the
|
||||||
# user's key is used. Over HTTPS the token reaches git through a private
|
# user's key is used. Over HTTPS the token reaches git through a private
|
||||||
# GIT_ASKPASS helper and the environment of this one command: it is never part
|
# GIT_ASKPASS helper and the environment of this one command: it is never part
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ print_plan() {
|
|||||||
say "$(printf ' %-18s: %s' "Framework" "add $(framework_url) as a submodule")"
|
say "$(printf ' %-18s: %s' "Framework" "add $(framework_url) as a submodule")"
|
||||||
say "$(printf ' %-18s: %s' "Skills and hooks" "install once; plan gate $(yes_no "${PROJECT[is_plan_gate_enabled]}")")"
|
say "$(printf ' %-18s: %s' "Skills and hooks" "install once; plan gate $(yes_no "${PROJECT[is_plan_gate_enabled]}")")"
|
||||||
say "$(printf ' %-18s: %s' "Templates" "AGENTS.md and docs/artifact-registry.md (you are asked before a file is replaced)")"
|
say "$(printf ' %-18s: %s' "Templates" "AGENTS.md and docs/artifact-registry.md (you are asked before a file is replaced)")"
|
||||||
|
say "$(printf ' %-18s: %s' "Git excludes" "${FRAMEWORK_EXCLUDES[*]} go into .git/info/exclude (no tracked file changes)")"
|
||||||
else
|
else
|
||||||
say "$(printf ' %-18s: %s' "Framework" "NOT possible without SSH to Gitea; you will be asked whether to go on without it")"
|
say "$(printf ' %-18s: %s' "Framework" "NOT possible without SSH to Gitea; you will be asked whether to go on without it")"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -291,6 +291,7 @@ echo done'
|
|||||||
local exclude
|
local exclude
|
||||||
exclude="$(cat "$WORK/p/.git/info/exclude")"
|
exclude="$(cat "$WORK/p/.git/info/exclude")"
|
||||||
assert_contains "old entry kept" "$exclude" "build/"
|
assert_contains "old entry kept" "$exclude" "build/"
|
||||||
|
assert_contains "comment line" "$exclude" "# RepoFoundry: the credentials file of this project"
|
||||||
assert_eq "entry added once" "1" "$(grep -c '^\.env$' "$WORK/p/.git/info/exclude")"
|
assert_eq "entry added once" "1" "$(grep -c '^\.env$' "$WORK/p/.git/info/exclude")"
|
||||||
assert_eq "old entry still on its own line" "1" "$(grep -c '^build/$' "$WORK/p/.git/info/exclude")"
|
assert_eq "old entry still on its own line" "1" "$(grep -c '^build/$' "$WORK/p/.git/info/exclude")"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -282,6 +282,105 @@ test_existing_template_targets_are_replaced_only_after_a_yes() {
|
|||||||
assert_contains "reported" "$OUT" "kept existing AGENTS.md; copied docs/artifact-registry.md"
|
assert_contains "reported" "$OUT" "kept existing AGENTS.md; copied docs/artifact-registry.md"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------- git excludes
|
||||||
|
|
||||||
|
# exclude_count FILE LINE: how many lines of FILE are exactly LINE.
|
||||||
|
exclude_count() {
|
||||||
|
grep -cxF -e "$2" "$1" || true
|
||||||
|
}
|
||||||
|
|
||||||
|
test_the_framework_files_are_ignored_by_git_and_nothing_else_changes() {
|
||||||
|
setup_hosts
|
||||||
|
local dir="$WORK/project" exclude path listing
|
||||||
|
exclude="$dir/.git/info/exclude"
|
||||||
|
local_answers "$dir" y n
|
||||||
|
# create now, and create the project's .env as well
|
||||||
|
run_apply "$LOCAL_ANSWERS"$'y\ny\n'
|
||||||
|
assert_status "apply" 0 "$STATUS"
|
||||||
|
assert_contains "reported" "$OUT" "Git excludes : created (/.claude /.agents /AGENTS.md added to .git/info/exclude)"
|
||||||
|
for path in /.claude /.agents /AGENTS.md; do
|
||||||
|
assert_eq "one entry for $path" "1" "$(exclude_count "$exclude" "$path")"
|
||||||
|
done
|
||||||
|
for path in .claude .agents AGENTS.md .claude/skills/coding-conventions/SKILL.md .agents/skills/.framework-skills; do
|
||||||
|
check
|
||||||
|
if ! project_git "$dir" check-ignore -q -- "$path"; then
|
||||||
|
fail "$path is not ignored by git"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
for path in framework .gitmodules docs/artifact-registry.md; do
|
||||||
|
check
|
||||||
|
if project_git "$dir" check-ignore -q --no-index -- "$path"; then
|
||||||
|
fail "$path is ignored by git but is part of the project"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
listing="$(project_git "$dir" status --porcelain)"
|
||||||
|
assert_not_contains ".claude is not listed" "$listing" ".claude"
|
||||||
|
assert_not_contains ".agents is not listed" "$listing" ".agents"
|
||||||
|
assert_not_contains "AGENTS.md is not listed" "$listing" "AGENTS.md"
|
||||||
|
assert_contains "the submodule is listed" "$listing" "framework"
|
||||||
|
assert_contains "the registry is listed" "$listing" "docs/"
|
||||||
|
assert_file_missing "no .gitignore is written" "$dir/.gitignore"
|
||||||
|
assert_eq "nothing was committed" "1" "$(project_git "$dir" rev-list --count HEAD)"
|
||||||
|
assert_eq "the .env keeps its own entry, once" "1" "$(exclude_count "$exclude" ".env")"
|
||||||
|
assert_contains "the .env comment is unchanged" "$(cat "$exclude")" "# RepoFoundry: the credentials file of this project"
|
||||||
|
}
|
||||||
|
|
||||||
|
test_the_git_excludes_are_written_once_and_keep_the_existing_lines() {
|
||||||
|
local dir="$WORK/p" exclude="$WORK/p/.git/info/exclude" path
|
||||||
|
mkdir -p "$dir"
|
||||||
|
project_git "$dir" init -q
|
||||||
|
printf 'build/' >"$exclude" # no trailing newline
|
||||||
|
run_lib "" 'PROJECT[directory]="'"$dir"'"
|
||||||
|
exclude_framework_files
|
||||||
|
echo "${STEP_STATUS["Git excludes"]}"
|
||||||
|
exclude_framework_files
|
||||||
|
echo "${STEP_STATUS["Git excludes"]} ${STEP_DETAIL["Git excludes"]}"'
|
||||||
|
assert_status "run" 0 "$STATUS"
|
||||||
|
assert_eq "created, then reused" $'created\nreused (/.claude /.agents /AGENTS.md already excluded)' "$OUT"
|
||||||
|
assert_eq "the old line is kept on its own line" "1" "$(exclude_count "$exclude" "build/")"
|
||||||
|
for path in /.claude /.agents /AGENTS.md; do
|
||||||
|
assert_eq "entry for $path written once" "1" "$(exclude_count "$exclude" "$path")"
|
||||||
|
done
|
||||||
|
assert_eq "one comment line" "1" "$(exclude_count "$exclude" "# RepoFoundry: the files installed from the framework")"
|
||||||
|
}
|
||||||
|
|
||||||
|
test_nothing_is_written_for_paths_git_already_ignores() {
|
||||||
|
local dir="$WORK/p" exclude="$WORK/p/.git/info/exclude"
|
||||||
|
mkdir -p "$dir"
|
||||||
|
project_git "$dir" init -q
|
||||||
|
printf '.claude\n.agents\nAGENTS.md\n' >"$dir/.gitignore"
|
||||||
|
run_lib "" 'PROJECT[directory]="'"$dir"'"
|
||||||
|
exclude_framework_files
|
||||||
|
echo "${STEP_STATUS["Git excludes"]}"'
|
||||||
|
assert_status "run" 0 "$STATUS"
|
||||||
|
assert_eq "reused" "reused" "$OUT"
|
||||||
|
assert_eq "no entry written" "0" "$(grep -c '^/' "$exclude" || true)"
|
||||||
|
assert_eq "no comment written" "0" "$(exclude_count "$exclude" "# RepoFoundry: the files installed from the framework")"
|
||||||
|
}
|
||||||
|
|
||||||
|
test_a_tracked_framework_file_stays_tracked_and_is_named() {
|
||||||
|
local dir="$WORK/p"
|
||||||
|
mkdir -p "$dir/.agents" "$dir/.claude"
|
||||||
|
project_git "$dir" init -q
|
||||||
|
printf 'mine\n' >"$dir/AGENTS.md"
|
||||||
|
printf 'x\n' >"$dir/.agents/keep"
|
||||||
|
printf 'y\n' >"$dir/.claude/new" # not tracked
|
||||||
|
project_git "$dir" add AGENTS.md .agents/keep
|
||||||
|
project_git "$dir" commit -q -m seed
|
||||||
|
run_lib "" 'PROJECT[directory]="'"$dir"'"
|
||||||
|
exclude_framework_files
|
||||||
|
echo "${STEP_STATUS["Git excludes"]} ${STEP_DETAIL["Git excludes"]}"'
|
||||||
|
assert_status "run" 0 "$STATUS"
|
||||||
|
assert_contains "names the tracked paths" "$OUT" "git tracks .agents AGENTS.md, so it is not ignored"
|
||||||
|
assert_eq "both are still tracked" $'.agents/keep\nAGENTS.md' "$(project_git "$dir" ls-files)"
|
||||||
|
assert_eq "the content is unchanged" "mine" "$(cat "$dir/AGENTS.md")"
|
||||||
|
assert_eq "nothing is staged or modified" "" "$(project_git "$dir" status --porcelain)"
|
||||||
|
check
|
||||||
|
if ! project_git "$dir" check-ignore -q -- .claude; then
|
||||||
|
fail ".claude, which git does not track, is not ignored"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# ----------------------------------------------------------- SSH and errors
|
# ----------------------------------------------------------- SSH and errors
|
||||||
|
|
||||||
test_without_ssh_the_run_stops_unless_the_framework_is_skipped() {
|
test_without_ssh_the_run_stops_unless_the_framework_is_skipped() {
|
||||||
@@ -311,6 +410,9 @@ test_without_ssh_the_framework_steps_are_skipped_after_a_yes() {
|
|||||||
assert_contains "framework skipped" "$OUT" "Framework : skipped (no SSH access to Gitea)"
|
assert_contains "framework skipped" "$OUT" "Framework : skipped (no SSH access to Gitea)"
|
||||||
assert_contains "skills and hooks skipped" "$OUT" "Skills and hooks : skipped (no SSH access to Gitea)"
|
assert_contains "skills and hooks skipped" "$OUT" "Skills and hooks : skipped (no SSH access to Gitea)"
|
||||||
assert_contains "templates skipped" "$OUT" "Templates : skipped (no SSH access to Gitea)"
|
assert_contains "templates skipped" "$OUT" "Templates : skipped (no SSH access to Gitea)"
|
||||||
|
assert_contains "git excludes skipped" "$OUT" "Git excludes : skipped (no SSH access to Gitea)"
|
||||||
|
assert_not_contains "nothing excluded: .claude" "$(cat "$dir/.git/info/exclude")" "/.claude"
|
||||||
|
assert_not_contains "nothing excluded: AGENTS.md" "$(cat "$dir/.git/info/exclude")" "/AGENTS.md"
|
||||||
assert_file_missing "no submodule" "$dir/.gitmodules"
|
assert_file_missing "no submodule" "$dir/.gitmodules"
|
||||||
assert_file_missing "no AGENTS.md" "$dir/AGENTS.md"
|
assert_file_missing "no AGENTS.md" "$dir/AGENTS.md"
|
||||||
}
|
}
|
||||||
@@ -365,6 +467,7 @@ test_the_dry_run_plan_describes_the_local_steps_and_creates_nothing() {
|
|||||||
assert_contains "framework" "$OUT" "Framework : add $SSH_FRAMEWORK_URL as a submodule"
|
assert_contains "framework" "$OUT" "Framework : add $SSH_FRAMEWORK_URL as a submodule"
|
||||||
assert_contains "skills and hooks" "$OUT" "Skills and hooks : install once; plan gate yes"
|
assert_contains "skills and hooks" "$OUT" "Skills and hooks : install once; plan gate yes"
|
||||||
assert_contains "templates" "$OUT" "Templates : AGENTS.md and docs/artifact-registry.md (you are asked before a file is replaced)"
|
assert_contains "templates" "$OUT" "Templates : AGENTS.md and docs/artifact-registry.md (you are asked before a file is replaced)"
|
||||||
|
assert_contains "git excludes" "$OUT" "Git excludes : /.claude /.agents /AGENTS.md go into .git/info/exclude (no tracked file changes)"
|
||||||
assert_file_missing "nothing created" "$dir"
|
assert_file_missing "nothing created" "$dir"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,6 +481,7 @@ test_the_plan_marks_an_existing_directory_and_missing_ssh() {
|
|||||||
run_dry "$LOCAL_ANSWERS"
|
run_dry "$LOCAL_ANSWERS"
|
||||||
assert_contains "existing directory" "$OUT" "use the existing directory $dir, which has files (you will be asked)"
|
assert_contains "existing directory" "$OUT" "use the existing directory $dir, which has files (you will be asked)"
|
||||||
assert_contains "no SSH" "$OUT" "NOT possible without SSH to Gitea; you will be asked whether to go on without it"
|
assert_contains "no SSH" "$OUT" "NOT possible without SSH to Gitea; you will be asked whether to go on without it"
|
||||||
|
assert_not_contains "no git excludes without the framework" "$OUT" "Git excludes"
|
||||||
assert_contains "HTTPS origin" "$OUT" "will use HTTPS (SSH test: failed"
|
assert_contains "HTTPS origin" "$OUT" "will use HTTPS (SSH test: failed"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||