Plan MIL-007 and UC-002; AGPL-3.0 default only for a public GitHub project

- MIL-006: the AGPL-3.0 default needs GitHub and a public project
- MIL-007: fetch the framework's own submodules (qc); start through a command link; README usage
- UC-002 with SSD, DM, OC, SD and DCD; US-001.07 and US-002
- Reconcile the project DM, DCD, dictionary, use case diagram and traceability matrix
- Review records RC-022 to RC-028
This commit is contained in:
2026-10-07 12:30:58 +08:00
parent 5b66eff809
commit 1cd27f77ed
29 changed files with 1143 additions and 85 deletions
+87
View File
@@ -0,0 +1,87 @@
# Design Class Diagram
## Metadata
| Key | Value |
| --- | --- |
| ID | DCD-003 |
| CrossReference | [DM-003], [SD-002], [DICT-001], [UC-002], [DCD-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-07 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version | pending |
---
## Purpose and Scope
Covers [UC-002]. Adds the classes that start the script through a command link. `ProjectCreator`, `Configuration` and `Run` are the classes of [DCD-001] and change only as stated under Method Traceability. The consolidated diagram is [DCD-002].
## Diagram
```plantuml
@startuml
class Launcher {
+resolveCheckout(invocation : Path) : Checkout
+currentFolder() : WorkingFolder
+startFromWorkingFolder(configPath : Path [0..1], envPath : Path [0..1]) : PromptSet
}
class Checkout {
-path : Path
+configFile() : Path
+envFile() : Path
}
class WorkingFolder {
-path : Path
}
class ProjectCreator {
+startProjectCreation(checkout : Checkout, workingFolder : WorkingFolder, configPath : Path [0..1], envPath : Path [0..1]) : PromptSet
}
class Run
Launcher "1" --> "1" ProjectCreator : starts
Launcher ..> Checkout : creates
Launcher ..> WorkingFolder : creates
Run "1" *-- "1" Checkout
Run "1" *-- "1" WorkingFolder
@enduml
```
## Class Table
| Class | Refines (Domain Model concept) | Responsibility | Attributes | Operations |
| --- | --- | --- | --- | --- |
| `Launcher` | Command Link (the object that follows it) | Follows the command link to the checkout, takes the folder the Maintainer stands in, and starts the run. | none | `resolveCheckout`, `currentFolder`, `startFromWorkingFolder` |
| `Checkout` | Checkout | Names the folder that holds the script's own files and the default `config.env` and `.env`. | `path` | `configFile`, `envFile` |
| `WorkingFolder` | Working Folder | Names the base of the default directory of the new project. | `path` | none |
The concept Command Link has no class: it is a link the Maintainer makes with the shell, and the system only follows it.
## Method Traceability
| Method signature | Operation Contract / SD message |
| --- | --- |
| `Launcher.startFromWorkingFolder(configPath, envPath) : PromptSet` | [SD-002] `startFromWorkingFolder`; P1, P6 |
| `Launcher.resolveCheckout(invocation) : Checkout` | [SD-002] `resolveCheckout(invocation)`; P2 |
| `Launcher.currentFolder() : WorkingFolder` | [SD-002] `currentFolder()`; P3 |
| `Checkout.configFile() : Path`, `Checkout.envFile() : Path` | [SD-002] `startProjectCreation`; P5 |
| `ProjectCreator.startProjectCreation(checkout, workingFolder, configPath, envPath) : PromptSet` | [SD-002] `startProjectCreation`; P4, P5, P6. Replaces the signature of [DCD-001] by adding `checkout`, `workingFolder`, `configPath` and `envPath` |
## Pattern Annotations
| Pattern | Classes | Rationale |
| --- | --- | --- |
| Controller | `Launcher` | One class takes the system operation of [UC-002] |
| Information Expert | `Launcher`, `Checkout` | The launcher knows the invocation; the checkout knows where its files are |
## Dependency Check
`Launcher` depends on `ProjectCreator`, `Checkout` and `WorkingFolder`; none of them depends on `Launcher`, so no cycle is added.
---
[DM-003]: ./dm.md
[SD-002]: ./sd.md
[DICT-001]: ../dictionary.md
[UC-002]: ./uc.md
[DCD-001]: ../uc-001/dcd.md
[DCD-002]: ../dcd.md
+84
View File
@@ -0,0 +1,84 @@
# Domain Model
## Metadata
| Key | Value |
| --- | --- |
| ID | DM-003 |
| CrossReference | [UC-002], [UCD-001], [SSD-002], [DICT-001], [DM-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-07 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version | pending |
---
## Purpose and Scope
Covers [UC-002] "Start the script as a global command". The concepts come from the nouns of that use case and use the PO terms of [DICT-001]. The concepts `Maintainer`, `Configuration`, `Project` and `Local Project` are those of [DM-001] and are not redefined here. The project-level model that consolidates all use cases is [DM-002].
## Diagram
Concepts, attributes and associations only — no operations.
```plantuml
@startuml
class Maintainer {
name
}
class "Command Link" as CommandLink {
name
folder
}
class Checkout {
path
}
class "Working Folder" as WorkingFolder {
path
}
class Configuration {
preset project details
}
class "Local Project" as LocalProject {
path
}
Maintainer "1" --> "0..*" CommandLink : makes
CommandLink "0..*" --> "1" Checkout : leads to
Maintainer "1" --> "1" WorkingFolder : starts the script in
Checkout "1" --> "1" Configuration : holds by default
WorkingFolder "1" --> "0..*" LocalProject : is the base of
@enduml
```
## Concept Table
| Concept | Definition | Attributes | Source (use case / glossary) |
| --- | --- | --- | --- |
| 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" |
| Working Folder | The folder in which the Maintainer starts the script and under which the new project is created by default | path | [UC-002] step 2 "working folder" |
## Association Table
| From | Association (reading direction) | To | Multiplicity |
| --- | --- | --- | --- |
| Maintainer | makes | Command Link | 1 to 0..* |
| Command Link | leads to | Checkout | 0..* to 1 |
| Maintainer | starts the script in | Working Folder | 1 to 1 |
| Checkout | holds by default | Configuration | 1 to 1 |
| Working Folder | is the base of | Local Project | 1 to 0..* |
## Generalizations
| General | Specializations | Is-a justification |
| --- | --- | --- |
| None | - | - |
---
[UC-002]: ./uc.md
[UCD-001]: ../use-case-diagram.md
[SSD-002]: ./ssd.md
[DICT-001]: ../dictionary.md
[DM-001]: ../uc-001/dm.md
[DM-002]: ../domain-model.md
+53
View File
@@ -0,0 +1,53 @@
# Operation Contract
## Metadata
| Key | Value |
| --- | --- |
| ID | OC-002 |
| CrossReference | [SSD-002], [DM-003], [DICT-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-07 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version | pending |
---
Concepts below use the IT terms of [DICT-001] for the PO concepts of [DM-003]. `Run` and `PromptSet` are the system concepts of [OC-001]. The operation `provideProjectDetails` is the one of [OC-001]; the only change is the base of its default `directory`, stated in P4.
## Contract: startFromWorkingFolder
| Item | Value |
| --- | --- |
| Operation | `startFromWorkingFolder(configPath: Path [0..1], envPath: Path [0..1]): PromptSet` |
| Traces to | `startFromWorkingFolder` in [SSD-002] |
| Concepts | Run, CommandLink, Checkout, WorkingFolder, Configuration |
**Preconditions**
- A `CommandLink` exists that leads to the script in a `Checkout`, or the Maintainer started the script by its path.
- The Maintainer is in a `WorkingFolder`.
**Postconditions**
- P1. A `Run` instance was created.
- P2. A `Checkout` instance was created and associated with the `Run`, with `path` set to the folder that holds the script's own files, reached through the `CommandLink`, however many links lie between them.
- P3. A `WorkingFolder` instance was created and associated with the `Run`, with `path` set to the folder in which the Maintainer started the script. It was not changed by following the `CommandLink`.
- P4. The default of `directory` in the `PromptSet` is `./<name>` under the `WorkingFolder`, never under the `Checkout`.
- P5. A `Configuration` instance was created and associated with the `Run` from `configPath`, or from `config.env` in the `Checkout` when `configPath` is absent, and from `envPath`, or from `.env` in the `Checkout` when `envPath` is absent; the validation of [OC-001] `startProjectCreation` P2 and P3 applies.
- P6. The `Run` was associated with a `PromptSet` that is returned.
**Exceptions**
| Condition (failing precondition) | Outcome |
| --- | --- |
| The `Checkout`'s own files are not found from the link target | The `Run` ends with an error naming the folder it looked in; nothing was changed |
| `config.env` or `.env` is not found in the `Checkout` and no path was given (P5) | The `Run` ends with an error naming the path it looked in and the options `--config` and `--env`; nothing was changed |
| A value in `config.env` or `.env` is malformed (P5) | As in [OC-001] `startProjectCreation`: the error names the key, never its value; nothing was changed |
---
[SSD-002]: ./ssd.md
[DM-003]: ./dm.md
[DICT-001]: ../dictionary.md
[OC-001]: ../uc-001/oc.md
+84
View File
@@ -0,0 +1,84 @@
# Sequence Diagram
## Metadata
| Key | Value |
| --- | --- |
| ID | SD-002 |
| CrossReference | [OC-002], [DCD-003], [DICT-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-07 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version | pending |
---
Design objects are conceptual; in `create-project.sh` each becomes a small function group. [DCD-003] gives each object its class and turns each message below into a method signature. `ProjectCreator` and `ConfigLoader` are the design objects of [SD-001].
## Sequence: startFromWorkingFolder
**Realizes:** `startFromWorkingFolder` in [OC-002]
### Diagram
```plantuml
@startuml
actor Maintainer
participant ":Launcher" as L
participant ":ProjectCreator" as PC
participant ":Checkout" as CK
participant ":WorkingFolder" as WF
Maintainer -> L : startFromWorkingFolder(configPath, envPath)
activate L
L -> L : resolveCheckout(invocation)
create CK
L -> CK : Checkout(path)
L -> L : currentFolder()
create WF
L -> WF : WorkingFolder(path)
alt the Checkout's own files are not found
L --> Maintainer : error naming the folder looked in
end
L -> PC : startProjectCreation(checkout, workingFolder, configPath, envPath)
activate PC
alt config.env or .env not found, or a value malformed
PC --> L : error naming the path or the key
end
PC --> L : promptSet
deactivate PC
L --> Maintainer : promptSet
deactivate L
@enduml
```
### Pattern Annotations
| Pattern (GRASP / GoF) | Applied to | Rationale |
| --- | --- | --- |
| Information Expert | `Launcher.resolveCheckout` | The launcher knows how the script was invoked, so it is the one that can follow the command link |
| Controller | `Launcher` | One object takes the system operation and hands the work to `ProjectCreator`; `ProjectCreator` stays unaware of links |
| Low Coupling | `ProjectCreator` receives `checkout` and `workingFolder` as values | The use case [UC-001] runs unchanged whatever way the script was started |
### Postcondition Coverage
| Postcondition (from contract) | Satisfied by message |
| --- | --- |
| P1 Run | `startFromWorkingFolder` (the run starts with it) |
| P2 Checkout | `resolveCheckout(invocation)` and the creation of `Checkout` |
| P3 WorkingFolder | `currentFolder()` and the creation of `WorkingFolder` |
| P4 default directory under the WorkingFolder | `startProjectCreation(checkout, workingFolder, ...)`; the prompt default is built from `workingFolder` |
| P5 Configuration | `startProjectCreation` loads `config.env` and `.env` from `checkout` or from the given paths (`load` of [SD-001]) |
| P6 PromptSet | the returned `promptSet` |
| Exceptions: files not found; configuration not found or malformed | the two `alt` fragments |
### Responsibility Check
`Launcher` only finds the checkout and the working folder; it reads no configuration and makes no repository. `ProjectCreator` keeps every other responsibility of [SD-001].
---
[OC-002]: ./oc.md
[DCD-003]: ./dcd.md
[DICT-001]: ../dictionary.md
[SD-001]: ../uc-001/sd.md
+50
View File
@@ -0,0 +1,50 @@
# System Sequence Diagram
## Metadata
| Key | Value |
| --- | --- |
| ID | SSD-002 |
| CrossReference | [UC-002], [DM-003] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-07 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version | pending |
---
## Source Use Case
Start the script as a global command ([UC-002]) — scenario: main success scenario
## Diagram
```plantuml
@startuml
actor Maintainer as A
participant ":System" as S
A -> S : startFromWorkingFolder(configPath, envPath)
S --> A : prompts for project details
A -> S : provideProjectDetails(...)
S --> A : creation summary with the project's full path
@enduml
```
## System Operations
| Step | Message | Parameters | Return | Use case step |
| --- | --- | --- | --- | --- |
| 3 to 4 | startFromWorkingFolder | configPath (optional), envPath (optional) | prompts for project details whose default directory is under the working folder | 3, 4, 5 |
| 5 | provideProjectDetails | the parameters of `provideProjectDetails` in [UC-001] | creation summary that names the full path of the new project | 5, 6 |
Failure flows (extensions 1a, 3a, 4a and 4b of [UC-002]) are out of scope for this diagram: they end the run with a message and add no system operation. `provideProjectDetails` is the operation of [UC-001] and is not repeated in [OC-002]; the only difference is the base of the default `directory`. Making the command link (step 1) and opening the shell (step 2) are done by the Maintainer outside the system, so they are not system operations.
## Lifecycle Notes
One script run, as in [UC-001]. The command link persists between runs; the system keeps no state of it.
---
[UC-002]: ./uc.md
[DM-003]: ./dm.md
[OC-002]: ./oc.md
+74
View File
@@ -0,0 +1,74 @@
# Start the script as a global command
## Metadata
| Key | Value |
| --- | --- |
| ID | UC-002 |
| CrossReference | [UCD-001], [US-001], [SA-001], [BC-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-07 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version | pending |
---
**Format:** Fully Dressed
## Fully Dressed
- **Scope:** RepoFoundry (`create-project.sh`)
- **Level:** user-goal
- **Primary Actor:** Maintainer (S01 or S02; one person holds both roles for now)
- **Stakeholders and Interests:**
- S01 — the script is started by name from any folder, and the new project lands where S01 stands
- S02 — starting through a link never reads or writes outside the checkout and the current folder
- S03 — the README says exactly how to make the command global
- **Preconditions:**
- The checkout of RepoFoundry exists and holds `config.env` and `.env` as described in the README, or the Maintainer points to them with `--config` and `--env`.
- A folder that is on the shell's `PATH` exists and the Maintainer may write to it.
- **Postconditions (success guarantee):**
- A command link exists in a `PATH` folder and leads to the script in the checkout.
- The Maintainer started the script by that name from a working folder, and use case [UC-001] ran with that working folder as its base: the default directory of the new project is `./<name>` under it.
- Nothing was written outside the working folder and the new project.
### Main Success Scenario
1. The Maintainer makes the script reachable by name: creates a command link in a `PATH` folder that leads to `src/create-project.sh` in the checkout (the README gives the command).
2. The Maintainer opens a shell in the folder in which the new project is to be created (the working folder).
3. The Maintainer starts the script by the name of the command link.
4. The system follows the command link to the checkout, loads its own files from there, and reads `config.env` and `.env` from the checkout, or from the files named by `--config` and `--env`.
5. The system runs [UC-001] (`<<include>>`) with the working folder as the base of the default directory of the new project.
6. The system reports a summary that names the full path of the new project.
### Extensions (Alternative / Exception Flows)
- 1a. The `PATH` folder is not writable, or not on `PATH`:
1. The README names the other choices (a folder the Maintainer owns and adds to `PATH`, or an alias); the system is not involved.
- 3a. The command link is broken (the checkout was moved or removed):
1. The shell reports that the command cannot run; the README says how to recreate the link.
- 4a. The checkout's own files cannot be found from the link target:
1. The system stops before any change and names the folder it looked in.
- 4b. `config.env` or `.env` is not found:
1. The system stops before any change, names the path it looked in and says that `--config` and `--env` can point elsewhere.
### Special Requirements / Business Rules
| Step | Rule |
| --- | --- |
| 1 | The command link is made by the Maintainer with the shell, not by the script; the script never edits `PATH`, a shell profile or a system folder |
| 4 | The system finds its own files by following the command link, however many links lie on the way, on every supported platform |
| 4 | `config.env` and `.env` are read from the checkout, never from the working folder, unless `--config` and `--env` name them |
| 5 | The base of the default directory is the working folder, never the checkout |
| 3 to 6 | Behaviour, prompts and summary are the same as when the script is started by its path from the checkout |
### Open Issues
- The README example is tested on Linux, macOS and Git Bash on Windows (MIL-007 criterion 6).
---
[UCD-001]: ../use-case-diagram.md
[US-001]: ../user-stories.md
[SA-001]: ../stakeholder-analysis.md
[BC-001]: ../business-case.md