بنقرة واحدة
prepare-release
Before publish — ASOPB scan, staging, dry-run, publish gate (NEVER executes publish)
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Before publish — ASOPB scan, staging, dry-run, publish gate (NEVER executes publish)
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Run ASOPB evaluation with credential routing, build context sync, and baseline comparison
Walk the full ADEPT Code Hygiene Quick Reference Card checklist and report PASS/FAIL/N-A for each item. Use as a final check before pushing.
Full task closure workflow -- runs test validation, session report, tracking doc updates, commit preparation, and hygiene audit in sequence. Use at the end of a development session. Pass an optional title hint as argument.
Configure Claude Code to connect to an ADEPT instance (local Docker stack or remote server). Generates .mcp.json, runs doctor check, verifies connectivity. Use when setting up or switching between ADEPT instances.
Guided workflow to deploy ADEPT on cloud infrastructure (AWS, Azure, or GCP) as a single VM or A2A mesh pair. Covers provisioning, OS prep, stack deployment, and optional A2A federation between two independently-deployed stacks.
Add a new tool to an existing MCP server following the canonical register(mcp) + Pydantic pattern. Use during Phase 4 (Implement) of the feature development lifecycle.
| name | prepare-release |
| description | Before publish — ASOPB scan, staging, dry-run, publish gate (NEVER executes publish) |
| disable-model-invocation | true |
| allowed-tools | Bash(make stage*) Bash(make docker-scan*) Bash(make docker-push-ghcr) Bash(make publish-dry*) Bash(python3 scripts/release/*) Bash(docker logs*) Bash(docker ps*) Bash(docker images*) Bash(git *) Bash(ls *) Bash(cat logs/*) Read Write Edit Glob Grep |
You are assisting an ADEPT developer with the pre-release verification workflow. This skill walks through the full ASOPB release gate process.
Do not use emojis in any output.
Enforce all rules in docs/development/AGENT_CODING_RULES.md throughout this skill execution.
CRITICAL: This skill NEVER executes the actual publish step. Only the developer can trigger make publish or twine upload. The skill stops at dry-run verification.
Before starting, verify:
git status shows no uncommitted changes)adept-release-scanner image is builtADEPT uses a phase-based branching model with squash-merge to main:
main ─────────────────●───────────────────●──────────────
↑ squash-merge ↑ squash-merge
FY26Q4 ──────────────┘ │
FY26Q4-phase1 ────────────────────────────┘
FY26Q4-phase2 ─── ... (future)
Release sequence (execute in order):
Version bump on the parent feature branch (e.g., FY26Q4):
v1.0.YYYYMMDD:
pyproject.toml (main package)examples/adept_asopb/pyproject.toml (ASOPB package)src/agentic_framework_sdk/__init__.py (__version__ string)uv lockchore(release): bump version to v1.0.YYYYMMDDCreate the next phase branch off the parent tip BEFORE merging:
git checkout feature-platform-optimizations-FY26Q4
git checkout -b feature-platform-optimizations-FY26Q4-phase1
git push -u origin feature-platform-optimizations-FY26Q4-phase1
This preserves full commit lineage for the team.
Squash-merge to main via PR (developer approves and merges):
release(v1.0.YYYYMMDD): <summary of quarter's work>gh pr merge yourself — developer approvesForward-merge main into phase branch (updates merge-base):
git checkout feature-platform-optimizations-FY26Q4-phase1
git merge main -m "chore: sync with main after v1.0.YYYYMMDD release"
git push origin feature-platform-optimizations-FY26Q4-phase1
This ensures future PRs from phase1 to main show ONLY the delta (new work), not previously-merged content.
Team develops on phase branch — when ready, repeat from step 1.
Key rules:
git branch --show-current
git status --short
echo "=== Version Parity Check ==="
grep '^version' pyproject.toml
grep '^version' examples/adept_asopb/pyproject.toml
grep '__version__' src/agentic_framework_sdk/__init__.py
All 3 MUST show the same YYYYMMDD date. If any differ, bump them before proceeding:
pyproject.toml — main package (agentic_framework_pkg)examples/adept_asopb/pyproject.toml — ASOPB packagesrc/agentic_framework_sdk/__init__.py — SDK __version__ stringAfter bumping, regenerate the lock file: uv lock
docker images adept-release-scanner --format "{{.Tag}} {{.CreatedAt}}"
python3 docs/api/generate_openapi.py
This fetches the current API surface from the running agent_gateway and orchestration_service, merges with hand-authored metadata, scans for prohibited patterns, and writes docs/api/openapi.json and docs/api/openapi-admin.json. If the stack is not running, start it first (make start). If specs changed, commit them before staging.
GATE CHECK: All four checks must pass before proceeding.
Stage the release artifacts using the .publish-exclude filter:
make -C scripts/release stage
For staging from working tree (includes uncommitted changes, useful for pre-commit validation):
make -C scripts/release stage-worktree
This runs rsync with 270+ exclusion rules, outputting to /tmp/adept-release-stage-YYYYMMDD.
Verify staging results:
STAGE_DIR=$(ls -td /tmp/adept-release-stage-* | head -1)
ls "$STAGE_DIR/" | head -20
find "$STAGE_DIR" -type f | wc -l
Expected: 1000-1500 files (varies by release).
Important: All release Makefile targets live in scripts/release/Makefile, not the root Makefile. Always use make -C scripts/release <target> or cd scripts/release && make <target>.
Verify the Pages documentation site builds cleanly from the staged tree:
# 1. Confirm docs/public-site/ is present in staged tree
ls /tmp/adept-release-stage/docs/public-site/mkdocs.yml
# 2. Run prohibited-pattern scan on Pages content
if grep -rniE -f scripts/release/prohibited_patterns.txt /tmp/adept-release-stage/docs/public-site/docs/; then
echo "FAIL: Prohibited patterns in Pages content"
else
echo "PASS: No prohibited patterns"
fi
# 3. Verify nav completeness (all referenced .md files exist)
grep -oP '(?<=: ).*\.md' /tmp/adept-release-stage/docs/public-site/mkdocs.yml | while read f; do
if [ ! -f "/tmp/adept-release-stage/docs/public-site/docs/$f" ]; then
echo "MISSING: docs/public-site/docs/$f"
fi
done
# 4. Test MkDocs build in isolated venv (matches CI runner conditions)
# CRITICAL: Must use a fresh venv to catch dependency incompatibilities
# that host-cached packages would mask. The CI runner installs fresh.
rm -rf /tmp/pages-venv
python3 -m venv /tmp/pages-venv
/tmp/pages-venv/bin/pip install -q -r /tmp/adept-release-stage/docs/public-site/requirements.txt
cd /tmp/adept-release-stage/docs/public-site && /tmp/pages-venv/bin/mkdocs build --strict --site-dir /tmp/pages-build-test 2>&1
rm -rf /tmp/pages-venv
GATE CHECK: All four checks must pass. If the MkDocs build fails (broken links, missing nav files, or dependency incompatibilities), fix in the source repo and re-stage.
Why this matters: After publishing, deploy-docs.yml triggers on the public repo. If Pages content has prohibited patterns or broken links, the workflow will either deploy sensitive content or fail the strict build — both unacceptable. The fresh venv ensures dependency resolution matches the CI runner (which installs from scratch), preventing cases where a host-cached compatible Pygments masks an incompatibility that only surfaces in CI.
Run the full security scan pipeline inside the Docker scanner:
make -C scripts/release docker-scan-staged
This runs:
--promptfoo-target)Promptfoo distinction — CI vs pre-release:
.github/workflows/asopb-pre-release-scan.yml): advisory only (continue-on-error: true), expensive due to backend LLM calls, non-blocking/promptfoo-check before publish approvalMonitor progress:
docker ps --filter name=release-scanner
docker logs adept-release-scanner --tail 20 --follow
Wait for completion. Output lands in logs/scan-staged-YYYYMMDD-HHMM/.
Run the codified analysis suite on the scan output. These scripts (in scripts/release/) are the proper tooling for release analysis — not ad-hoc one-liners:
# Find the latest scan directory
SCAN_DIR=$(ls -td logs/scan-staged-* | head -1)
echo "Scan directory: $SCAN_DIR"
# 1. Full analysis with FP classification simulation
# Shows: per-domain breakdown, FP suppression rates, simulated ASPI
python3 scripts/release/analyze_findings.py "$SCAN_DIR" --simulate
# 2. Actionable findings only (everything that survives FP filtering)
# Use this to identify what ACTUALLY needs fixing before publish
python3 scripts/release/analyze_findings.py "$SCAN_DIR" --actionable-only
# 3. JSON output for downstream tooling / CI integration
python3 scripts/release/analyze_findings.py "$SCAN_DIR" --format json
Or equivalently via Makefile targets (from scripts/release/):
make -C scripts/release scan-analyze SCAN_DIR="$SCAN_DIR"
make -C scripts/release scan-actionable SCAN_DIR="$SCAN_DIR"
Review the output:
If running the full 8-domain ASOPB evaluation with LLM scoring (not required for Pipeline ASPI release gate), estimate the T2 LLM token cost before proceeding:
# Estimate token budget (dry-run, no LLM calls)
python3 -c "
from asopb.config import EvalConfig
from asopb.evaluator import Evaluator
config = EvalConfig(skip_llm=False)
evaluator = Evaluator(config=config)
estimate = evaluator.estimate_t2_token_budget()
print(f'Estimated LLM calls: {estimate[\"estimated_calls\"]}')
print(f'Estimated input tokens: {estimate[\"estimated_input_tokens\"]:,}')
print(f'Estimated output tokens: {estimate[\"estimated_output_tokens\"]:,}')
print(f'Estimated total: {estimate[\"estimated_total_tokens\"]:,}')
for d, info in estimate['per_domain'].items():
print(f' {d}: {info[\"controls_t2_eligible\"]} eligible controls, ~{info[\"input_tokens\"]:,} input tokens')
"
Present the estimate to the developer with three options:
--token-budget-confirm)--token-budget <N> to skip LLM if estimated exceeds budget--skip-llm (fastest, no cost)GATE CHECK: Developer must explicitly choose an option before proceeding with LLM-enabled evaluation. This prevents unexpected cost from large codebases.
For the release gate (Pipeline ASPI), LLM scoring is NOT needed — skip this phase.
Release Gate Policy (see docs/development/VERSIONING_AND_RELEASE_CONVENTIONS.md Section 8):
| Gate | Metric | Threshold | Blocking? |
|---|---|---|---|
| Release | Pipeline ASPI (staged, D5/D7/D8) | >= 95 | YES |
| Advisory | Full 8-domain ASPI (evaluator) | Report only | NO |
The Pipeline ASPI is the release gate. The full evaluator score is informational — it reports codebase health for future investment but does NOT block publishing.
Run the gate check:
python3 scripts/release/gate_check.py "$SCAN_DIR" --no-report --verbose
Or equivalently:
python3 scripts/release/compute_aspi.py "$SCAN_DIR" --no-report --gate 95
Proceed to dry-run:
make -C scripts/release dry-run VERSION=v1.0.YYYYMMDD
Report results to developer. The developer decides whether to execute make -C scripts/release publish VERSION=v1.0.YYYYMMDD.
python3 scripts/release/analyze_findings.py "$SCAN_DIR" --actionable-only to identify what needs fixing.publish-excludeIf the scanner Dockerfile or ML model dependencies changed since last push, update GHCR so CI Phase 2 jobs (ml-fast, grype-scan) run instead of skipping:
make -C scripts/release docker-push-ghcr
This pushes two tags: ghcr.io/<org>/adept-release-scanner:latest (mutable, CI pulls this) and :YYYYMMDD (immutable audit reference). Authenticates via gh auth token. Requires write:packages scope on the GitHub PAT.
After push, verify the package is linked to the repo (required for CI pull via GITHUB_TOKEN):
gh api orgs/<org>/packages/container/adept-release-scanner --jq '.repository.full_name // "NOT LINKED"'
If output is "NOT LINKED" or errors with 404, this is the first push and you must link it:
adept-agentic-framework-extended (Read)GATE CHECK: Verify the next push triggers Phase 2 CI jobs (not skipped).
NOTE — Repo-Agnostic Abstraction (#79): When ASOPB is extracted into a standalone MCP tool/server, this Phase 5b must be parameterized for arbitrary target repositories:
Before proceeding to dry-run, ensure the three tracking documents reflect the release state. These are user-facing docs that ship in the published tree.
docs/CHANGELOG.md — Add a new top-level entry for this release:
docs/ROADMAP.md — Update three sections:
docs/KNOWN_ISSUES.md — Update as applicable:
# Verify all three docs are updated
grep "Last Updated" docs/CHANGELOG.md docs/ROADMAP.md docs/KNOWN_ISSUES.md
# All should show today's date or the release date
# Verify CHANGELOG has the new release entry at the top
head -20 docs/CHANGELOG.md
# Verify KNOWN_ISSUES ASPI score matches gate result
grep -i "ASPI" docs/KNOWN_ISSUES.md | grep -i "current"
GATE CHECK: All three documents updated with current release state. Commit these changes before proceeding to dry-run.
make -C scripts/release dry-run VERSION=v1.0.YYYYMMDD
This validates:
STOP HERE. Report results to developer. NEVER execute make -C scripts/release publish.
Release candidates allow iterative validation of the published tree before the final GA release. Each RC publishes to the public repo with a version tag suffix (e.g., v1.0.20260601-rc7).
.publish-exclude rules.public.md files)# 1. Stage from working tree (includes uncommitted changes for pre-commit testing)
make -C scripts/release stage-worktree
# 2. Verify staged content (spot-check new additions)
STAGE_DIR=$(ls -td /tmp/adept-release-stage-* | head -1)
ls "$STAGE_DIR/.claude/skills/" # Skills present?
find "$STAGE_DIR" -name "*.public.md" # Public variants waiting for swap?
# 3. Dry-run publish (simulates full pipeline including public-variant swap)
scripts/release/publish-to-public.sh --version v1.0.YYYYMMDD-rcN --dry-run \
--public-repo https://github.com/<org>/<public-repo>.git
# 4. Inspect dry-run output
cd /tmp/publish-public-*/public
ls .claude/skills/ # All SKILL.md (no .public.md after swap)
# 5. Execute publish (developer decision)
scripts/release/publish-to-public.sh --version v1.0.YYYYMMDD-rcN \
--public-repo https://github.com/<org>/<public-repo>.git
IMPORTANT: Always use --public-repo https://... (HTTPS) not the SSH default (git@github.com:...). HTTPS uses the gh CLI token for authentication which is universally available; SSH requires key setup that may not be present on all development hosts.
| Aspect | Release Candidate | General Availability |
|---|---|---|
| Version tag | v1.0.YYYYMMDD-rcN | v1.0.YYYYMMDD |
| ASOPB scan | Optional (gate already passed) | Required (full 7-pass) |
| Purpose | Validate staged tree content | Production release |
| Publish frequency | Multiple per session as needed | Once per release cycle |
| Rollback | Just re-publish from prior RC | Requires coordination |
After each RC publish, verify on the public repo:
.claude/skills/ directory)SKILL.md, no .public.md)docs/public-site/ changed)When creating GitHub Release notes on the public repo (pnnl/adept-agentic), the following information MUST NOT appear:
Allowed in public release notes:
Internal release notes (on / issues and team emails) may contain all details.
See docs/security/ASPI_SCORING_REFERENCE.md for the complete ASPI scoring reference, including Pipeline ASPI vs Full ASPI distinctions, all gate thresholds, and the FP suppression stack.
Key points for release:
ASPI = D5 * 0.4 + D8 * 0.4 + D7 * 0.2scripts/release/Makefile — All release targets (stage, scan, dry-run, publish, test, GHCR push). Invoke with make -C scripts/release <target>.scripts/release/scan_pipeline.pyscripts/release/scan_pipeline.py (ASPOBScore class)scripts/release/fp_patterns.pyscripts/release/analyze_findings.pyscripts/release/gate_check.pyscripts/release/compute_aspi.pyscripts/release/scan_grype.pyscripts/release/scan_dead_imports.pyscripts/release/compensating_controls.pyscripts/release/publish-to-public.sh.publish-excludeDetects imports referencing symbols that no longer exist in the source tree (beyond what ruff F401 catches). Use during pre-release to identify stale test imports that may mask broken code paths.
# Run on tests/ directory (most common)
cd scripts/release && python3 scan_dead_imports.py --target ../../tests/ --src ../../src/ --format json
# Gate mode (exit 1 if DEAD imports found)
cd scripts/release && python3 scan_dead_imports.py --target ../../tests/ --src ../../src/ --gate
# Actionable only (hides FIXTURE and UNUSED_VALID)
cd scripts/release && python3 scan_dead_imports.py --target ../../tests/ --src ../../src/ --actionable-only
Classifications: DEAD (symbol gone), MOVED (exists elsewhere), FIXTURE (pytest), UNUSED_VALID (exists but unused).
Validates that .asopb-allowlist.yaml has no structural errors. The allowlist provides category-level FP suppression via declarative YAML rules (type, file_patterns, pattern, min_score, max_entity_length).
cd scripts/release
# Validate allowlist structure
python3 -c "
import sys; sys.path.insert(0, '../../examples/adept_asopb/src')
from asopb.quality.allowlist import load_allowlist, validate_allowlist
from pathlib import Path
al = load_allowlist(Path('.asopb-allowlist.yaml'))
print(f'Allowlist: {al.total_rules} rules, hash={al.content_hash[:16]}..., version={al.schema_version}')
issues = validate_allowlist(al)
errors = [i for i in issues if i.severity == 'ERROR']
if errors:
for e in errors: print(f' ERROR [{e.category}:{e.rule_index}]: {e.message}')
sys.exit(1)
print('Validation: PASS')
"
# Run scan with allowlist suppression
python3 scan_pipeline.py /tmp/adept-release-stage --passes all --allowlist .asopb-allowlist.yaml
Guide: docs/guides/ALLOWLIST_SUPPRESSION_GUIDE.md
Validates integrity of false-positive suppressions. Detects stale suppressions where the underlying file changed (SHA-256 mismatch), entity moved, or file deleted.
cd scripts/release
# Validate all compensating controls against current codebase
python3 compensating_controls.py validate
# CI gate mode (exit 1 on stale/invalidated/expired)
python3 compensating_controls.py gate --fail-on stale,invalidated,expired
# List controls with current status
python3 compensating_controls.py list --format table
# Add new control (auto-computes file hash + fingerprint)
python3 compensating_controls.py add --domain D5 --file <path> --line 10-20 --entity <pattern> --justification "..."
Statuses: active, stale (file hash changed), invalidated (file/entity gone), expired (past expiration date).
After a successful gate pass, generate SVG badges for repository README or CI artifacts:
# Auto-discover latest scan output and generate badges
python3 scripts/release/generate_badges.py
# Explicit scan directory
python3 scripts/release/generate_badges.py logs/scan-staged-20260511-1418
# Manual score values
python3 scripts/release/generate_badges.py --pipeline-aspi 92.1 --full-aspi 87.3 --dast 84.6
# JSON format (for shields.io dynamic badges)
python3 scripts/release/generate_badges.py --format json --output-dir ./badges
Produces: pipeline-aspi.svg, full-aspi.svg, dast.svg in /tmp/asopb-badges/.