napkinstack 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 NapkinStack
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,139 @@
1
+ Metadata-Version: 2.4
2
+ Name: napkinstack
3
+ Version: 0.1.0
4
+ Summary: Framework de travail pour faire travailler plusieurs équipes et leurs agents sur un même dépôt : modules, contrats, garde-fous en CI.
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Requires-Dist: pyyaml>=6.0
8
+ Requires-Dist: copier==9.18.2
9
+ Requires-Dist: pre-commit==4.6.2
10
+ Requires-Python: >=3.12
11
+ Project-URL: Homepage, https://github.com/NapkinStack/engineering-os
12
+ Project-URL: Source, https://github.com/NapkinStack/engineering-os
13
+ Project-URL: Issues, https://github.com/NapkinStack/engineering-os/issues
14
+ Description-Content-Type: text/markdown
15
+
16
+ # NapkinStack
17
+
18
+ Framework de travail pour faire travailler plusieurs équipes et leurs agents sur un même
19
+ dépôt : modules, contrats, garde-fous en CI. Sur le modèle de Django ou Rails, une commande
20
+ crée le projet, qui reçoit ensuite les nouvelles versions à sa demande ; aucune stack
21
+ applicative n'est imposée. Positionnement et vocabulaire : [`PRODUCT.md`](PRODUCT.md) §1.
22
+
23
+ > **État : en construction (v0.1.0).** Toutes les commandes fonctionnent depuis ce dépôt ;
24
+ > la première version publiée sur PyPI arrive au chantier M5, avant un premier projet
25
+ > pilote. Suivi : [feuille de route](docs/governance/plans/2026-09-15-moteur-v0.1.0.md),
26
+ > [`docs/governance/chantiers.md`](docs/governance/chantiers.md).
27
+
28
+ ## Le parcours d'un projet
29
+
30
+ ```mermaid
31
+ flowchart LR
32
+ I["Installer<br/>uv tool install"]:::cmd --> N["nstack init"]:::cmd
33
+ N --> G["Publier sur GitHub<br/>appliquer la checklist"]:::humain
34
+ G --> D["nstack doctor<br/>lecture seule"]:::cmd
35
+ D --> M["nstack new-module"]:::cmd
36
+ M --> W["Travail en PR<br/>l'équipe et son agent"]:::humain
37
+ W --> U["nstack update<br/>branche fusionnée"]:::cmd
38
+ U --> P["PR relue<br/>validée par la CI"]:::humain
39
+ P -->|"version suivante"| U
40
+
41
+ classDef cmd fill:#1f2937,color:#fff
42
+ classDef humain fill:#065f46,color:#fff
43
+ ```
44
+
45
+ **Légende** — gris : commande NapkinStack · vert : action de l'équipe. Décision :
46
+ [PDR-0001](docs/pdr/0001-creer-un-projet-et-recevoir-les-evolutions.md).
47
+
48
+ Le projet possède son squelette et l'adapte librement. Chaque nouvelle version lui arrive
49
+ à sa demande, fusionnée avec ses adaptations ; les conflits restent à l'équipe.
50
+
51
+ ```mermaid
52
+ flowchart LR
53
+ V1["Squelette v0.1<br/>base commune"]:::ref --> F{"Fusion<br/>à 3 voies"}
54
+ V2["Squelette v0.2<br/>correctifs NapkinStack"]:::ns --> F
55
+ PR["Projet<br/>adaptations de l'équipe"]:::equipe --> F
56
+ F -->|"lignes différentes"| B["Branche de mise à jour<br/>correctifs + adaptations"]:::ok
57
+ F -->|"même ligne modifiée"| X["Conflit marqué<br/>commit refusé"]:::ko
58
+
59
+ classDef ref fill:#374151,color:#fff
60
+ classDef ns fill:#1e3a8a,color:#fff
61
+ classDef equipe fill:#065f46,color:#fff
62
+ classDef ok fill:#065f46,color:#fff
63
+ classDef ko fill:#7c2d12,color:#fff
64
+ ```
65
+
66
+ **Légende** — gris : version dont le projet est issu · bleu : nouvelle version · vert :
67
+ travail de l'équipe et résultat accepté · rouge : conflit laissé à l'équipe.
68
+
69
+ ## Installer
70
+
71
+ ```bash
72
+ uv tool install napkinstack --with-executables-from pre-commit # prérequis : uv et git
73
+ nstack init mon-projet
74
+ ```
75
+
76
+ Disponible dès la publication de la v0.1.0 sur PyPI ; chaque projet épingle ensuite sa
77
+ version et la change par `nstack update`.
78
+
79
+ ## Les commandes
80
+
81
+ | Commande | Rôle |
82
+ |---|---|
83
+ | `nstack init <dossier>` | Crée le projet : squelette, dépôt git, commit initial, checklist GitHub |
84
+ | `nstack doctor` | Vérifie le poste et les réglages GitHub, en lecture seule |
85
+ | `nstack new-module <nom> <organisation>/<équipe> <criticité>` | Crée un module, sans stack imposée |
86
+ | `nstack check`, `test`, `bootstrap` `[module]` ; `nstack run <module>` | Exécutent les commandes déclarées dans le manifest du module |
87
+ | `nstack fitness` | Manifests, frontières entre modules, skills |
88
+ | `nstack pr-scope` | Une PR = un module, budget de revue |
89
+ | `nstack skills` | Expose les playbooks en skills pour l'agent |
90
+ | `nstack update` | Pose la nouvelle version sur une branche à relire |
91
+
92
+ **Prérequis** : uv et git. Les garde-fous bloquent vraiment sur un dépôt GitHub public, ou
93
+ privé sous l'offre Team ou Pro ; sur un dépôt privé de l'offre Free, la CI informe sans
94
+ bloquer ([précision de PDR-0001](docs/pdr/0001-creer-un-projet-et-recevoir-les-evolutions.md)).
95
+
96
+ **IA** : NapkinStack n'en embarque aucune. L'agent de l'équipe (Claude Code, Codex,
97
+ Copilot…) lit le kernel et les playbooks, lance les commandes, et la CI accepte ou refuse
98
+ ses propositions comme celles de n'importe quel contributeur.
99
+
100
+ ## Ce dépôt
101
+
102
+ ```mermaid
103
+ flowchart LR
104
+ S["skeleton/<br/>squelette de projet"]:::livre -->|"copier.yml"| P["Projet d'une équipe"]:::projet
105
+ E["src/napkinstack/<br/>moteur nstack"]:::livre -.->|"version épinglée"| P
106
+ A["PRODUCT.md · docs/governance/<br/>platform/ · CI du dépôt"]:::interne
107
+
108
+ classDef livre fill:#1e3a8a,color:#fff
109
+ classDef projet fill:#065f46,color:#fff
110
+ classDef interne fill:#374151,color:#fff
111
+ ```
112
+
113
+ **Légende** — bleu : livré aux projets · vert : projet généré, qui possède son squelette ·
114
+ gris : développement de NapkinStack, jamais copié (PDR-0001 R6). Trait plein : génération ;
115
+ pointillé : dépendance versionnée.
116
+
117
+ | Chemin | Rôle |
118
+ |---|---|
119
+ | `skeleton/` | Ce que reçoit chaque projet : kernel, playbooks, manuel, CI, hooks |
120
+ | `copier.yml` | Questions posées à la création (gabarit Copier, ADR-0001) |
121
+ | `src/napkinstack/` | Le moteur, commande `nstack` |
122
+ | `platform/` | Enveloppe du module moteur : manifest, runbook, tests |
123
+ | `PRODUCT.md`, `docs/governance/` | Contexte de travail sur NapkinStack |
124
+ | `docs/adr/`, `docs/pdr/` | Décisions de NapkinStack |
125
+
126
+ ## Développer NapkinStack
127
+
128
+ ```bash
129
+ uv sync # prérequis : uv
130
+ uv run pre-commit install
131
+ uv run nstack fitness # garde-fous du dépôt
132
+ uv run bash platform/tests/run.sh # oracle : chaque garde-fou prouve qu'il sait échouer
133
+ uv run nstack init /tmp/essai --source . --ref HEAD # projet d'essai depuis l'arbre de travail
134
+ uv run nstack doctor --root /tmp/essai # poste et réglages GitHub, en lecture seule
135
+ ```
136
+
137
+ Contribuer : [`CONTRIBUTING.md`](CONTRIBUTING.md), après [`PRODUCT.md`](PRODUCT.md).
138
+
139
+ Licence : [MIT](LICENSE).
@@ -0,0 +1,124 @@
1
+ # NapkinStack
2
+
3
+ Framework de travail pour faire travailler plusieurs équipes et leurs agents sur un même
4
+ dépôt : modules, contrats, garde-fous en CI. Sur le modèle de Django ou Rails, une commande
5
+ crée le projet, qui reçoit ensuite les nouvelles versions à sa demande ; aucune stack
6
+ applicative n'est imposée. Positionnement et vocabulaire : [`PRODUCT.md`](PRODUCT.md) §1.
7
+
8
+ > **État : en construction (v0.1.0).** Toutes les commandes fonctionnent depuis ce dépôt ;
9
+ > la première version publiée sur PyPI arrive au chantier M5, avant un premier projet
10
+ > pilote. Suivi : [feuille de route](docs/governance/plans/2026-09-15-moteur-v0.1.0.md),
11
+ > [`docs/governance/chantiers.md`](docs/governance/chantiers.md).
12
+
13
+ ## Le parcours d'un projet
14
+
15
+ ```mermaid
16
+ flowchart LR
17
+ I["Installer<br/>uv tool install"]:::cmd --> N["nstack init"]:::cmd
18
+ N --> G["Publier sur GitHub<br/>appliquer la checklist"]:::humain
19
+ G --> D["nstack doctor<br/>lecture seule"]:::cmd
20
+ D --> M["nstack new-module"]:::cmd
21
+ M --> W["Travail en PR<br/>l'équipe et son agent"]:::humain
22
+ W --> U["nstack update<br/>branche fusionnée"]:::cmd
23
+ U --> P["PR relue<br/>validée par la CI"]:::humain
24
+ P -->|"version suivante"| U
25
+
26
+ classDef cmd fill:#1f2937,color:#fff
27
+ classDef humain fill:#065f46,color:#fff
28
+ ```
29
+
30
+ **Légende** — gris : commande NapkinStack · vert : action de l'équipe. Décision :
31
+ [PDR-0001](docs/pdr/0001-creer-un-projet-et-recevoir-les-evolutions.md).
32
+
33
+ Le projet possède son squelette et l'adapte librement. Chaque nouvelle version lui arrive
34
+ à sa demande, fusionnée avec ses adaptations ; les conflits restent à l'équipe.
35
+
36
+ ```mermaid
37
+ flowchart LR
38
+ V1["Squelette v0.1<br/>base commune"]:::ref --> F{"Fusion<br/>à 3 voies"}
39
+ V2["Squelette v0.2<br/>correctifs NapkinStack"]:::ns --> F
40
+ PR["Projet<br/>adaptations de l'équipe"]:::equipe --> F
41
+ F -->|"lignes différentes"| B["Branche de mise à jour<br/>correctifs + adaptations"]:::ok
42
+ F -->|"même ligne modifiée"| X["Conflit marqué<br/>commit refusé"]:::ko
43
+
44
+ classDef ref fill:#374151,color:#fff
45
+ classDef ns fill:#1e3a8a,color:#fff
46
+ classDef equipe fill:#065f46,color:#fff
47
+ classDef ok fill:#065f46,color:#fff
48
+ classDef ko fill:#7c2d12,color:#fff
49
+ ```
50
+
51
+ **Légende** — gris : version dont le projet est issu · bleu : nouvelle version · vert :
52
+ travail de l'équipe et résultat accepté · rouge : conflit laissé à l'équipe.
53
+
54
+ ## Installer
55
+
56
+ ```bash
57
+ uv tool install napkinstack --with-executables-from pre-commit # prérequis : uv et git
58
+ nstack init mon-projet
59
+ ```
60
+
61
+ Disponible dès la publication de la v0.1.0 sur PyPI ; chaque projet épingle ensuite sa
62
+ version et la change par `nstack update`.
63
+
64
+ ## Les commandes
65
+
66
+ | Commande | Rôle |
67
+ |---|---|
68
+ | `nstack init <dossier>` | Crée le projet : squelette, dépôt git, commit initial, checklist GitHub |
69
+ | `nstack doctor` | Vérifie le poste et les réglages GitHub, en lecture seule |
70
+ | `nstack new-module <nom> <organisation>/<équipe> <criticité>` | Crée un module, sans stack imposée |
71
+ | `nstack check`, `test`, `bootstrap` `[module]` ; `nstack run <module>` | Exécutent les commandes déclarées dans le manifest du module |
72
+ | `nstack fitness` | Manifests, frontières entre modules, skills |
73
+ | `nstack pr-scope` | Une PR = un module, budget de revue |
74
+ | `nstack skills` | Expose les playbooks en skills pour l'agent |
75
+ | `nstack update` | Pose la nouvelle version sur une branche à relire |
76
+
77
+ **Prérequis** : uv et git. Les garde-fous bloquent vraiment sur un dépôt GitHub public, ou
78
+ privé sous l'offre Team ou Pro ; sur un dépôt privé de l'offre Free, la CI informe sans
79
+ bloquer ([précision de PDR-0001](docs/pdr/0001-creer-un-projet-et-recevoir-les-evolutions.md)).
80
+
81
+ **IA** : NapkinStack n'en embarque aucune. L'agent de l'équipe (Claude Code, Codex,
82
+ Copilot…) lit le kernel et les playbooks, lance les commandes, et la CI accepte ou refuse
83
+ ses propositions comme celles de n'importe quel contributeur.
84
+
85
+ ## Ce dépôt
86
+
87
+ ```mermaid
88
+ flowchart LR
89
+ S["skeleton/<br/>squelette de projet"]:::livre -->|"copier.yml"| P["Projet d'une équipe"]:::projet
90
+ E["src/napkinstack/<br/>moteur nstack"]:::livre -.->|"version épinglée"| P
91
+ A["PRODUCT.md · docs/governance/<br/>platform/ · CI du dépôt"]:::interne
92
+
93
+ classDef livre fill:#1e3a8a,color:#fff
94
+ classDef projet fill:#065f46,color:#fff
95
+ classDef interne fill:#374151,color:#fff
96
+ ```
97
+
98
+ **Légende** — bleu : livré aux projets · vert : projet généré, qui possède son squelette ·
99
+ gris : développement de NapkinStack, jamais copié (PDR-0001 R6). Trait plein : génération ;
100
+ pointillé : dépendance versionnée.
101
+
102
+ | Chemin | Rôle |
103
+ |---|---|
104
+ | `skeleton/` | Ce que reçoit chaque projet : kernel, playbooks, manuel, CI, hooks |
105
+ | `copier.yml` | Questions posées à la création (gabarit Copier, ADR-0001) |
106
+ | `src/napkinstack/` | Le moteur, commande `nstack` |
107
+ | `platform/` | Enveloppe du module moteur : manifest, runbook, tests |
108
+ | `PRODUCT.md`, `docs/governance/` | Contexte de travail sur NapkinStack |
109
+ | `docs/adr/`, `docs/pdr/` | Décisions de NapkinStack |
110
+
111
+ ## Développer NapkinStack
112
+
113
+ ```bash
114
+ uv sync # prérequis : uv
115
+ uv run pre-commit install
116
+ uv run nstack fitness # garde-fous du dépôt
117
+ uv run bash platform/tests/run.sh # oracle : chaque garde-fou prouve qu'il sait échouer
118
+ uv run nstack init /tmp/essai --source . --ref HEAD # projet d'essai depuis l'arbre de travail
119
+ uv run nstack doctor --root /tmp/essai # poste et réglages GitHub, en lecture seule
120
+ ```
121
+
122
+ Contribuer : [`CONTRIBUTING.md`](CONTRIBUTING.md), après [`PRODUCT.md`](PRODUCT.md).
123
+
124
+ Licence : [MIT](LICENSE).
@@ -0,0 +1,31 @@
1
+ [project]
2
+ name = "napkinstack"
3
+ version = "0.1.0"
4
+ description = "Framework de travail pour faire travailler plusieurs équipes et leurs agents sur un même dépôt : modules, contrats, garde-fous en CI."
5
+ requires-python = ">=3.12"
6
+ license = "MIT"
7
+ license-files = ["LICENSE"]
8
+ readme = "README.md"
9
+ dependencies = [
10
+ "PyYAML>=6.0",
11
+ "copier==9.18.2",
12
+ "pre-commit==4.6.2",
13
+ ]
14
+
15
+ [project.urls]
16
+ Homepage = "https://github.com/NapkinStack/engineering-os"
17
+ Source = "https://github.com/NapkinStack/engineering-os"
18
+ Issues = "https://github.com/NapkinStack/engineering-os/issues"
19
+
20
+ [project.scripts]
21
+ nstack = "napkinstack.cli:main"
22
+
23
+ [dependency-groups]
24
+ dev = ["pytest==9.1.1"]
25
+
26
+ [tool.uv]
27
+ required-version = ">=0.12.14,<0.13"
28
+
29
+ [build-system]
30
+ requires = ["uv_build>=0.12.14,<0.13"]
31
+ build-backend = "uv_build"
@@ -0,0 +1,27 @@
1
+ [project]
2
+ name = "napkinstack"
3
+ version = "0.1.0"
4
+ description = "Framework de travail pour faire travailler plusieurs équipes et leurs agents sur un même dépôt : modules, contrats, garde-fous en CI."
5
+ requires-python = ">=3.12"
6
+ license = "MIT"
7
+ license-files = ["LICENSE"]
8
+ readme = "README.md"
9
+ dependencies = ["PyYAML>=6.0", "copier==9.18.2", "pre-commit==4.6.2"]
10
+
11
+ [project.urls]
12
+ Homepage = "https://github.com/NapkinStack/engineering-os"
13
+ Source = "https://github.com/NapkinStack/engineering-os"
14
+ Issues = "https://github.com/NapkinStack/engineering-os/issues"
15
+
16
+ [project.scripts]
17
+ nstack = "napkinstack.cli:main"
18
+
19
+ [dependency-groups]
20
+ dev = ["pytest==9.1.1"]
21
+
22
+ [tool.uv]
23
+ required-version = ">=0.12.14,<0.13"
24
+
25
+ [build-system]
26
+ requires = ["uv_build>=0.12.14,<0.13"]
27
+ build-backend = "uv_build"
@@ -0,0 +1,5 @@
1
+ """NapkinStack — moteur : fitness functions, skills et scaffold de module."""
2
+
3
+ from importlib.metadata import version
4
+
5
+ __version__ = version("napkinstack")
@@ -0,0 +1,103 @@
1
+ """Point d'entrée unique `nstack` (chantier C1, PDR-0001)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import os
7
+ import subprocess
8
+ from pathlib import Path
9
+
10
+ from napkinstack import __version__, doctor, modules, skills
11
+ from napkinstack.fitness import boundaries, manifests
12
+
13
+ PACKAGE = Path(__file__).resolve().parent
14
+
15
+
16
+ def _root(value: str) -> Path:
17
+ root = Path(value).resolve()
18
+ if not root.is_dir():
19
+ raise argparse.ArgumentTypeError(f"racine introuvable : {value}")
20
+ return root
21
+
22
+
23
+ def _script(relative: str, *args: str, root: Path) -> int:
24
+ env = {**os.environ, "NSTACK_ROOT": str(root)}
25
+ return subprocess.run(["bash", str(PACKAGE / relative), *args], cwd=root, env=env).returncode
26
+
27
+
28
+ def _fitness(root: Path) -> int:
29
+ results = [manifests.run(root), boundaries.run(root), skills.run(root, check_only=True)]
30
+ return 1 if any(results) else 0
31
+
32
+
33
+ def _add(sub, name: str, help_: str, func) -> argparse.ArgumentParser:
34
+ parser = sub.add_parser(name, help=help_)
35
+ parser.add_argument("--root", type=_root, default=Path.cwd(),
36
+ help="racine du projet (défaut : dossier courant)")
37
+ parser.set_defaults(func=func)
38
+ return parser
39
+
40
+
41
+ def _init(args: argparse.Namespace) -> int:
42
+ from napkinstack import project # Copier ne se charge que pour init et update
43
+
44
+ answers = {"project_name": args.project_name, "github_repo": args.github_repo,
45
+ "owner_team": args.owner_team}
46
+ return project.init(args.destination, answers, args.source or project.SOURCE,
47
+ args.ref or project.default_ref())
48
+
49
+
50
+ def _update(args: argparse.Namespace) -> int:
51
+ from napkinstack import project
52
+
53
+ return project.update(args.root, args.ref or project.default_ref())
54
+
55
+
56
+ def build_parser() -> argparse.ArgumentParser:
57
+ parser = argparse.ArgumentParser(prog="nstack", description="Moteur NapkinStack.")
58
+ parser.add_argument("--version", action="version", version=f"nstack {__version__}")
59
+ sub = parser.add_subparsers(dest="command", required=True, metavar="commande")
60
+ _add(sub, "manifests", "manifests, cycles de vie, dépréciations (M1–M9)",
61
+ lambda a: manifests.run(a.root))
62
+ _add(sub, "boundaries", "graphe déclaré contre graphe réel (B1–B5)",
63
+ lambda a: boundaries.run(a.root))
64
+ sk = _add(sub, "skills", "génère ou vérifie les skills (S1–S4)",
65
+ lambda a: skills.run(a.root, check_only=a.check))
66
+ sk.add_argument("--check", action="store_true", help="vérifier sans écrire")
67
+ _add(sub, "fitness", "manifests + frontières + skills",
68
+ lambda a: _fitness(a.root))
69
+ _add(sub, "doctor", "diagnostique le poste et les réglages GitHub, en lecture seule (PDR-0001)",
70
+ lambda a: doctor.run(a.root))
71
+ nm = _add(sub, "new-module", "crée un module et ses garde-fous, sans stack imposée",
72
+ lambda a: modules.nouveau(a.root, a.name, a.owner, a.criticality))
73
+ nm.add_argument("name", help="nom du module, kebab-case")
74
+ nm.add_argument("owner", help="équipe GitHub, organisation/équipe")
75
+ nm.add_argument("criticality", choices=["prototype", "standard", "eleve", "critique"])
76
+ for nom_verbe, aide in (("bootstrap", "prépare un module, ou tous (commands.bootstrap)"),
77
+ ("check", "format, lint, types d'un module, ou de tous (commands.check)"),
78
+ ("test", "tests d'un module, ou de tous (commands.test)")):
79
+ vb = _add(sub, nom_verbe, aide, lambda a, v=nom_verbe: modules.verbe(a.root, v, a.module))
80
+ vb.add_argument("module", nargs="?", help="nom du module (défaut : tous)")
81
+ rn = _add(sub, "run", "démarre un module en local (commands.run)",
82
+ lambda a: modules.verbe(a.root, "run", a.module))
83
+ rn.add_argument("module")
84
+ ps = _add(sub, "pr-scope", "une PR = un module, budget de revue (P1–P2)",
85
+ lambda a: _script("fitness/pr_scope.sh", a.base, root=a.root))
86
+ ps.add_argument("--base", default="origin/main")
87
+ ini = sub.add_parser("init", help="crée un projet à partir du squelette (PDR-0001)")
88
+ ini.add_argument("destination", type=Path, help="dossier du projet, absent ou vide")
89
+ ini.add_argument("--project-name", help="nom du projet (demandé si absent)")
90
+ ini.add_argument("--github-repo", help="dépôt GitHub, organisation/nom (demandé si absent)")
91
+ ini.add_argument("--owner-team", help="équipe GitHub du socle, organisation/équipe (demandé si absent)")
92
+ ini.add_argument("--source", help="gabarit : URL ou chemin (défaut : dépôt NapkinStack)")
93
+ ini.add_argument("--ref", help="version du squelette, tag vX.Y.Z (défaut : celle de nstack)")
94
+ ini.set_defaults(func=_init)
95
+ up = _add(sub, "update", "fusionne une version de NapkinStack sur une branche à relire (PDR-0001)",
96
+ _update)
97
+ up.add_argument("--ref", help="version cible, tag vX.Y.Z (défaut : celle de nstack)")
98
+ return parser
99
+
100
+
101
+ def main(argv: list[str] | None = None) -> int:
102
+ args = build_parser().parse_args(argv)
103
+ return args.func(args)