@tyroneross/build-loop 0.36.0 → 0.43.0
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.
- package/.agents/plugins/marketplace.json +2 -2
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor/rules/build-loop-surface.mdc +12 -11
- package/.cursor/rules/skill-index.mdc +33 -0
- package/AGENTS.md +213 -34
- package/README.md +99 -31
- package/agents/advisor.md +4 -4
- package/agents/alignment-checker.md +2 -2
- package/agents/architecture-scout.md +4 -4
- package/agents/build-orchestrator.md +38 -36
- package/agents/database-assessor.md +11 -5
- package/agents/design-contract-specialist.md +8 -8
- package/agents/fact-checker.md +13 -3
- package/agents/fix-critique.md +2 -2
- package/agents/independent-auditor.md +60 -7
- package/agents/leak-scanner.md +82 -0
- package/agents/overfitting-reviewer.md +2 -2
- package/agents/plan-critic.md +1 -1
- package/agents/promotion-reviewer.md +5 -5
- package/agents/retrospective-synthesizer.md +138 -35
- package/agents/scope-auditor.md +82 -11
- package/agents/security-reviewer.md +56 -2
- package/agents/self-improvement-architect.md +17 -3
- package/agents/transcript-pattern-miner.md +5 -5
- package/agents/ui-validator.md +1 -1
- package/bin/build-loop-debugger.js +143 -0
- package/bin/build-loop-install.js +1 -4
- package/bin/build-loop-load-probe.js +345 -0
- package/codex-skills/build-loop/SKILL.md +28 -6
- package/commands/feedback.md +37 -0
- package/dist/src/interactive-verifier.d.ts +1 -14
- package/dist/src/interactive-verifier.d.ts.map +1 -1
- package/dist/src/interactive-verifier.js +6 -113
- package/dist/src/interactive-verifier.js.map +1 -1
- package/dist/src/quality.d.ts +5 -0
- package/dist/src/quality.d.ts.map +1 -0
- package/dist/src/quality.js +81 -0
- package/dist/src/quality.js.map +1 -0
- package/dist/src/storage.d.ts.map +1 -1
- package/dist/src/storage.js +37 -3
- package/dist/src/storage.js.map +1 -1
- package/docs/agent-surface-policy.md +35 -31
- package/docs/memory-setup.md +19 -0
- package/hooks/git/pre-push +65 -4
- package/hooks/hooks.json +95 -38
- package/hooks/pre-commit +20 -1
- package/hooks/pre-edit-rally-point.sh +10 -3
- package/hooks/session-start-codex-hook-trust.sh +30 -0
- package/hooks/session-start-git-hooks.sh +3 -1
- package/hooks/session-start-rally-point.sh +52 -4
- package/hooks/session-start-worktree-gc.sh +47 -94
- package/hooks/stop-transcript-sweep.sh +173 -0
- package/hooks/test_closeout.sh +14 -2
- package/package.json +8 -7
- package/scripts/README.md +1 -1
- package/scripts/_paths.py +65 -0
- package/scripts/groundwork_exchange.py +1012 -0
- package/scripts/install_memory.py +33 -1
- package/scripts/lessons_index/ingest.py +13 -2
- package/scripts/lessons_index/query.py +36 -13
- package/scripts/memory_context/__init__.py +108 -14
- package/scripts/memory_graph/__init__.py +5 -1
- package/scripts/project_resolver.py +42 -36
- package/scripts/sync_plugin_cache.py +37 -2
- package/skills/agent-rally-point/SKILL.md +46 -0
- package/skills/api-registry-bridge/SKILL.md +1 -1
- package/skills/architecture/dead/SKILL.md +1 -1
- package/skills/architecture/impact/SKILL.md +1 -1
- package/skills/architecture/review/SKILL.md +1 -1
- package/skills/architecture/rules/SKILL.md +3 -3
- package/skills/architecture/scan/SKILL.md +1 -1
- package/skills/architecture/trace/SKILL.md +1 -1
- package/skills/attribution-standard/SKILL.md +6 -6
- package/skills/auto-decision-capture/SKILL.md +31 -2
- package/skills/auto-finding-capture/SKILL.md +28 -1
- package/skills/build-loop/SKILL.md +131 -23
- package/skills/build-loop/fallbacks.md +16 -21
- package/skills/build-loop/phases/ui-validation.md +2 -2
- package/skills/build-loop/references/advisor-dispatch-ladder.md +1 -1
- package/skills/build-loop/references/apple-native-planning.md +1 -1
- package/skills/build-loop/references/autonomous-and-per-commit-modes.md +11 -5
- package/skills/build-loop/references/autonomy-dashboard.md +115 -0
- package/skills/build-loop/references/capability-routing.md +24 -2
- package/skills/build-loop/references/coordination.md +24 -6
- package/skills/build-loop/references/experiment-results-template.md +15 -3
- package/skills/build-loop/references/leadership.md +1 -1
- package/skills/build-loop/references/memory.md +14 -3
- package/skills/build-loop/references/modular-systems-pack.md +8 -0
- package/skills/build-loop/references/output-style.md +86 -0
- package/skills/build-loop/references/phase-1-assess.md +102 -2
- package/skills/build-loop/references/phase-2-plan.md +9 -1
- package/skills/build-loop/references/phase-3-execute.md +5 -2
- package/skills/build-loop/references/phase-4-review.md +85 -8
- package/skills/build-loop/references/phase-5-iterate.md +76 -8
- package/skills/build-loop/references/phase-6-learn.md +10 -17
- package/skills/build-loop/references/privileged-request-broker.md +254 -0
- package/skills/build-loop/references/resource-aware-execution.md +183 -0
- package/skills/build-loop/references/self-recursive-dev.md +2 -2
- package/skills/build-loop/references/status-output-format.md +207 -0
- package/skills/build-loop/references/verify-dispatch.md +56 -2
- package/skills/building-with-deepagents/SKILL.md +1 -1
- package/skills/claim-scope/SKILL.md +185 -0
- package/skills/color-engine/SKILL.md +103 -0
- package/skills/color-engine/_core.py +464 -0
- package/skills/color-engine/color_engine.py +175 -0
- package/skills/cost-rca/SKILL.md +61 -0
- package/skills/data-plane-worktrees/SKILL.md +139 -0
- package/skills/data-plane-worktrees/agents/openai.yaml +4 -0
- package/skills/database-practice/SKILL.md +200 -0
- package/skills/database-practice/references/diagnostic-queries.sql +126 -0
- package/skills/database-practice/references/vector-and-graph-tuning.md +208 -0
- package/skills/database-practice/scripts/db_table_map.py +1244 -0
- package/skills/database-practice/scripts/test_db_table_map.py +514 -0
- package/skills/debug-loop/SKILL.md +36 -6
- package/skills/debugging-memory/SKILL.md +32 -430
- package/skills/debugging-memory/references/pattern-extraction.md +4 -4
- package/skills/debugging-memory/references/search.md +32 -120
- package/skills/debugging-memory/references/store.md +32 -126
- package/skills/debugging-memory/references/subagent-integration.md +1 -1
- package/skills/decision-queue/SKILL.md +251 -0
- package/skills/decision-queue/assets/template.html +1242 -0
- package/skills/decision-queue/references/example-large-queue-batching.md +164 -0
- package/skills/decision-queue/scripts/regen_template_constants.py +160 -0
- package/skills/defenseclaw-bridge/SKILL.md +2 -2
- package/skills/defenseclaw-bridge/references/dc-config-mapping.md +2 -9
- package/skills/drain-proposals/SKILL.md +53 -0
- package/skills/focused-loop-builder/SKILL.md +31 -0
- package/skills/focused-loop-builder/references/spec-format.md +27 -0
- package/skills/handoff/SKILL.md +169 -8
- package/skills/ibr-bridge/SKILL.md +4 -1
- package/skills/knowledge/SKILL.md +26 -14
- package/skills/knowledge/references/review-mode.md +2 -3
- package/skills/knowledge/templates/madr-minimal.md +1 -1
- package/skills/mcp-builder/SKILL.md +1 -1
- package/skills/model-bakeoff/SKILL.md +48 -10
- package/skills/model-tiering/SKILL.md +92 -31
- package/skills/native-ax-driver/SKILL.md +38 -5
- package/skills/native-ax-driver/scripts/native_driver.py +278 -22
- package/skills/native-ax-driver/scripts/test_native_driver.py +227 -0
- package/skills/optimize/SKILL.md +1 -1
- package/skills/plugin-builder/SKILL.md +48 -1
- package/skills/plugin-builder/references/build-loop-phase-guidance.md +3 -4
- package/skills/plugin-builder/references/distribution.md +13 -2
- package/skills/plugin-builder/references/plugin-hygiene-lessons.md +2 -2
- package/skills/plugin-tests/SKILL.md +2 -2
- package/skills/recursive-retrospective/SKILL.md +1 -1
- package/skills/repo-closeout/SKILL.md +17 -0
- package/skills/repo-closeout/agents/openai.yaml +4 -0
- package/skills/repo-maintenance/SKILL.md +179 -0
- package/skills/repo-maintenance/agents/openai.yaml +4 -0
- package/skills/repo-maintenance/references/pre-public-hygiene.md +134 -0
- package/skills/repo-maintenance/references/repository-taxonomy.md +161 -0
- package/skills/repo-maintenance/references/safety-protocol.md +106 -0
- package/skills/repo-maintenance/references/stack-profiles.md +138 -0
- package/skills/repo-maintenance/scripts/audit_repo_maintenance.py +1198 -0
- package/skills/repo-maintenance/scripts/test_audit_repo_maintenance.py +506 -0
- package/skills/repository-intelligence/SKILL.md +189 -0
- package/skills/repository-intelligence/agents/openai.yaml +4 -0
- package/skills/repository-intelligence/references/assessment-rubric.md +88 -0
- package/skills/repository-intelligence/scripts/repository_inventory.py +347 -0
- package/skills/research/SKILL.md +12 -2
- package/skills/root-cause-analysis/SKILL.md +1 -1
- package/skills/runtime-parity-verification/SKILL.md +36 -1
- package/skills/security-methodology/SKILL.md +23 -10
- package/skills/security-methodology/references/agentic-handoff-templates.md +220 -0
- package/skills/security-methodology/references/cross-source-matrix.md +1 -1
- package/skills/security-methodology/references/owasp-agentic-top-10.md +1 -1
- package/skills/security-scan/SKILL.md +55 -15
- package/skills/self-improve/SKILL.md +70 -50
- package/skills/silent-assumptions/SKILL.md +341 -0
- package/skills/silent-assumptions/references/elicitation-detectors.md +342 -0
- package/skills/spec-writing/SKILL.md +128 -24
- package/skills/spec-writing/scripts/check_checklist.py +114 -15
- package/skills/ui-design/SKILL.md +6 -4
- package/skills/ui-design/references/color-engine.md +132 -0
- package/skills/ui-design/references/design-preferences-from-owned-apps.md +8 -8
- package/skills/ui-design/references/ui-guidance-sources.md +1 -1
- package/skills/ui-design/references/universal-design-principles.alt.md +2 -2
- package/plugin-artifacts/codex/.codex-plugin/plugin.json +0 -41
- package/plugin-artifacts/codex/AGENTS.md +0 -560
- package/plugin-artifacts/codex/BUILD-ARTIFACT.md +0 -5
- package/plugin-artifacts/codex/LICENSE +0 -202
- package/plugin-artifacts/codex/README.md +0 -313
- package/plugin-artifacts/codex/assets/build-loop-plugin-icon.png +0 -0
- package/plugin-artifacts/codex/docs/agent-surface-policy.md +0 -63
- package/plugin-artifacts/codex/references/advisor-dispatch-ladder.md +0 -62
- package/plugin-artifacts/codex/references/agent-role-taxonomy.md +0 -135
- package/plugin-artifacts/codex/references/autonomous-and-per-commit-modes.md +0 -161
- package/plugin-artifacts/codex/references/autonomy-config.md +0 -231
- package/plugin-artifacts/codex/references/backlog-system.md +0 -285
- package/plugin-artifacts/codex/references/capability-routing.md +0 -231
- package/plugin-artifacts/codex/references/codex-subagents.md +0 -106
- package/plugin-artifacts/codex/references/coordination-file-template.md +0 -181
- package/plugin-artifacts/codex/references/coordination-rules.md +0 -552
- package/plugin-artifacts/codex/references/dogfood-reload-checkpoint.md +0 -112
- package/plugin-artifacts/codex/references/halt-and-ask-protocol.md +0 -102
- package/plugin-artifacts/codex/references/implementer-envelope-schema.md +0 -302
- package/plugin-artifacts/codex/references/intent-capability-pack.md +0 -257
- package/plugin-artifacts/codex/references/intent-exploration-prompts.md +0 -96
- package/plugin-artifacts/codex/references/leadership.md +0 -72
- package/plugin-artifacts/codex/references/memory-systems.md +0 -261
- package/plugin-artifacts/codex/references/memory.md +0 -313
- package/plugin-artifacts/codex/references/model-tier-mapping.md +0 -296
- package/plugin-artifacts/codex/references/modular-systems-pack.md +0 -96
- package/plugin-artifacts/codex/references/phase-1-assess.md +0 -249
- package/plugin-artifacts/codex/references/phase-2-plan.md +0 -86
- package/plugin-artifacts/codex/references/phase-3-execute.md +0 -49
- package/plugin-artifacts/codex/references/phase-4-review.md +0 -341
- package/plugin-artifacts/codex/references/phase-5-iterate.md +0 -72
- package/plugin-artifacts/codex/references/phase-6-learn.md +0 -58
- package/plugin-artifacts/codex/references/recent-design-structures.md +0 -274
- package/plugin-artifacts/codex/references/research-trigger-policy.md +0 -140
- package/plugin-artifacts/codex/references/runtime-smoke-triggers.md +0 -42
- package/plugin-artifacts/codex/references/self-review.md +0 -234
- package/plugin-artifacts/codex/references/single-writer-commit-protocol.md +0 -90
- package/plugin-artifacts/codex/references/task-capture-policy.md +0 -68
- package/plugin-artifacts/codex/references/ui-io-contract.md +0 -116
- package/plugin-artifacts/codex/references/ui-spotcheck-protocol.md +0 -65
- package/plugin-artifacts/codex/references/verify-dispatch.md +0 -85
- package/plugin-artifacts/codex/skills/build-loop/SKILL.md +0 -381
- package/plugin-artifacts/codex/skills/build-loop/detect-plugins.mjs +0 -82
- package/plugin-artifacts/codex/skills/build-loop/eval-guide.md +0 -65
- package/plugin-artifacts/codex/skills/build-loop/fallbacks.md +0 -549
- package/plugin-artifacts/codex/skills/build-loop/phases/fact-check.md +0 -42
- package/plugin-artifacts/codex/skills/build-loop/phases/ui-validation.md +0 -267
- package/plugin-artifacts/codex/skills/build-loop/references/advisor-dispatch-ladder.md +0 -62
- package/plugin-artifacts/codex/skills/build-loop/references/apple-native-planning.md +0 -439
- package/plugin-artifacts/codex/skills/build-loop/references/autonomous-and-per-commit-modes.md +0 -161
- package/plugin-artifacts/codex/skills/build-loop/references/capability-routing.md +0 -231
- package/plugin-artifacts/codex/skills/build-loop/references/codex-subagents.md +0 -106
- package/plugin-artifacts/codex/skills/build-loop/references/coordination.md +0 -161
- package/plugin-artifacts/codex/skills/build-loop/references/correction-aware-capture.md +0 -177
- package/plugin-artifacts/codex/skills/build-loop/references/experiment-results-template.md +0 -101
- package/plugin-artifacts/codex/skills/build-loop/references/independent-auditor.md +0 -72
- package/plugin-artifacts/codex/skills/build-loop/references/intent-capability-pack.md +0 -257
- package/plugin-artifacts/codex/skills/build-loop/references/intent-exploration-prompts.md +0 -96
- package/plugin-artifacts/codex/skills/build-loop/references/leadership.md +0 -72
- package/plugin-artifacts/codex/skills/build-loop/references/memory.md +0 -313
- package/plugin-artifacts/codex/skills/build-loop/references/modular-systems-pack.md +0 -96
- package/plugin-artifacts/codex/skills/build-loop/references/output-style.md +0 -222
- package/plugin-artifacts/codex/skills/build-loop/references/pay-it-forward-arch.md +0 -98
- package/plugin-artifacts/codex/skills/build-loop/references/phase-1-assess.md +0 -249
- package/plugin-artifacts/codex/skills/build-loop/references/phase-2-plan.md +0 -86
- package/plugin-artifacts/codex/skills/build-loop/references/phase-3-execute.md +0 -49
- package/plugin-artifacts/codex/skills/build-loop/references/phase-4-review.md +0 -341
- package/plugin-artifacts/codex/skills/build-loop/references/phase-5-iterate.md +0 -72
- package/plugin-artifacts/codex/skills/build-loop/references/phase-6-learn.md +0 -58
- package/plugin-artifacts/codex/skills/build-loop/references/recent-design-structures.md +0 -274
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/ASSESSMENT.md +0 -85
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/STANDALONE_TEST_RUN.md +0 -149
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/01-simple-bugfix.md +0 -32
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/02-ui-build-with-iteration.md +0 -48
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/03-multi-failure-escalation.md +0 -60
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/04-ui-build-ibr-absent.md +0 -51
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/05-refactor-navgator-absent.md +0 -71
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/06-recurring-bug-debugger-absent.md +0 -52
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/trace-comparison.md +0 -202
- package/plugin-artifacts/codex/skills/build-loop/references/self-recursive-dev.md +0 -77
- package/plugin-artifacts/codex/skills/build-loop/references/self-review.md +0 -234
- package/plugin-artifacts/codex/skills/build-loop/references/ui-io-contract.md +0 -116
- package/plugin-artifacts/codex/skills/build-loop/references/verify-dispatch.md +0 -85
- package/plugin-artifacts/codex/skills/build-loop/scanners/audit-design-rules.mjs +0 -476
- package/plugin-artifacts/codex/skills/build-loop/scanners/require-visual-evidence.mjs +0 -239
- package/plugin-artifacts/codex/skills/build-loop/templates/backlog-item.md +0 -35
- package/plugin-artifacts/codex/skills/build-loop/templates/codex-worker-prompt.md +0 -100
- package/plugin-artifacts/codex/skills/build-loop/templates/ui-subagent-prompt.md +0 -179
- package/plugin-artifacts/codex/skills/build-loop/templates/ux-fix-plan.md +0 -40
- package/scripts/build_codex_plugin_artifact.py +0 -321
|
@@ -1,321 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com>
|
|
3
|
-
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
"""Build the slim Codex plugin artifact.
|
|
5
|
-
|
|
6
|
-
The source repo keeps Claude's full internal skill tree at ``skills/``. Codex
|
|
7
|
-
auto-discovers root ``skills/*/SKILL.md`` entries, so the Codex marketplace must
|
|
8
|
-
install from an artifact that exposes exactly one public skill.
|
|
9
|
-
"""
|
|
10
|
-
from __future__ import annotations
|
|
11
|
-
|
|
12
|
-
import argparse
|
|
13
|
-
import filecmp
|
|
14
|
-
import json
|
|
15
|
-
import os
|
|
16
|
-
import re
|
|
17
|
-
import shutil
|
|
18
|
-
import tempfile
|
|
19
|
-
from pathlib import Path
|
|
20
|
-
from typing import Iterable
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
DEFAULT_TARGET = Path("plugin-artifacts/codex")
|
|
24
|
-
IGNORED_NAMES = {".DS_Store", "__pycache__", ".pytest_cache"}
|
|
25
|
-
IGNORED_SUFFIXES = {".pyc"}
|
|
26
|
-
TOP_LEVEL_FILES = ("AGENTS.md", "README.md", "LICENSE")
|
|
27
|
-
ASSET_FILES = (Path("assets") / "build-loop-plugin-icon.png",)
|
|
28
|
-
|
|
29
|
-
# Bundle markdown points readers at ``references/<file>.md`` (root-relative).
|
|
30
|
-
# The Claude source resolves that logical namespace across the repo's top-level
|
|
31
|
-
# ``references/`` plus each skill's own ``references/``. The slim Codex bundle
|
|
32
|
-
# ships only the ``build-loop`` skill, so those pointers dangle unless we mirror
|
|
33
|
-
# every cited reference into ONE top-level ``references/`` dir at the bundle
|
|
34
|
-
# root — the natural resolution point for both AGENTS.md (at root) and any
|
|
35
|
-
# deeper file an LLM reads. Search order resolves drift deterministically: the
|
|
36
|
-
# skill's own copy wins (it's the one already shipped in the skill tree), then
|
|
37
|
-
# the repo root, then the ui-design skill.
|
|
38
|
-
REFERENCE_SOURCE_DIRS = (
|
|
39
|
-
Path("skills") / "build-loop" / "references",
|
|
40
|
-
Path("references"),
|
|
41
|
-
Path("skills") / "ui-design" / "references",
|
|
42
|
-
)
|
|
43
|
-
# A bare ``references/X.md`` pointer. Anchored to a path boundary so we don't
|
|
44
|
-
# match foreign-skill prose like ``build-loop:deepagents`` references — those
|
|
45
|
-
# are always written with the skill name in front (``The skill's
|
|
46
|
-
# `references/anti-patterns.md```) and resolve inside that other skill, which
|
|
47
|
-
# the slim bundle does not ship.
|
|
48
|
-
_REFERENCE_POINTER_RE = re.compile(r"(?:^|[\s`(\[])references/([A-Za-z0-9_.-]+\.md)")
|
|
49
|
-
# Pointers that name another skill's references dir in prose, not a build-loop
|
|
50
|
-
# bundle file. They have no build-loop source and must not fail the check.
|
|
51
|
-
FOREIGN_SKILL_REFERENCES = frozenset(
|
|
52
|
-
{
|
|
53
|
-
"anti-patterns.md", # build-loop:building-with-deepagents
|
|
54
|
-
"stack-templates.md", # build-loop:logging-tracer
|
|
55
|
-
"ios-notification-alarm-playbook.md", # build-loop:debugging-memory
|
|
56
|
-
}
|
|
57
|
-
)
|
|
58
|
-
# Pre-existing, deliberate forward-reference placeholders in the source tree
|
|
59
|
-
# (marked TBD in prose). They have no file anywhere — in the Claude tree either.
|
|
60
|
-
# Not codex-introduced; fixing them is out of scope for the artifact builder, so
|
|
61
|
-
# they are tolerated rather than blocking every bundle build. Keep this list
|
|
62
|
-
# tight: a NEW unresolvable pointer on the primary surface must still fail.
|
|
63
|
-
KNOWN_TBD_REFERENCES = frozenset(
|
|
64
|
-
{
|
|
65
|
-
"brief-filters.md", # references/implementer-envelope-schema.md: "(TBD)"
|
|
66
|
-
}
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def cited_reference_basenames(*roots: Path) -> set[str]:
|
|
71
|
-
"""Every bare ``references/<file>.md`` pointer across the given markdown roots."""
|
|
72
|
-
cited: set[str] = set()
|
|
73
|
-
for root in roots:
|
|
74
|
-
for md in root.rglob("*.md"):
|
|
75
|
-
cited.update(
|
|
76
|
-
_REFERENCE_POINTER_RE.findall(
|
|
77
|
-
md.read_text(encoding="utf-8", errors="ignore")
|
|
78
|
-
)
|
|
79
|
-
)
|
|
80
|
-
return cited
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def resolve_reference_source(source: Path, basename: str) -> Path | None:
|
|
84
|
-
"""Locate a cited reference file in the build-loop source search paths."""
|
|
85
|
-
for rel_dir in REFERENCE_SOURCE_DIRS:
|
|
86
|
-
candidate = source / rel_dir / basename
|
|
87
|
-
if candidate.is_file():
|
|
88
|
-
return candidate
|
|
89
|
-
return None
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def mirror_references(source: Path, bundle_root: Path) -> None:
|
|
93
|
-
"""Copy the transitive closure of cited references into ``<bundle>/references/``.
|
|
94
|
-
|
|
95
|
-
Iterates to a fixpoint: a mirrored reference file may itself cite further
|
|
96
|
-
``references/X.md``, so re-scan after each copy until no new resolvable
|
|
97
|
-
pointer appears. Makes every root-relative ``references/X.md`` pointer in the
|
|
98
|
-
bundle resolve at the bundle root. Foreign-skill and known-TBD pointers are
|
|
99
|
-
skipped (no build-loop source); a genuinely unexpected unresolvable pointer
|
|
100
|
-
is left for ``check_reference_pointers`` to adjudicate by surface.
|
|
101
|
-
"""
|
|
102
|
-
out_dir = bundle_root / "references"
|
|
103
|
-
copied: set[str] = set()
|
|
104
|
-
while True:
|
|
105
|
-
cited = cited_reference_basenames(bundle_root)
|
|
106
|
-
new_resolvable = False
|
|
107
|
-
for basename in sorted(cited - copied):
|
|
108
|
-
copied.add(basename)
|
|
109
|
-
if basename in FOREIGN_SKILL_REFERENCES or basename in KNOWN_TBD_REFERENCES:
|
|
110
|
-
continue
|
|
111
|
-
src_file = resolve_reference_source(source, basename)
|
|
112
|
-
if src_file is not None:
|
|
113
|
-
copy_file(src_file, out_dir / basename)
|
|
114
|
-
new_resolvable = True
|
|
115
|
-
if not new_resolvable:
|
|
116
|
-
break
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
def check_reference_pointers(bundle_root: Path) -> None:
|
|
120
|
-
"""Assert every ``references/X.md`` pointer on the bundle's PRIMARY surface resolves.
|
|
121
|
-
|
|
122
|
-
Primary surface = the files a Codex user actually lands on: top-level
|
|
123
|
-
AGENTS.md / README.md and the whole ``skills/build-loop`` tree. Resolution
|
|
124
|
-
target is the mirrored top-level ``<bundle>/references/``. Foreign-skill and
|
|
125
|
-
known-TBD pointers are allowlisted. A dangling primary-surface pointer is a
|
|
126
|
-
real regression and fails the build. Pointers that appear ONLY inside
|
|
127
|
-
transitively-mirrored reference files (often forward TBDs) are tolerated —
|
|
128
|
-
fixing unrelated source dead-links is not the artifact builder's job.
|
|
129
|
-
"""
|
|
130
|
-
refs_dir = bundle_root / "references"
|
|
131
|
-
surface_roots = [bundle_root / "skills" / "build-loop"]
|
|
132
|
-
surface_roots += [
|
|
133
|
-
bundle_root / name for name in ("AGENTS.md", "README.md") if (bundle_root / name).is_file()
|
|
134
|
-
]
|
|
135
|
-
# rglob on a file path yields nothing; scan top-level files explicitly.
|
|
136
|
-
cited: set[str] = set()
|
|
137
|
-
for root in surface_roots:
|
|
138
|
-
if root.is_dir():
|
|
139
|
-
cited |= cited_reference_basenames(root)
|
|
140
|
-
elif root.is_file():
|
|
141
|
-
cited |= set(
|
|
142
|
-
_REFERENCE_POINTER_RE.findall(root.read_text(encoding="utf-8", errors="ignore"))
|
|
143
|
-
)
|
|
144
|
-
dangling = sorted(
|
|
145
|
-
b
|
|
146
|
-
for b in cited
|
|
147
|
-
if b not in FOREIGN_SKILL_REFERENCES
|
|
148
|
-
and b not in KNOWN_TBD_REFERENCES
|
|
149
|
-
and not (refs_dir / b).is_file()
|
|
150
|
-
)
|
|
151
|
-
if dangling:
|
|
152
|
-
raise ArtifactError(
|
|
153
|
-
"dangling reference pointers on the primary surface (no file at "
|
|
154
|
-
"bundle references/): " + ", ".join(dangling)
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
class ArtifactError(RuntimeError):
|
|
159
|
-
pass
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
def ignore_generated(_dir: str, names: list[str]) -> set[str]:
|
|
163
|
-
ignored = set()
|
|
164
|
-
for name in names:
|
|
165
|
-
if name in IGNORED_NAMES:
|
|
166
|
-
ignored.add(name)
|
|
167
|
-
continue
|
|
168
|
-
if any(name.endswith(suffix) for suffix in IGNORED_SUFFIXES):
|
|
169
|
-
ignored.add(name)
|
|
170
|
-
return ignored
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
def copy_file(source: Path, target: Path) -> None:
|
|
174
|
-
if not source.is_file():
|
|
175
|
-
raise ArtifactError(f"missing required file: {source}")
|
|
176
|
-
target.parent.mkdir(parents=True, exist_ok=True)
|
|
177
|
-
shutil.copy2(source, target)
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
def copy_tree(source: Path, target: Path) -> None:
|
|
181
|
-
if not source.is_dir():
|
|
182
|
-
raise ArtifactError(f"missing required directory: {source}")
|
|
183
|
-
shutil.copytree(source, target, ignore=ignore_generated)
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
def write_codex_manifest(source: Path, target: Path) -> None:
|
|
187
|
-
manifest_path = source / ".codex-plugin" / "plugin.json"
|
|
188
|
-
if not manifest_path.is_file():
|
|
189
|
-
raise ArtifactError(f"missing required file: {manifest_path}")
|
|
190
|
-
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
|
|
191
|
-
manifest["skills"] = "./skills"
|
|
192
|
-
target.parent.mkdir(parents=True, exist_ok=True)
|
|
193
|
-
target.write_text(json.dumps(manifest, indent=2) + "\n", encoding="utf-8")
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
def write_notice(target: Path) -> None:
|
|
197
|
-
target.write_text(
|
|
198
|
-
"\n".join(
|
|
199
|
-
[
|
|
200
|
-
"# Codex Build Loop Artifact",
|
|
201
|
-
"",
|
|
202
|
-
"Generated by `python3 scripts/build_codex_plugin_artifact.py`.",
|
|
203
|
-
"This artifact is the Codex marketplace install surface.",
|
|
204
|
-
"It exposes exactly one public skill: `build-loop`.",
|
|
205
|
-
"",
|
|
206
|
-
]
|
|
207
|
-
),
|
|
208
|
-
encoding="utf-8",
|
|
209
|
-
)
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
def skill_files(root: Path) -> list[Path]:
|
|
213
|
-
return sorted(root.rglob("SKILL.md"))
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
def validate_artifact(target: Path) -> None:
|
|
217
|
-
manifest_path = target / ".codex-plugin" / "plugin.json"
|
|
218
|
-
skills_root = target / "skills"
|
|
219
|
-
if not manifest_path.is_file():
|
|
220
|
-
raise ArtifactError(f"artifact missing {manifest_path}")
|
|
221
|
-
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
|
|
222
|
-
if manifest.get("skills") != "./skills":
|
|
223
|
-
raise ArtifactError("artifact Codex manifest must use skills=./skills")
|
|
224
|
-
|
|
225
|
-
files = skill_files(skills_root)
|
|
226
|
-
rel_files = [str(path.relative_to(target)) for path in files]
|
|
227
|
-
if rel_files != ["skills/build-loop/SKILL.md"]:
|
|
228
|
-
raise ArtifactError(f"artifact must expose exactly one SKILL.md, got {rel_files}")
|
|
229
|
-
|
|
230
|
-
for rel_path in ASSET_FILES:
|
|
231
|
-
if not (target / rel_path).is_file():
|
|
232
|
-
raise ArtifactError(f"artifact missing asset: {rel_path}")
|
|
233
|
-
|
|
234
|
-
check_reference_pointers(target)
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
def build_artifact(source: Path, target: Path) -> None:
|
|
238
|
-
source = source.resolve()
|
|
239
|
-
target = target.resolve()
|
|
240
|
-
if source == target or target in source.parents:
|
|
241
|
-
raise ArtifactError(f"refusing to write artifact above source: {target}")
|
|
242
|
-
|
|
243
|
-
parent = target.parent
|
|
244
|
-
parent.mkdir(parents=True, exist_ok=True)
|
|
245
|
-
with tempfile.TemporaryDirectory(prefix=".codex-artifact-", dir=str(parent)) as tmp_raw:
|
|
246
|
-
tmp = Path(tmp_raw)
|
|
247
|
-
write_codex_manifest(source, tmp / ".codex-plugin" / "plugin.json")
|
|
248
|
-
for name in TOP_LEVEL_FILES:
|
|
249
|
-
copy_file(source / name, tmp / name)
|
|
250
|
-
for rel_path in ASSET_FILES:
|
|
251
|
-
copy_file(source / rel_path, tmp / rel_path)
|
|
252
|
-
copy_tree(source / "skills" / "build-loop", tmp / "skills" / "build-loop")
|
|
253
|
-
copy_file(source / "docs" / "agent-surface-policy.md", tmp / "docs" / "agent-surface-policy.md")
|
|
254
|
-
write_notice(tmp / "BUILD-ARTIFACT.md")
|
|
255
|
-
# Mirror cited references AFTER the skill tree + top-level files exist so
|
|
256
|
-
# the pointer scan sees every citing file.
|
|
257
|
-
mirror_references(source, tmp)
|
|
258
|
-
validate_artifact(tmp)
|
|
259
|
-
|
|
260
|
-
if target.exists():
|
|
261
|
-
shutil.rmtree(target)
|
|
262
|
-
os.replace(tmp, target)
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
def iter_files(root: Path) -> Iterable[Path]:
|
|
266
|
-
for path in sorted(root.rglob("*")):
|
|
267
|
-
if path.is_file():
|
|
268
|
-
yield path
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
def assert_same_tree(expected: Path, actual: Path) -> None:
|
|
272
|
-
expected_files = {path.relative_to(expected) for path in iter_files(expected)}
|
|
273
|
-
actual_files = {path.relative_to(actual) for path in iter_files(actual)}
|
|
274
|
-
if expected_files != actual_files:
|
|
275
|
-
missing = sorted(str(path) for path in expected_files - actual_files)
|
|
276
|
-
extra = sorted(str(path) for path in actual_files - expected_files)
|
|
277
|
-
raise ArtifactError(f"artifact file set differs; missing={missing}, extra={extra}")
|
|
278
|
-
for rel in sorted(expected_files):
|
|
279
|
-
if not filecmp.cmp(expected / rel, actual / rel, shallow=False):
|
|
280
|
-
raise ArtifactError(f"artifact file differs: {rel}")
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
def check_artifact(source: Path, target: Path) -> None:
|
|
284
|
-
parent = target.resolve().parent
|
|
285
|
-
parent.mkdir(parents=True, exist_ok=True)
|
|
286
|
-
with tempfile.TemporaryDirectory(prefix=".codex-artifact-check-", dir=str(parent)) as tmp_raw:
|
|
287
|
-
tmp = Path(tmp_raw) / "codex"
|
|
288
|
-
build_artifact(source, tmp)
|
|
289
|
-
assert_same_tree(tmp, target.resolve())
|
|
290
|
-
validate_artifact(target.resolve())
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
|
294
|
-
parser = argparse.ArgumentParser(description=__doc__)
|
|
295
|
-
parser.add_argument("--source", default=".", help="Build Loop source repo root.")
|
|
296
|
-
parser.add_argument("--target", default=str(DEFAULT_TARGET), help="Codex artifact output directory.")
|
|
297
|
-
parser.add_argument("--check", action="store_true", help="Fail if the artifact is missing or stale.")
|
|
298
|
-
return parser.parse_args(argv)
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
def main(argv: list[str] | None = None) -> int:
|
|
302
|
-
args = parse_args(argv)
|
|
303
|
-
source = Path(args.source).expanduser().resolve()
|
|
304
|
-
target = Path(args.target).expanduser()
|
|
305
|
-
if not target.is_absolute():
|
|
306
|
-
target = source / target
|
|
307
|
-
try:
|
|
308
|
-
if args.check:
|
|
309
|
-
check_artifact(source, target)
|
|
310
|
-
print(f"codex artifact up to date: {target}")
|
|
311
|
-
else:
|
|
312
|
-
build_artifact(source, target)
|
|
313
|
-
print(f"codex artifact written: {target}")
|
|
314
|
-
return 0
|
|
315
|
-
except ArtifactError as exc:
|
|
316
|
-
print(f"error: {exc}")
|
|
317
|
-
return 1
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
if __name__ == "__main__":
|
|
321
|
-
raise SystemExit(main())
|