ai-forge-cli 3.0.0__tar.gz → 3.0.2__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-3.0.0/src/ai_forge_cli.egg-info → ai_forge_cli-3.0.2}/PKG-INFO +1 -1
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/pyproject.toml +1 -1
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2/src/ai_forge_cli.egg-info}/PKG-INFO +1 -1
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/commands/init.py +56 -22
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/tests/test_context.py +14 -8
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/tests/test_crawler.py +2 -2
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/MANIFEST.in +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/README.md +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/setup.cfg +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/setup.py +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/ai_forge_cli.egg-info/SOURCES.txt +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/ai_forge_cli.egg-info/dependency_links.txt +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/ai_forge_cli.egg-info/entry_points.txt +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/ai_forge_cli.egg-info/requires.txt +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/ai_forge_cli.egg-info/top_level.txt +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/__init__.py +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/__main__.py +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/assets/audit_template.html +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/assets/forge_full_logo.drawio.svg +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/assets/forge_white_small.drawio.svg +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/commands/__init__.py +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/commands/audit.py +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/commands/base.py +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/commands/context.py +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/commands/crawl.py +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/common.py +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/crawler.py +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/forge.py +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/resources/FRAMEWORK_V4.md +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/resources/SCHEMA_REFERENCE_V4.md +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/resources/skills/forge-build/SKILL.md +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/resources/skills/forge-build/agents/openai.yaml +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/resources/skills/forge-business/SKILL.md +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/resources/skills/forge-business/agents/openai.yaml +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/resources/skills/forge-hydrate/SKILL.md +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/resources/skills/forge-hydrate/agents/openai.yaml +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/resources/skills/forge-review/SKILL.md +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/resources/skills/forge-review/agents/openai.yaml +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/resources/skills/forge-schema/SKILL.md +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/resources/skills/forge-schema/agents/openai.yaml +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/resources/skills/forge-security/SKILL.md +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/resources/skills/forge-security/agents/openai.yaml +0 -0
- {ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/yaml_io.py +0 -0
|
@@ -25,6 +25,7 @@ SKILL_SURFACES = [
|
|
|
25
25
|
".claude/skills",
|
|
26
26
|
".codex/skills",
|
|
27
27
|
".agents/skills",
|
|
28
|
+
".copilot/skills",
|
|
28
29
|
]
|
|
29
30
|
|
|
30
31
|
DOC_FILES = [
|
|
@@ -163,6 +164,7 @@ def _scaffold_repository(target_root: Path, system_name: str, system_id: str) ->
|
|
|
163
164
|
_copy_skills(forge_root)
|
|
164
165
|
_rewrite_skill_references(forge_root)
|
|
165
166
|
_create_surface_skills(target_root, forge_root)
|
|
167
|
+
_create_github_copilot_context(target_root)
|
|
166
168
|
|
|
167
169
|
|
|
168
170
|
def _copy_docs(forge_root: Path) -> None:
|
|
@@ -227,10 +229,13 @@ def _rewrite_skill_references(forge_root: Path) -> None:
|
|
|
227
229
|
for skill_name in SKILL_DIRS:
|
|
228
230
|
skill_path = forge_root / "skills" / skill_name / "SKILL.md"
|
|
229
231
|
text = skill_path.read_text(encoding="utf-8")
|
|
230
|
-
|
|
232
|
+
text = text.replace("../../SCHEMA_REFERENCE_V4.md", "forge/SCHEMA_REFERENCE_V4.md")
|
|
233
|
+
text = text.replace("../../FRAMEWORK_V4.md", "forge/FRAMEWORK_V4.md")
|
|
234
|
+
text = text.replace("../../USING_FORGE.md", "forge/USING_FORGE.md")
|
|
235
|
+
if "Read before starting:" in text and "forge/USING_FORGE.md" not in text:
|
|
231
236
|
text = text.replace(
|
|
232
237
|
"Read before starting:\n",
|
|
233
|
-
"Read before starting:\n\n-
|
|
238
|
+
"Read before starting:\n\n- `forge/USING_FORGE.md`\n",
|
|
234
239
|
1,
|
|
235
240
|
)
|
|
236
241
|
skill_path.write_text(text, encoding="utf-8")
|
|
@@ -253,30 +258,31 @@ def _create_surface_skill(surface_root: Path, forge_root: Path, skill_name: str)
|
|
|
253
258
|
target_skill.unlink()
|
|
254
259
|
else:
|
|
255
260
|
shutil.rmtree(target_skill)
|
|
256
|
-
target_skill.
|
|
261
|
+
target_skill.symlink_to(_relative_symlink_target(surface_root, source_skill), target_is_directory=True)
|
|
257
262
|
|
|
258
|
-
for child in source_skill.iterdir():
|
|
259
|
-
if child.name == "SKILL.md":
|
|
260
|
-
continue
|
|
261
|
-
target_child = target_skill / child.name
|
|
262
|
-
if target_child.exists() or target_child.is_symlink():
|
|
263
|
-
if target_child.is_symlink() or target_child.is_file():
|
|
264
|
-
target_child.unlink()
|
|
265
|
-
else:
|
|
266
|
-
shutil.rmtree(target_child)
|
|
267
|
-
target_child.symlink_to(_relative_symlink_target(target_skill, child), target_is_directory=child.is_dir())
|
|
268
263
|
|
|
269
|
-
|
|
270
|
-
|
|
264
|
+
def _create_github_copilot_context(target_root: Path) -> None:
|
|
265
|
+
github_root = target_root / ".github"
|
|
266
|
+
instructions_root = github_root / "instructions"
|
|
267
|
+
prompts_root = github_root / "prompts"
|
|
268
|
+
instructions_root.mkdir(parents=True, exist_ok=True)
|
|
269
|
+
prompts_root.mkdir(parents=True, exist_ok=True)
|
|
270
|
+
_write_text(github_root / "copilot-instructions.md", _copilot_instructions_doc())
|
|
271
|
+
_write_text(instructions_root / "forge.instructions.md", _copilot_path_instructions_doc())
|
|
272
|
+
for skill_name in SKILL_DIRS:
|
|
273
|
+
_create_symlink(
|
|
274
|
+
prompts_root / f"{skill_name}.prompt.md",
|
|
275
|
+
target_root / "forge" / "skills" / skill_name / "SKILL.md",
|
|
276
|
+
)
|
|
271
277
|
|
|
272
278
|
|
|
273
|
-
def
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
)
|
|
279
|
+
def _create_symlink(link_path: Path, destination: Path) -> None:
|
|
280
|
+
if link_path.exists() or link_path.is_symlink():
|
|
281
|
+
if link_path.is_symlink() or link_path.is_file():
|
|
282
|
+
link_path.unlink()
|
|
283
|
+
else:
|
|
284
|
+
shutil.rmtree(link_path)
|
|
285
|
+
link_path.symlink_to(_relative_symlink_target(link_path.parent, destination), target_is_directory=destination.is_dir())
|
|
280
286
|
|
|
281
287
|
|
|
282
288
|
def _relative_symlink_target(link_parent: Path, destination: Path) -> Path:
|
|
@@ -309,6 +315,34 @@ def _scaffold_gitignore() -> str:
|
|
|
309
315
|
)
|
|
310
316
|
|
|
311
317
|
|
|
318
|
+
def _copilot_instructions_doc() -> str:
|
|
319
|
+
return """# Forge Instructions
|
|
320
|
+
|
|
321
|
+
This repository uses Forge V4. Start with `forge/USING_FORGE.md`, then use the
|
|
322
|
+
skills in `forge/skills` in this order:
|
|
323
|
+
|
|
324
|
+
1. `forge-business`
|
|
325
|
+
2. `forge-schema`
|
|
326
|
+
3. `forge-review`
|
|
327
|
+
4. `forge-security`
|
|
328
|
+
5. `forge-build`
|
|
329
|
+
|
|
330
|
+
Treat `forge/skills` as the canonical skill source. Agent-specific skill
|
|
331
|
+
surfaces are symlinked back to that directory.
|
|
332
|
+
"""
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def _copilot_path_instructions_doc() -> str:
|
|
336
|
+
return """---
|
|
337
|
+
applyTo: "**"
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
Use the Forge V4 workflow for repository work. Read `forge/USING_FORGE.md`
|
|
341
|
+
before implementation, and prefer the relevant skill in `forge/skills` for the
|
|
342
|
+
current task.
|
|
343
|
+
"""
|
|
344
|
+
|
|
345
|
+
|
|
312
346
|
def _print_init_summary(target_root: Path, system_name: str, system_id: str) -> None:
|
|
313
347
|
forge_root = target_root / "forge"
|
|
314
348
|
print(_banner("FORGE INITIALIZED"))
|
|
@@ -117,20 +117,26 @@ def test_init_scaffolds_traversable_repo(tmp_path: Path, capsys) -> None:
|
|
|
117
117
|
assert "*.egg-info/" in (root / ".gitignore").read_text(encoding="utf-8")
|
|
118
118
|
codex_skill = root / ".codex" / "skills" / "forge-build"
|
|
119
119
|
assert codex_skill.is_dir()
|
|
120
|
-
assert
|
|
120
|
+
assert codex_skill.is_symlink()
|
|
121
|
+
assert codex_skill.resolve() == forge_root / "skills" / "forge-build"
|
|
121
122
|
assert (codex_skill / "SKILL.md").exists()
|
|
122
123
|
assert (codex_skill / "agents" / "openai.yaml").exists()
|
|
123
124
|
assert not (codex_skill / "coding_agent_skills_reference").exists()
|
|
124
125
|
surfaced_skill = (codex_skill / "SKILL.md").read_text(encoding="utf-8")
|
|
125
|
-
assert "
|
|
126
|
+
assert "forge/USING_FORGE.md" in surfaced_skill
|
|
126
127
|
assert "../forge-schema/SKILL.md" in surfaced_skill
|
|
127
|
-
assert (root / ".claude" / "skills" / "forge-business"
|
|
128
|
-
assert (root / ".claude" / "skills" / "forge-schema"
|
|
129
|
-
assert (root / ".claude" / "skills" / "forge-hydrate"
|
|
130
|
-
assert (root / ".agents" / "skills" / "forge-review"
|
|
128
|
+
assert (root / ".claude" / "skills" / "forge-business").is_symlink()
|
|
129
|
+
assert (root / ".claude" / "skills" / "forge-schema").is_symlink()
|
|
130
|
+
assert (root / ".claude" / "skills" / "forge-hydrate").is_symlink()
|
|
131
|
+
assert (root / ".agents" / "skills" / "forge-review").is_symlink()
|
|
132
|
+
assert (root / ".copilot" / "skills" / "forge-security").is_symlink()
|
|
133
|
+
assert (root / ".github" / "copilot-instructions.md").exists()
|
|
134
|
+
assert (root / ".github" / "instructions" / "forge.instructions.md").exists()
|
|
135
|
+
assert (root / ".github" / "prompts" / "forge-build.prompt.md").is_symlink()
|
|
136
|
+
assert (root / ".github" / "prompts" / "forge-build.prompt.md").resolve() == forge_root / "skills" / "forge-build" / "SKILL.md"
|
|
131
137
|
rewritten_skill = (forge_root / "skills" / "forge-schema" / "SKILL.md").read_text(encoding="utf-8")
|
|
132
|
-
assert "
|
|
133
|
-
assert "
|
|
138
|
+
assert "forge/SCHEMA_REFERENCE_V4.md" in rewritten_skill
|
|
139
|
+
assert "forge/USING_FORGE.md" in rewritten_skill
|
|
134
140
|
usage_doc = (forge_root / "USING_FORGE.md").read_text(encoding="utf-8")
|
|
135
141
|
assert "Forge is **skills-first**." in usage_doc
|
|
136
142
|
assert "Use Forge In This Order" in usage_doc
|
|
@@ -436,8 +436,8 @@ def test_init_scaffolds_v4_project(tmp_path: Path, capsys) -> None:
|
|
|
436
436
|
assert (forge_root / "skills" / "forge-schema" / "SKILL.md").exists()
|
|
437
437
|
assert (forge_root / "skills" / "forge-hydrate" / "SKILL.md").exists()
|
|
438
438
|
skill_text = (forge_root / "skills" / "forge-schema" / "SKILL.md").read_text(encoding="utf-8")
|
|
439
|
-
assert "
|
|
440
|
-
assert "
|
|
439
|
+
assert "forge/FRAMEWORK_V4.md" in skill_text
|
|
440
|
+
assert "forge/SCHEMA_REFERENCE_V4.md" in skill_text
|
|
441
441
|
capsys.readouterr()
|
|
442
442
|
assert main(["crawl", "--project-dir", str(root)]) == 0
|
|
443
443
|
payload = json.loads(capsys.readouterr().out)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/resources/skills/forge-build/agents/openai.yaml
RENAMED
|
File without changes
|
|
File without changes
|
{ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/resources/skills/forge-business/agents/openai.yaml
RENAMED
|
File without changes
|
|
File without changes
|
{ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/resources/skills/forge-hydrate/agents/openai.yaml
RENAMED
|
File without changes
|
|
File without changes
|
{ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/resources/skills/forge-review/agents/openai.yaml
RENAMED
|
File without changes
|
|
File without changes
|
{ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/resources/skills/forge-schema/agents/openai.yaml
RENAMED
|
File without changes
|
|
File without changes
|
{ai_forge_cli-3.0.0 → ai_forge_cli-3.0.2}/src/cli/resources/skills/forge-security/agents/openai.yaml
RENAMED
|
File without changes
|
|
File without changes
|