ai-forge-cli 2.1.2__tar.gz → 2.1.3__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.
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/PKG-INFO +18 -16
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/README.md +17 -15
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/pyproject.toml +2 -2
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/src/ai_forge_cli.egg-info/PKG-INFO +18 -16
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/src/ai_forge_cli.egg-info/SOURCES.txt +2 -0
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/src/cli/__init__.py +1 -1
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/src/cli/commands/init.py +85 -70
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/src/cli/common.py +15 -2
- ai_forge_cli-2.1.3/src/cli/resources/FRAMEWORK_V3.md +184 -0
- ai_forge_cli-2.1.3/src/cli/resources/SCHEMA_REFERENCE_V3.md +1583 -0
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/tests/test_context.py +22 -13
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/setup.cfg +0 -0
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/src/ai_forge_cli.egg-info/dependency_links.txt +0 -0
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/src/ai_forge_cli.egg-info/entry_points.txt +0 -0
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/src/ai_forge_cli.egg-info/requires.txt +0 -0
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/src/ai_forge_cli.egg-info/top_level.txt +0 -0
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/src/cli/__main__.py +0 -0
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/src/cli/assets/audit_template.html +0 -0
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/src/cli/assets/forge_full_logo.drawio.svg +0 -0
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/src/cli/assets/forge_white_small.drawio.svg +0 -0
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/src/cli/commands/__init__.py +0 -0
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/src/cli/commands/audit.py +0 -0
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/src/cli/commands/base.py +0 -0
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/src/cli/commands/context.py +0 -0
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/src/cli/forge.py +0 -0
- {ai_forge_cli-2.1.2 → ai_forge_cli-2.1.3}/src/cli/schema.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ai-forge-cli
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.3
|
|
4
4
|
Summary: Forge V3 context CLI
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -27,8 +27,8 @@ scoped context, validation, and audit artifacts to the active skill.
|
|
|
27
27
|
|
|
28
28
|
- `src/cli`: the Forge CLI implementation
|
|
29
29
|
- `skills/`: the Forge skill source used by initialized repositories
|
|
30
|
-
- `FRAMEWORK_V3.md`: the framework process and recommended authoring order
|
|
31
|
-
- `SCHEMA_REFERENCE_V3.md`: the schema contract and field rules
|
|
30
|
+
- `FRAMEWORK_V3.md`: the framework process and recommended authoring order used to seed `forge/FRAMEWORK_V3.md`
|
|
31
|
+
- `SCHEMA_REFERENCE_V3.md`: the schema contract and field rules used to seed `forge/SCHEMA_REFERENCE_V3.md`
|
|
32
32
|
- `examples/`: example Forge repositories and audit artifacts
|
|
33
33
|
|
|
34
34
|
## CLI Commands
|
|
@@ -57,21 +57,21 @@ scoped context, validation, and audit artifacts to the active skill.
|
|
|
57
57
|
|
|
58
58
|
1. Run `forge init` in an empty repository.
|
|
59
59
|
2. Read:
|
|
60
|
-
- `
|
|
61
|
-
- `
|
|
62
|
-
- `
|
|
60
|
+
- `forge/USING_FORGE.md`
|
|
61
|
+
- `forge/FRAMEWORK_V3.md`
|
|
62
|
+
- `forge/SCHEMA_REFERENCE_V3.md`
|
|
63
63
|
3. Use `forge-schema` to define:
|
|
64
|
-
- `system.yaml`
|
|
65
|
-
- `high_level_flows/`
|
|
66
|
-
- `early_state.yaml`
|
|
67
|
-
- `runtime.yaml`
|
|
68
|
-
4. Derive `verticals/` once the runtime picture is clear.
|
|
64
|
+
- `forge/system.yaml`
|
|
65
|
+
- `forge/high_level_flows/`
|
|
66
|
+
- `forge/early_state.yaml`
|
|
67
|
+
- `forge/runtime.yaml`
|
|
68
|
+
4. Derive `forge/verticals/` once the runtime picture is clear.
|
|
69
69
|
5. Pick one vertical and deepen it through:
|
|
70
|
-
- `runtime_flows/`
|
|
71
|
-
- `data_shapes/`
|
|
72
|
-
- `persistent_shapes/`
|
|
73
|
-
- `containers/`
|
|
74
|
-
- `deployment.yaml`
|
|
70
|
+
- `forge/runtime_flows/`
|
|
71
|
+
- `forge/data_shapes/`
|
|
72
|
+
- `forge/persistent_shapes/`
|
|
73
|
+
- `forge/containers/`
|
|
74
|
+
- `forge/deployment.yaml`
|
|
75
75
|
6. Use `forge-review` to check the slice for drift, bloat, and broken references before build starts.
|
|
76
76
|
7. Use `forge-security` to make the slice security posture explicit before build starts.
|
|
77
77
|
8. Use `forge-build` to plan or implement that approved vertical.
|
|
@@ -83,6 +83,8 @@ The intended operating mode is:
|
|
|
83
83
|
3. use `forge context` only for that narrow scope
|
|
84
84
|
4. use `forge audit` when you need a whole-system review artifact
|
|
85
85
|
|
|
86
|
+
An initialized repository keeps the Forge-owned schema workspace under `./forge/`. The repo root stays available for product code, app docs, and non-Forge tooling.
|
|
87
|
+
|
|
86
88
|
## Golden Path Examples
|
|
87
89
|
|
|
88
90
|
- `examples/forge_v2_ordering_example`: the compact canonical example for docs,
|
|
@@ -12,8 +12,8 @@ scoped context, validation, and audit artifacts to the active skill.
|
|
|
12
12
|
|
|
13
13
|
- `src/cli`: the Forge CLI implementation
|
|
14
14
|
- `skills/`: the Forge skill source used by initialized repositories
|
|
15
|
-
- `FRAMEWORK_V3.md`: the framework process and recommended authoring order
|
|
16
|
-
- `SCHEMA_REFERENCE_V3.md`: the schema contract and field rules
|
|
15
|
+
- `FRAMEWORK_V3.md`: the framework process and recommended authoring order used to seed `forge/FRAMEWORK_V3.md`
|
|
16
|
+
- `SCHEMA_REFERENCE_V3.md`: the schema contract and field rules used to seed `forge/SCHEMA_REFERENCE_V3.md`
|
|
17
17
|
- `examples/`: example Forge repositories and audit artifacts
|
|
18
18
|
|
|
19
19
|
## CLI Commands
|
|
@@ -42,21 +42,21 @@ scoped context, validation, and audit artifacts to the active skill.
|
|
|
42
42
|
|
|
43
43
|
1. Run `forge init` in an empty repository.
|
|
44
44
|
2. Read:
|
|
45
|
-
- `
|
|
46
|
-
- `
|
|
47
|
-
- `
|
|
45
|
+
- `forge/USING_FORGE.md`
|
|
46
|
+
- `forge/FRAMEWORK_V3.md`
|
|
47
|
+
- `forge/SCHEMA_REFERENCE_V3.md`
|
|
48
48
|
3. Use `forge-schema` to define:
|
|
49
|
-
- `system.yaml`
|
|
50
|
-
- `high_level_flows/`
|
|
51
|
-
- `early_state.yaml`
|
|
52
|
-
- `runtime.yaml`
|
|
53
|
-
4. Derive `verticals/` once the runtime picture is clear.
|
|
49
|
+
- `forge/system.yaml`
|
|
50
|
+
- `forge/high_level_flows/`
|
|
51
|
+
- `forge/early_state.yaml`
|
|
52
|
+
- `forge/runtime.yaml`
|
|
53
|
+
4. Derive `forge/verticals/` once the runtime picture is clear.
|
|
54
54
|
5. Pick one vertical and deepen it through:
|
|
55
|
-
- `runtime_flows/`
|
|
56
|
-
- `data_shapes/`
|
|
57
|
-
- `persistent_shapes/`
|
|
58
|
-
- `containers/`
|
|
59
|
-
- `deployment.yaml`
|
|
55
|
+
- `forge/runtime_flows/`
|
|
56
|
+
- `forge/data_shapes/`
|
|
57
|
+
- `forge/persistent_shapes/`
|
|
58
|
+
- `forge/containers/`
|
|
59
|
+
- `forge/deployment.yaml`
|
|
60
60
|
6. Use `forge-review` to check the slice for drift, bloat, and broken references before build starts.
|
|
61
61
|
7. Use `forge-security` to make the slice security posture explicit before build starts.
|
|
62
62
|
8. Use `forge-build` to plan or implement that approved vertical.
|
|
@@ -68,6 +68,8 @@ The intended operating mode is:
|
|
|
68
68
|
3. use `forge context` only for that narrow scope
|
|
69
69
|
4. use `forge audit` when you need a whole-system review artifact
|
|
70
70
|
|
|
71
|
+
An initialized repository keeps the Forge-owned schema workspace under `./forge/`. The repo root stays available for product code, app docs, and non-Forge tooling.
|
|
72
|
+
|
|
71
73
|
## Golden Path Examples
|
|
72
74
|
|
|
73
75
|
- `examples/forge_v2_ordering_example`: the compact canonical example for docs,
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ai-forge-cli"
|
|
7
|
-
version = "2.1.
|
|
7
|
+
version = "2.1.3"
|
|
8
8
|
description = "Forge V3 context CLI"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -28,7 +28,7 @@ where = ["src"]
|
|
|
28
28
|
include = ["cli*"]
|
|
29
29
|
|
|
30
30
|
[tool.setuptools.package-data]
|
|
31
|
-
cli = ["assets/*.svg", "assets/*.html"]
|
|
31
|
+
cli = ["assets/*.svg", "assets/*.html", "resources/*.md"]
|
|
32
32
|
|
|
33
33
|
[tool.pytest.ini_options]
|
|
34
34
|
testpaths = ["tests"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ai-forge-cli
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.3
|
|
4
4
|
Summary: Forge V3 context CLI
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -27,8 +27,8 @@ scoped context, validation, and audit artifacts to the active skill.
|
|
|
27
27
|
|
|
28
28
|
- `src/cli`: the Forge CLI implementation
|
|
29
29
|
- `skills/`: the Forge skill source used by initialized repositories
|
|
30
|
-
- `FRAMEWORK_V3.md`: the framework process and recommended authoring order
|
|
31
|
-
- `SCHEMA_REFERENCE_V3.md`: the schema contract and field rules
|
|
30
|
+
- `FRAMEWORK_V3.md`: the framework process and recommended authoring order used to seed `forge/FRAMEWORK_V3.md`
|
|
31
|
+
- `SCHEMA_REFERENCE_V3.md`: the schema contract and field rules used to seed `forge/SCHEMA_REFERENCE_V3.md`
|
|
32
32
|
- `examples/`: example Forge repositories and audit artifacts
|
|
33
33
|
|
|
34
34
|
## CLI Commands
|
|
@@ -57,21 +57,21 @@ scoped context, validation, and audit artifacts to the active skill.
|
|
|
57
57
|
|
|
58
58
|
1. Run `forge init` in an empty repository.
|
|
59
59
|
2. Read:
|
|
60
|
-
- `
|
|
61
|
-
- `
|
|
62
|
-
- `
|
|
60
|
+
- `forge/USING_FORGE.md`
|
|
61
|
+
- `forge/FRAMEWORK_V3.md`
|
|
62
|
+
- `forge/SCHEMA_REFERENCE_V3.md`
|
|
63
63
|
3. Use `forge-schema` to define:
|
|
64
|
-
- `system.yaml`
|
|
65
|
-
- `high_level_flows/`
|
|
66
|
-
- `early_state.yaml`
|
|
67
|
-
- `runtime.yaml`
|
|
68
|
-
4. Derive `verticals/` once the runtime picture is clear.
|
|
64
|
+
- `forge/system.yaml`
|
|
65
|
+
- `forge/high_level_flows/`
|
|
66
|
+
- `forge/early_state.yaml`
|
|
67
|
+
- `forge/runtime.yaml`
|
|
68
|
+
4. Derive `forge/verticals/` once the runtime picture is clear.
|
|
69
69
|
5. Pick one vertical and deepen it through:
|
|
70
|
-
- `runtime_flows/`
|
|
71
|
-
- `data_shapes/`
|
|
72
|
-
- `persistent_shapes/`
|
|
73
|
-
- `containers/`
|
|
74
|
-
- `deployment.yaml`
|
|
70
|
+
- `forge/runtime_flows/`
|
|
71
|
+
- `forge/data_shapes/`
|
|
72
|
+
- `forge/persistent_shapes/`
|
|
73
|
+
- `forge/containers/`
|
|
74
|
+
- `forge/deployment.yaml`
|
|
75
75
|
6. Use `forge-review` to check the slice for drift, bloat, and broken references before build starts.
|
|
76
76
|
7. Use `forge-security` to make the slice security posture explicit before build starts.
|
|
77
77
|
8. Use `forge-build` to plan or implement that approved vertical.
|
|
@@ -83,6 +83,8 @@ The intended operating mode is:
|
|
|
83
83
|
3. use `forge context` only for that narrow scope
|
|
84
84
|
4. use `forge audit` when you need a whole-system review artifact
|
|
85
85
|
|
|
86
|
+
An initialized repository keeps the Forge-owned schema workspace under `./forge/`. The repo root stays available for product code, app docs, and non-Forge tooling.
|
|
87
|
+
|
|
86
88
|
## Golden Path Examples
|
|
87
89
|
|
|
88
90
|
- `examples/forge_v2_ordering_example`: the compact canonical example for docs,
|
|
@@ -6,6 +6,7 @@ import sys
|
|
|
6
6
|
import threading
|
|
7
7
|
import time
|
|
8
8
|
from argparse import Namespace
|
|
9
|
+
from importlib.resources import as_file, files
|
|
9
10
|
from pathlib import Path
|
|
10
11
|
|
|
11
12
|
from cli.schema import dump_yaml
|
|
@@ -152,40 +153,40 @@ def _step(number: int, title: str, detail: str) -> str:
|
|
|
152
153
|
|
|
153
154
|
|
|
154
155
|
def _scaffold_repository(target_root: Path, system_name: str, system_id: str) -> None:
|
|
156
|
+
forge_root = target_root / "forge"
|
|
155
157
|
_write_text(target_root / "README.md", _project_readme(system_name))
|
|
156
|
-
_write_text(target_root / "decision_notes.md", "# Decision Notes\n\nRecord meaningful Forge decisions here.\n")
|
|
157
158
|
_write_text(target_root / ".gitignore", _scaffold_gitignore())
|
|
159
|
+
_write_text(forge_root / "decision_notes.md", "# Decision Notes\n\nRecord meaningful Forge decisions here.\n")
|
|
158
160
|
|
|
159
|
-
_write_yaml(
|
|
160
|
-
_write_yaml(
|
|
161
|
-
_write_yaml(
|
|
162
|
-
_write_yaml(
|
|
161
|
+
_write_yaml(forge_root / "system.yaml", _system_seed(system_name, system_id))
|
|
162
|
+
_write_yaml(forge_root / "runtime.yaml", {"schema": "forge.v2.runtime", "runtime": {"containers": [], "relationships": []}})
|
|
163
|
+
_write_yaml(forge_root / "early_state.yaml", {"schema": "forge.v2.early_state", "early_state": []})
|
|
164
|
+
_write_yaml(forge_root / "deployment.yaml", {"schema": "forge.v2.deployment", "deployment": {"environments": []}})
|
|
163
165
|
|
|
164
166
|
for directory in COLLECTION_DIRS:
|
|
165
|
-
(
|
|
167
|
+
(forge_root / directory).mkdir(parents=True, exist_ok=True)
|
|
166
168
|
|
|
167
|
-
_copy_docs(
|
|
168
|
-
_copy_skills(
|
|
169
|
-
_rewrite_skill_references(
|
|
170
|
-
_create_skill_symlinks(target_root)
|
|
169
|
+
_copy_docs(forge_root)
|
|
170
|
+
_copy_skills(forge_root)
|
|
171
|
+
_rewrite_skill_references(forge_root)
|
|
172
|
+
_create_skill_symlinks(target_root, forge_root)
|
|
171
173
|
|
|
172
174
|
|
|
173
175
|
def _source_root() -> Path:
|
|
174
176
|
return Path(__file__).resolve().parents[3]
|
|
175
177
|
|
|
176
178
|
|
|
177
|
-
def _copy_docs(
|
|
178
|
-
|
|
179
|
-
docs_root.mkdir(parents=True, exist_ok=True)
|
|
180
|
-
source_root = _source_root()
|
|
179
|
+
def _copy_docs(forge_root: Path) -> None:
|
|
180
|
+
forge_root.mkdir(parents=True, exist_ok=True)
|
|
181
181
|
for filename in DOC_FILES:
|
|
182
|
-
|
|
183
|
-
|
|
182
|
+
with as_file(files("cli").joinpath("resources", filename)) as source_path:
|
|
183
|
+
shutil.copy2(source_path, forge_root / filename)
|
|
184
|
+
_write_text(forge_root / "USING_FORGE.md", _using_forge_doc())
|
|
184
185
|
|
|
185
186
|
|
|
186
|
-
def _copy_skills(
|
|
187
|
+
def _copy_skills(forge_root: Path) -> None:
|
|
187
188
|
source_skills = _source_root() / "skills"
|
|
188
|
-
target_skills =
|
|
189
|
+
target_skills = forge_root / "skills"
|
|
189
190
|
target_skills.mkdir(parents=True, exist_ok=True)
|
|
190
191
|
for skill_name in SKILL_DIRS:
|
|
191
192
|
shutil.copytree(
|
|
@@ -196,22 +197,22 @@ def _copy_skills(target_root: Path) -> None:
|
|
|
196
197
|
)
|
|
197
198
|
|
|
198
199
|
|
|
199
|
-
def _rewrite_skill_references(
|
|
200
|
+
def _rewrite_skill_references(forge_root: Path) -> None:
|
|
200
201
|
for skill_name in SKILL_DIRS:
|
|
201
|
-
skill_path =
|
|
202
|
+
skill_path = forge_root / "skills" / skill_name / "SKILL.md"
|
|
202
203
|
text = skill_path.read_text(encoding="utf-8")
|
|
203
|
-
text = text.replace("../../SCHEMA_REFERENCE_V3.md", "../../
|
|
204
|
-
text = text.replace("../../FRAMEWORK_V3.md", "../../
|
|
205
|
-
if "Read before starting:" in text and "../../
|
|
204
|
+
text = text.replace("../../SCHEMA_REFERENCE_V3.md", "../../SCHEMA_REFERENCE_V3.md")
|
|
205
|
+
text = text.replace("../../FRAMEWORK_V3.md", "../../FRAMEWORK_V3.md")
|
|
206
|
+
if "Read before starting:" in text and "../../USING_FORGE.md" not in text:
|
|
206
207
|
text = text.replace(
|
|
207
208
|
"Read before starting:\n",
|
|
208
|
-
"Read before starting:\n\n- `../../
|
|
209
|
+
"Read before starting:\n\n- `../../USING_FORGE.md`\n",
|
|
209
210
|
1,
|
|
210
211
|
)
|
|
211
212
|
skill_path.write_text(text, encoding="utf-8")
|
|
212
213
|
|
|
213
214
|
|
|
214
|
-
def _create_skill_symlinks(target_root: Path) -> None:
|
|
215
|
+
def _create_skill_symlinks(target_root: Path, forge_root: Path) -> None:
|
|
215
216
|
for surface in (".claude/skills", ".codex/skills", ".agents/skills"):
|
|
216
217
|
surface_root = target_root / surface
|
|
217
218
|
surface_root.mkdir(parents=True, exist_ok=True)
|
|
@@ -219,7 +220,7 @@ def _create_skill_symlinks(target_root: Path) -> None:
|
|
|
219
220
|
target = surface_root / skill_name
|
|
220
221
|
if target.exists() or target.is_symlink():
|
|
221
222
|
target.unlink()
|
|
222
|
-
target.symlink_to(_relative_symlink_target(surface_root,
|
|
223
|
+
target.symlink_to(_relative_symlink_target(surface_root, forge_root / "skills" / skill_name))
|
|
223
224
|
|
|
224
225
|
|
|
225
226
|
def _relative_symlink_target(link_parent: Path, destination: Path) -> Path:
|
|
@@ -230,9 +231,9 @@ def _project_readme(system_name: str) -> str:
|
|
|
230
231
|
return (
|
|
231
232
|
f"# {system_name}\n\n"
|
|
232
233
|
"Initialized with Forge.\n\n"
|
|
233
|
-
"
|
|
234
|
-
"
|
|
235
|
-
"the active skill needs.\n"
|
|
234
|
+
"Forge scaffolds a dedicated `forge/` workspace for the schema, docs, and skills.\n\n"
|
|
235
|
+
"Start with `forge/USING_FORGE.md`. Forge is skills-first: the skills drive "
|
|
236
|
+
"the workflow, and the CLI supplies only the scoped context or artifacts the active skill needs.\n"
|
|
236
237
|
)
|
|
237
238
|
|
|
238
239
|
|
|
@@ -268,28 +269,40 @@ def _scaffold_gitignore() -> str:
|
|
|
268
269
|
|
|
269
270
|
|
|
270
271
|
def _print_init_summary(target_root: Path, system_name: str, system_id: str) -> None:
|
|
271
|
-
|
|
272
|
+
forge_root = target_root / "forge"
|
|
272
273
|
print(_banner("FORGE INITIALIZED"))
|
|
273
274
|
print(f"Forge initialized at {target_root}")
|
|
274
275
|
print(f"{_color('Location:', YELLOW, bold=True)} {target_root}")
|
|
275
276
|
print("")
|
|
276
277
|
print(_section("Framework"))
|
|
277
278
|
print(_bullet(f"system: {system_name} (`{system_id}`)"))
|
|
278
|
-
print(_bullet(f"
|
|
279
|
-
print(_bullet(f"
|
|
280
|
-
print(_bullet(f"skills: {
|
|
279
|
+
print(_bullet(f"repository root: {target_root}"))
|
|
280
|
+
print(_bullet(f"forge workspace: {forge_root}"))
|
|
281
|
+
print(_bullet(f"skills: {forge_root / 'skills'}"))
|
|
281
282
|
print("")
|
|
282
283
|
print(_section("Start With Skills"))
|
|
283
|
-
print(_bullet("primary driver: `skills/forge-schema/SKILL.md`"))
|
|
284
|
-
print(_bullet("pre-build architecture review: `skills/forge-review/SKILL.md`"))
|
|
285
|
-
print(_bullet("pre-build security review: `skills/forge-security/SKILL.md`"))
|
|
286
|
-
print(_bullet("plan and build only after those passes: `skills/forge-build/SKILL.md`"))
|
|
284
|
+
print(_bullet("primary driver: `forge/skills/forge-schema/SKILL.md`"))
|
|
285
|
+
print(_bullet("pre-build architecture review: `forge/skills/forge-review/SKILL.md`"))
|
|
286
|
+
print(_bullet("pre-build security review: `forge/skills/forge-security/SKILL.md`"))
|
|
287
|
+
print(_bullet("plan and build only after those passes: `forge/skills/forge-build/SKILL.md`"))
|
|
287
288
|
print(_bullet("the CLI supports the active skill; it is not the main workflow", accent=ORANGE))
|
|
288
289
|
print("")
|
|
289
290
|
print(_section("Use Forge In This Order"))
|
|
290
|
-
print(
|
|
291
|
+
print(
|
|
292
|
+
_step(
|
|
293
|
+
1,
|
|
294
|
+
"Define the broad truth with `forge-schema`.",
|
|
295
|
+
"Author `forge/system.yaml`, `forge/high_level_flows/`, `forge/early_state.yaml`, and `forge/runtime.yaml` first.",
|
|
296
|
+
)
|
|
297
|
+
)
|
|
291
298
|
print(_step(2, "Split the system into development slices in `verticals/`.", "Keep each vertical thin, buildable, and tied to clear user value."))
|
|
292
|
-
print(
|
|
299
|
+
print(
|
|
300
|
+
_step(
|
|
301
|
+
3,
|
|
302
|
+
"Deepen one vertical only.",
|
|
303
|
+
"Add `forge/runtime_flows/`, `forge/data_shapes/`, `forge/persistent_shapes/`, `forge/containers/`, and `forge/deployment.yaml` as needed.",
|
|
304
|
+
)
|
|
305
|
+
)
|
|
293
306
|
print(
|
|
294
307
|
_step(
|
|
295
308
|
4,
|
|
@@ -306,15 +319,15 @@ def _print_init_summary(target_root: Path, system_name: str, system_id: str) ->
|
|
|
306
319
|
print(_bullet("capture meaningful tradeoffs in `decision_notes.md`"))
|
|
307
320
|
print("")
|
|
308
321
|
print(_section("Read Next"))
|
|
309
|
-
print(_bullet(f"`{
|
|
310
|
-
print(_bullet(f"`{
|
|
311
|
-
print(_bullet(f"`{
|
|
322
|
+
print(_bullet(f"`{forge_root / 'USING_FORGE.md'}`"))
|
|
323
|
+
print(_bullet(f"`{forge_root / 'FRAMEWORK_V3.md'}`"))
|
|
324
|
+
print(_bullet(f"`{forge_root / 'SCHEMA_REFERENCE_V3.md'}`"))
|
|
312
325
|
print("")
|
|
313
326
|
print(_section("CLI Support Workflow"))
|
|
314
327
|
print(_bullet("ask the active skill what scope it needs first", accent=ORANGE))
|
|
315
|
-
print(_bullet(f"broad context: `forge context --project-dir {
|
|
316
|
-
print(_bullet(f"vertical context: `forge context --project-dir {
|
|
317
|
-
print(_bullet(f"audit dashboard: `forge audit --project-dir {
|
|
328
|
+
print(_bullet(f"broad context: `forge context --project-dir {forge_root} --system --format md`"))
|
|
329
|
+
print(_bullet(f"vertical context: `forge context --project-dir {forge_root} --vertical <id> --format json`"))
|
|
330
|
+
print(_bullet(f"audit dashboard: `forge audit --project-dir {forge_root} --output forge-audit.html`"))
|
|
318
331
|
|
|
319
332
|
|
|
320
333
|
def _using_forge_doc() -> str:
|
|
@@ -323,14 +336,16 @@ def _using_forge_doc() -> str:
|
|
|
323
336
|
Forge works best when you move from broad architectural truth to one thin,
|
|
324
337
|
buildable vertical at a time.
|
|
325
338
|
|
|
339
|
+
The Forge-owned schema workspace lives under `forge/`.
|
|
340
|
+
|
|
326
341
|
## Start With Skills
|
|
327
342
|
|
|
328
343
|
Forge is **skills-first**. The skills are the main operating surface:
|
|
329
344
|
|
|
330
|
-
- `skills/forge-schema/SKILL.md`
|
|
331
|
-
- `skills/forge-review/SKILL.md`
|
|
332
|
-
- `skills/forge-security/SKILL.md`
|
|
333
|
-
- `skills/forge-build/SKILL.md`
|
|
345
|
+
- `forge/skills/forge-schema/SKILL.md`
|
|
346
|
+
- `forge/skills/forge-review/SKILL.md`
|
|
347
|
+
- `forge/skills/forge-security/SKILL.md`
|
|
348
|
+
- `forge/skills/forge-build/SKILL.md`
|
|
334
349
|
|
|
335
350
|
Use the CLI only to support the active skill:
|
|
336
351
|
|
|
@@ -343,32 +358,32 @@ for only the narrowest context that skill needs next.
|
|
|
343
358
|
## Use Forge In This Order
|
|
344
359
|
|
|
345
360
|
1. Define the system:
|
|
346
|
-
- `system.yaml`
|
|
347
|
-
- `high_level_flows/`
|
|
348
|
-
- `early_state.yaml`
|
|
349
|
-
- `runtime.yaml`
|
|
350
|
-
2. Derive `verticals/` once the runtime picture is stable.
|
|
361
|
+
- `forge/system.yaml`
|
|
362
|
+
- `forge/high_level_flows/`
|
|
363
|
+
- `forge/early_state.yaml`
|
|
364
|
+
- `forge/runtime.yaml`
|
|
365
|
+
2. Derive `forge/verticals/` once the runtime picture is stable.
|
|
351
366
|
3. Pick one vertical and deepen only that slice:
|
|
352
|
-
- `runtime_flows/`
|
|
353
|
-
- `data_shapes/`
|
|
354
|
-
- `persistent_shapes/`
|
|
355
|
-
- `containers/`
|
|
356
|
-
- `deployment.yaml`
|
|
367
|
+
- `forge/runtime_flows/`
|
|
368
|
+
- `forge/data_shapes/`
|
|
369
|
+
- `forge/persistent_shapes/`
|
|
370
|
+
- `forge/containers/`
|
|
371
|
+
- `forge/deployment.yaml`
|
|
357
372
|
4. Review and secure that slice before build starts.
|
|
358
373
|
5. Build and validate the approved slice before moving on.
|
|
359
374
|
|
|
360
375
|
## Core Artifacts
|
|
361
376
|
|
|
362
|
-
- `system.yaml`: purpose, boundary, actors, dependencies, and global security posture
|
|
363
|
-
- `runtime.yaml`: the real runtime containers and their relationships
|
|
364
|
-
- `early_state.yaml`: the important business things that matter before exact typing
|
|
365
|
-
- `high_level_flows/`: business and system flows
|
|
366
|
-
- `verticals/`: thin development slices derived from the system
|
|
367
|
-
- `runtime_flows/`: how a vertical moves through containers
|
|
368
|
-
- `data_shapes/`: promoted reusable payload/state shapes
|
|
369
|
-
- `persistent_shapes/`: the persisted subset of data shapes
|
|
370
|
-
- `containers/`: internal component structure for important containers
|
|
371
|
-
- `deployment.yaml`: environments, nodes, trust boundaries, and operational placement
|
|
377
|
+
- `forge/system.yaml`: purpose, boundary, actors, dependencies, and global security posture
|
|
378
|
+
- `forge/runtime.yaml`: the real runtime containers and their relationships
|
|
379
|
+
- `forge/early_state.yaml`: the important business things that matter before exact typing
|
|
380
|
+
- `forge/high_level_flows/`: business and system flows
|
|
381
|
+
- `forge/verticals/`: thin development slices derived from the system
|
|
382
|
+
- `forge/runtime_flows/`: how a vertical moves through containers
|
|
383
|
+
- `forge/data_shapes/`: promoted reusable payload/state shapes
|
|
384
|
+
- `forge/persistent_shapes/`: the persisted subset of data shapes
|
|
385
|
+
- `forge/containers/`: internal component structure for important containers
|
|
386
|
+
- `forge/deployment.yaml`: environments, nodes, trust boundaries, and operational placement
|
|
372
387
|
|
|
373
388
|
## Skill Roles
|
|
374
389
|
|
|
@@ -394,7 +409,7 @@ for only the narrowest context that skill needs next.
|
|
|
394
409
|
- Stay broad until the current layer is genuinely clear.
|
|
395
410
|
- Use `forge context` only after the active skill asks for a specific scope.
|
|
396
411
|
- Keep `forge audit` as the main artifact for human review and sign-off.
|
|
397
|
-
- Record meaningful tradeoffs and scope choices in `decision_notes.md`.
|
|
412
|
+
- Record meaningful tradeoffs and scope choices in `forge/decision_notes.md`.
|
|
398
413
|
|
|
399
414
|
## CLI Usage
|
|
400
415
|
|
|
@@ -9,14 +9,27 @@ def is_forge_root(path: Path) -> bool:
|
|
|
9
9
|
return path.is_dir() and all((path / filename).exists() for filename in REQUIRED_ROOT_FILES)
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
def _embedded_forge_root(path: Path) -> Path | None:
|
|
13
|
+
candidate = path / "forge"
|
|
14
|
+
if is_forge_root(candidate):
|
|
15
|
+
return candidate
|
|
16
|
+
return None
|
|
17
|
+
|
|
18
|
+
|
|
12
19
|
def find_project_root(start: Path | None = None) -> Path:
|
|
13
20
|
current = (start or Path.cwd()).resolve()
|
|
14
21
|
if is_forge_root(current):
|
|
15
22
|
return current
|
|
23
|
+
embedded = _embedded_forge_root(current)
|
|
24
|
+
if embedded is not None:
|
|
25
|
+
return embedded
|
|
16
26
|
for candidate in current.parents:
|
|
17
27
|
if is_forge_root(candidate):
|
|
18
28
|
return candidate
|
|
29
|
+
embedded = _embedded_forge_root(candidate)
|
|
30
|
+
if embedded is not None:
|
|
31
|
+
return embedded
|
|
19
32
|
raise FileNotFoundError(
|
|
20
|
-
"Could not find a Forge project root. Run this inside a
|
|
21
|
-
"`system.yaml` and `runtime.yaml`, or pass `--project-dir`."
|
|
33
|
+
"Could not find a Forge project root. Run this inside a Forge workspace containing "
|
|
34
|
+
"`system.yaml` and `runtime.yaml`, run it from a repository with `forge/`, or pass `--project-dir`."
|
|
22
35
|
)
|