diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..1666f8b --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,28 @@ +# CODEOWNERS - Define code ownership and required reviewers +# See: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners + +# Default owner for everything +* @itdove + +# Critical workflow files - require owner approval +/.github/workflows/publish.yml @itdove +/.github/workflows/publish-test.yml @itdove +/.github/workflows/tag-monitor.yml @itdove + +# Release documentation - require owner approval +/RELEASING.md @itdove +/CONTRIBUTING.md @itdove + +# Security and configuration +/.github/CODEOWNERS @itdove +/.gitignore @itdove + +# Version files - require owner approval +/pyproject.toml @itdove +/devflow/__init__.py @itdove + +# Release management module +/devflow/release/ @itdove + +# CLI commands that affect releases +/devflow/cli/commands/release_command.py @itdove diff --git a/.github/workflows/tag-monitor.yml b/.github/workflows/tag-monitor.yml new file mode 100644 index 0000000..0527067 --- /dev/null +++ b/.github/workflows/tag-monitor.yml @@ -0,0 +1,152 @@ +name: Tag Creation Monitor + +on: + push: + tags: + - 'v*' # Production tags (v1.0.0, v2.2.0) + - 'v*-test*' # Test tags (v1.0.0-test1, v2.2.0-test1) + +jobs: + monitor-and-notify: + runs-on: ubuntu-latest + permissions: + contents: read + issues: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Get tag information + id: tag-info + run: | + TAG_NAME="${GITHUB_REF#refs/tags/}" + TAG_CREATOR="${GITHUB_ACTOR}" + TAG_COMMIT=$(git rev-list -n 1 "${TAG_NAME}") + COMMIT_AUTHOR=$(git log -1 --pretty=%an "${TAG_COMMIT}") + + echo "tag_name=${TAG_NAME}" >> $GITHUB_OUTPUT + echo "tag_creator=${TAG_CREATOR}" >> $GITHUB_OUTPUT + echo "tag_commit=${TAG_COMMIT}" >> $GITHUB_OUTPUT + echo "commit_author=${COMMIT_AUTHOR}" >> $GITHUB_OUTPUT + + - name: Check authorization + id: auth-check + run: | + TAG_NAME="${{ steps.tag-info.outputs.tag_name }}" + TAG_CREATOR="${{ steps.tag-info.outputs.tag_creator }}" + + # Authorized maintainers who can create production releases + AUTHORIZED_USERS=("itdove") + + # Check if production release + if [[ "${TAG_NAME}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + IS_PRODUCTION="true" + TAG_TYPE="Production Release" + elif [[ "${TAG_NAME}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+-test ]]; then + IS_PRODUCTION="false" + TAG_TYPE="Test Release" + else + IS_PRODUCTION="false" + TAG_TYPE="Unknown" + fi + + # Check authorization + IS_AUTHORIZED="false" + if [ "${IS_PRODUCTION}" = "true" ]; then + for user in "${AUTHORIZED_USERS[@]}"; do + if [ "${TAG_CREATOR}" = "${user}" ]; then + IS_AUTHORIZED="true" + break + fi + done + else + # Test releases are allowed for everyone + IS_AUTHORIZED="true" + fi + + echo "is_production=${IS_PRODUCTION}" >> $GITHUB_OUTPUT + echo "tag_type=${TAG_TYPE}" >> $GITHUB_OUTPUT + echo "is_authorized=${IS_AUTHORIZED}" >> $GITHUB_OUTPUT + + echo "Tag Type: ${TAG_TYPE}" + echo "Created by: ${TAG_CREATOR}" + echo "Authorized: ${IS_AUTHORIZED}" + + - name: Log tag creation (authorized) + if: steps.auth-check.outputs.is_authorized == 'true' + run: | + echo "::notice title=Authorized Tag Created::Tag '${{ steps.tag-info.outputs.tag_name }}' created by @${{ steps.tag-info.outputs.tag_creator }}" + echo "" + echo "========================================================================" + echo "✓ AUTHORIZED TAG CREATION" + echo "========================================================================" + echo "Tag: ${{ steps.tag-info.outputs.tag_name }}" + echo "Type: ${{ steps.auth-check.outputs.tag_type }}" + echo "Created by: @${{ steps.tag-info.outputs.tag_creator }}" + echo "Commit: ${{ steps.tag-info.outputs.tag_commit }}" + echo "Authorization: ✓ Authorized" + echo "========================================================================" + + - name: Log tag creation (unauthorized) + if: steps.auth-check.outputs.is_authorized == 'false' + run: | + echo "::error title=Unauthorized Tag::Production tag '${{ steps.tag-info.outputs.tag_name }}' created by unauthorized user @${{ steps.tag-info.outputs.tag_creator }}" + echo "" + echo "========================================================================" + echo "✗ UNAUTHORIZED TAG CREATION" + echo "========================================================================" + echo "Tag: ${{ steps.tag-info.outputs.tag_name }}" + echo "Type: ${{ steps.auth-check.outputs.tag_type }}" + echo "Created by: @${{ steps.tag-info.outputs.tag_creator }}" + echo "Authorization: ✗ NOT AUTHORIZED" + echo "" + echo "ACTION REQUIRED:" + echo "1. Delete tag: git push origin :refs/tags/${{ steps.tag-info.outputs.tag_name }}" + echo "2. Report to repository owner" + echo "========================================================================" + exit 1 + + - name: Create security issue (unauthorized) + if: steps.auth-check.outputs.is_authorized == 'false' + uses: actions/github-script@v7 + with: + script: | + const tagName = '${{ steps.tag-info.outputs.tag_name }}'; + const tagCreator = '${{ steps.tag-info.outputs.tag_creator }}'; + const commitSha = '${{ steps.tag-info.outputs.tag_commit }}'; + + const issueBody = [ + '## Unauthorized Release Tag Detected', + '', + `**Tag:** \`${tagName}\``, + `**Created by:** @${tagCreator}`, + `**Commit:** ${commitSha}`, + `**Time:** ${new Date().toISOString()}`, + '', + '## Required Actions', + '', + '- [ ] Verify if intentional', + `- [ ] Delete tag: \`git push origin :refs/tags/${tagName}\``, + `- [ ] Review RELEASING.md policy with @${tagCreator}`, + '- [ ] Recreate by authorized user if needed', + '', + '## Fork-Based Workflow', + '', + 'This repository uses a fork-based workflow for contributions:', + '- **Contributors** must fork and submit PRs', + '- **Maintainers** (@itdove) create releases', + '- See [CONTRIBUTING.md](CONTRIBUTING.md) and [RELEASING.md](RELEASING.md)', + '', + '_Auto-generated by tag-monitor workflow_' + ].join('\n'); + + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: `🚨 Unauthorized Release Tag: ${tagName}`, + labels: ['security', 'unauthorized-release', 'priority-high'], + body: issueBody + }); diff --git a/.wolf/anatomy.md b/.wolf/anatomy.md index f0ba4f4..5626d92 100644 --- a/.wolf/anatomy.md +++ b/.wolf/anatomy.md @@ -1,7 +1,12 @@ # anatomy.md -> Auto-maintained by OpenWolf. Last scanned: 2026-04-08T02:00:17.107Z -> Files: 506 tracked | Anatomy hits: 0 | Misses: 0 +> Auto-maintained by OpenWolf. Last scanned: 2026-04-08T14:20:27.349Z +> Files: 511 tracked | Anatomy hits: 0 | Misses: 0 + +## ../../../.claude/skills/release/ + +- `release_helper.py` — ReleaseHelper: get_current_version, update_version, calculate_next_version, update_changelog + 2 mor (~3826 tok) +- `SKILL.md` — DevAIFlow Release Skill (~2689 tok) ## ./ @@ -11,14 +16,15 @@ - `CHANGELOG.md` — Change log (~4649 tok) - `CLAUDE.md` — OpenWolf (~139 tok) - `config.schema.json` (~9891 tok) -- `CONTRIBUTING.md` — Contributing to DevAIFlow (~2458 tok) +- `CONTRIBUTING.md` — Contributing to DevAIFlow (~2695 tok) - `coverage.json` (~12790 tok) - `demo_branch_selection.sh` — Demo script showing the new branch source selection feature (~846 tok) +- `FORK_WORKFLOW_SETUP.md` — Fork-Based Workflow Setup Guide (~1503 tok) - `LICENSE` — Project license (~3029 tok) - `pyproject.toml` — Python project configuration (~702 tok) - `QUICKREF.md` — DevAIFlow Quick Reference (~1384 tok) - `README.md` — Project documentation (~6603 tok) -- `RELEASING.md` — Release Management Process (~3523 tok) +- `RELEASING.md` — Release Management Process (~3825 tok) - `requirements-dev.txt` (~28 tok) - `requirements.txt` — Python dependencies (~72 tok) - `SECURITY.md` — Security Policy (~1380 tok) @@ -34,6 +40,10 @@ - `openwolf.md` (~313 tok) +## .github/ + +- `CODEOWNERS` — CODEOWNERS - Define code ownership and required reviewers (~222 tok) + ## .github/ISSUE_TEMPLATE/ - `agent-validation.md` — Environment (~360 tok) @@ -44,6 +54,7 @@ - `lint.yml` — GitHub Actions CI/CD - Lint Workflow (~534 tok) - `publish-test.yml` — GitHub Actions CI/CD - TestPyPI Publish Workflow (~370 tok) - `publish.yml` — GitHub Actions CI/CD - PyPI Publish Workflow (~582 tok) +- `tag-monitor.yml` — CI: Tag Creation Monitor (~1799 tok) - `test.yml` — GitHub Actions CI/CD - Test Workflow (~467 tok) ## .pytest_cache/ diff --git a/.wolf/buglog.json b/.wolf/buglog.json index bf99169..dfd0a5b 100644 --- a/.wolf/buglog.json +++ b/.wolf/buglog.json @@ -52,6 +52,38 @@ "related_bugs": [], "occurrences": 1, "last_seen": "2026-04-08T01:53:30.693Z" + }, + { + "id": "bug-004", + "timestamp": "2026-04-08T14:13:53.762Z", + "error_message": "Significant refactor of ", + "file": ".github/workflows/tag-monitor.yml", + "root_cause": "16 lines replaced/restructured", + "fix": "Rewrote 37→41 lines (16 removed)", + "tags": [ + "auto-detected", + "refactor", + "yml" + ], + "related_bugs": [], + "occurrences": 1, + "last_seen": "2026-04-08T14:13:53.762Z" + }, + { + "id": "bug-005", + "timestamp": "2026-04-08T14:19:28.337Z", + "error_message": "Significant refactor of ", + "file": "FORK_WORKFLOW_SETUP.md", + "root_cause": "2 lines replaced/restructured", + "fix": "Rewrote 14→25 lines (2 removed) | Also: ### 1. Remove Write Access from Non-Maintainers; **Goal**: Force contributors to use forks by remov | Also: ### 2. Enable Branch Protection Rules; **Goal**: Prevent direct pushes to main branch, re", + "tags": [ + "auto-detected", + "refactor", + "md" + ], + "related_bugs": [], + "occurrences": 3, + "last_seen": "2026-04-08T14:20:08.541Z" } ] } \ No newline at end of file diff --git a/.wolf/cron-state.json b/.wolf/cron-state.json index ce4dcb7..23641fd 100644 --- a/.wolf/cron-state.json +++ b/.wolf/cron-state.json @@ -1,7 +1,7 @@ { - "last_heartbeat": null, - "engine_status": "initialized", + "last_heartbeat": "2026-04-08T14:17:46.043Z", + "engine_status": "running", "execution_log": [], "dead_letter_queue": [], "upcoming": [] -} +} \ No newline at end of file diff --git a/.wolf/hooks/_session.json b/.wolf/hooks/_session.json index 974e97c..4cc6667 100644 --- a/.wolf/hooks/_session.json +++ b/.wolf/hooks/_session.json @@ -1,6 +1,6 @@ { - "session_id": "session-2026-04-08-2200", - "started": "2026-04-08T02:00:56.461Z", + "session_id": "session-2026-04-08-1023", + "started": "2026-04-08T14:23:00.781Z", "files_read": {}, "files_written": [], "edit_counts": {}, diff --git a/.wolf/memory.md b/.wolf/memory.md index 3e2f624..12fd040 100644 --- a/.wolf/memory.md +++ b/.wolf/memory.md @@ -130,3 +130,67 @@ | Time | Action | File(s) | Outcome | ~Tokens | |------|--------|---------|---------|--------| + +## Session: 2026-04-08 22:01 + +| Time | Action | File(s) | Outcome | ~Tokens | +|------|--------|---------|---------|--------| + +## Session: 2026-04-08 08:08 + +| Time | Action | File(s) | Outcome | ~Tokens | +|------|--------|---------|---------|--------| + +## Session: 2026-04-08 09:16 + +| Time | Action | File(s) | Outcome | ~Tokens | +|------|--------|---------|---------|--------| + +## Session: 2026-04-08 09:17 + +| Time | Action | File(s) | Outcome | ~Tokens | +|------|--------|---------|---------|--------| + +## Session: 2026-04-08 09:29 + +| Time | Action | File(s) | Outcome | ~Tokens | +|------|--------|---------|---------|--------| +| 09:49 | Created ../../../.claude/skills/release/SKILL.md | — | ~2868 | +| 09:49 | Edited ../../../.claude/skills/release/release_helper.py | 10→10 lines | ~87 | +| 09:49 | Edited ../../../.claude/skills/release/release_helper.py | modified __init__() | ~120 | +| 09:49 | Edited ../../../.claude/skills/release/release_helper.py | modified _read_version_from_init() | ~124 | +| 09:49 | Edited ../../../.claude/skills/release/release_helper.py | modified exists() | ~95 | +| 09:49 | Edited ../../../.claude/skills/release/release_helper.py | modified main() | ~73 | +| 09:50 | Created .github/workflows/tag-monitor.yml | — | ~1673 | +| 09:50 | Created .github/CODEOWNERS | — | ~222 | +| 09:56 | Edited CONTRIBUTING.md | expanded (+36 lines) | ~379 | +| 10:09 | Edited RELEASING.md | expanded (+54 lines) | ~527 | +| 10:10 | Edited .github/workflows/tag-monitor.yml | 7→7 lines | ~81 | +| 10:13 | Edited .github/workflows/tag-monitor.yml | 37→41 lines | ~516 | +| 10:15 | Implemented fork-based workflow and release automation (issue #369) | SKILL.md, release_helper.py, tag-monitor.yml, CODEOWNERS, CONTRIBUTING.md, RELEASING.md | Complete implementation | ~3000 | +| 10:15 | Updated ~/.claude/skills/release/ skill for DevAIFlow | SKILL.md, release_helper.py | Changed from ai-guardian to devaiflow paths | ~500 | +| 10:15 | Created tag monitoring workflow | .github/workflows/tag-monitor.yml | Monitors unauthorized releases | ~1700 | +| 10:15 | Created CODEOWNERS file | .github/CODEOWNERS | Protects critical release files | ~220 | +| 10:15 | Updated fork-based workflow documentation | CONTRIBUTING.md, RELEASING.md | Added authorization policies | ~900 | +| 10:14 | Session end: 12 writes across 6 files (SKILL.md, release_helper.py, tag-monitor.yml, CODEOWNERS, CONTRIBUTING.md) | 9 reads | ~51619 tok | +| 10:16 | Created FORK_WORKFLOW_SETUP.md | — | ~1827 | +| 10:17 | Session end: 13 writes across 7 files (SKILL.md, release_helper.py, tag-monitor.yml, CODEOWNERS, CONTRIBUTING.md) | 9 reads | ~53576 tok | +| 10:19 | Edited FORK_WORKFLOW_SETUP.md | expanded (+11 lines) | ~219 | +| 10:20 | Edited FORK_WORKFLOW_SETUP.md | maintainers() → itdove() | ~81 | +| 10:20 | Edited FORK_WORKFLOW_SETUP.md | reduced (-14 lines) | ~101 | +| 10:20 | Edited FORK_WORKFLOW_SETUP.md | reduced (-6 lines) | ~175 | +| 10:20 | Edited FORK_WORKFLOW_SETUP.md | 16→17 lines | ~152 | +| 10:18 | Enabled tag protection for v* tags | GitHub repository settings | Ruleset created via API | ~100 | +| 10:19 | Updated FORK_WORKFLOW_SETUP.md with completed status | FORK_WORKFLOW_SETUP.md | All protections now in place | ~300 | +| 10:21 | Session end: 18 writes across 7 files (SKILL.md, release_helper.py, tag-monitor.yml, CODEOWNERS, CONTRIBUTING.md) | 9 reads | ~54356 tok | + +## Session: 2026-04-08 10:22 + +| Time | Action | File(s) | Outcome | ~Tokens | +|------|--------|---------|---------|--------| +| 10:22 | Deleted FORK_WORKFLOW_SETUP.md | — | Setup completed, guide no longer needed | ~50 | + +## Session: 2026-04-08 10:23 + +| Time | Action | File(s) | Outcome | ~Tokens | +|------|--------|---------|---------|--------| diff --git a/.wolf/token-ledger.json b/.wolf/token-ledger.json index 2f1a9c4..dceaab0 100644 --- a/.wolf/token-ledger.json +++ b/.wolf/token-ledger.json @@ -2,14 +2,14 @@ "version": 1, "created_at": "2026-04-06T12:35:01.489Z", "lifetime": { - "total_tokens_estimated": 153928, - "total_reads": 14, - "total_writes": 19, - "total_sessions": 18, - "anatomy_hits": 7, - "anatomy_misses": 5, - "repeated_reads_blocked": 16, - "estimated_savings_vs_bare_cli": 191105 + "total_tokens_estimated": 313479, + "total_reads": 41, + "total_writes": 62, + "total_sessions": 25, + "anatomy_hits": 25, + "anatomy_misses": 11, + "repeated_reads_blocked": 25, + "estimated_savings_vs_bare_cli": 204743 }, "sessions": [ { @@ -288,6 +288,434 @@ "repeated_reads_blocked": 1, "anatomy_lookups": 1 } + }, + { + "id": "session-2026-04-08-0929", + "started": "2026-04-08T13:29:20.612Z", + "ended": "2026-04-08T14:14:47.040Z", + "reads": [ + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/AGENTS.md", + "tokens_estimated": 21442, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/.claude/projects/-Users-dvernier-development-devaiflow-devaiflow/4ae7f50f-9be8-45d5-bc21-43781148c4fe/tool-results/b1hys292b.txt", + "tokens_estimated": 0, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/RELEASING.md", + "tokens_estimated": 3523, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/devflow/release/manager.py", + "tokens_estimated": 14891, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/.claude/skills/release/SKILL.md", + "tokens_estimated": 0, + "was_repeated": true, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/.github/workflows/publish.yml", + "tokens_estimated": 582, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/CONTRIBUTING.md", + "tokens_estimated": 2458, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/.claude/skills/release/release_helper.py", + "tokens_estimated": 0, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/.github/workflows/tag-monitor.yml", + "tokens_estimated": 1673, + "was_repeated": true, + "anatomy_had_description": false + } + ], + "writes": [ + { + "file": "/Users/dvernier/.claude/skills/release/SKILL.md", + "tokens_estimated": 3073, + "action": "create" + }, + { + "file": "/Users/dvernier/.claude/skills/release/release_helper.py", + "tokens_estimated": 87, + "action": "edit" + }, + { + "file": "/Users/dvernier/.claude/skills/release/release_helper.py", + "tokens_estimated": 120, + "action": "edit" + }, + { + "file": "/Users/dvernier/.claude/skills/release/release_helper.py", + "tokens_estimated": 124, + "action": "edit" + }, + { + "file": "/Users/dvernier/.claude/skills/release/release_helper.py", + "tokens_estimated": 95, + "action": "edit" + }, + { + "file": "/Users/dvernier/.claude/skills/release/release_helper.py", + "tokens_estimated": 73, + "action": "edit" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/.github/workflows/tag-monitor.yml", + "tokens_estimated": 1673, + "action": "create" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/.github/CODEOWNERS", + "tokens_estimated": 238, + "action": "create" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/CONTRIBUTING.md", + "tokens_estimated": 406, + "action": "edit" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/RELEASING.md", + "tokens_estimated": 564, + "action": "edit" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/.github/workflows/tag-monitor.yml", + "tokens_estimated": 81, + "action": "edit" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/.github/workflows/tag-monitor.yml", + "tokens_estimated": 516, + "action": "edit" + } + ], + "totals": { + "input_tokens_estimated": 44569, + "output_tokens_estimated": 7050, + "reads_count": 9, + "writes_count": 12, + "repeated_reads_blocked": 3, + "anatomy_lookups": 6 + } + }, + { + "id": "session-2026-04-08-0929", + "started": "2026-04-08T13:29:20.612Z", + "ended": "2026-04-08T14:17:39.860Z", + "reads": [ + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/AGENTS.md", + "tokens_estimated": 21442, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/.claude/projects/-Users-dvernier-development-devaiflow-devaiflow/4ae7f50f-9be8-45d5-bc21-43781148c4fe/tool-results/b1hys292b.txt", + "tokens_estimated": 0, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/RELEASING.md", + "tokens_estimated": 3523, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/devflow/release/manager.py", + "tokens_estimated": 14891, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/.claude/skills/release/SKILL.md", + "tokens_estimated": 0, + "was_repeated": true, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/.github/workflows/publish.yml", + "tokens_estimated": 582, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/CONTRIBUTING.md", + "tokens_estimated": 2458, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/.claude/skills/release/release_helper.py", + "tokens_estimated": 0, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/.github/workflows/tag-monitor.yml", + "tokens_estimated": 1673, + "was_repeated": true, + "anatomy_had_description": false + } + ], + "writes": [ + { + "file": "/Users/dvernier/.claude/skills/release/SKILL.md", + "tokens_estimated": 3073, + "action": "create" + }, + { + "file": "/Users/dvernier/.claude/skills/release/release_helper.py", + "tokens_estimated": 87, + "action": "edit" + }, + { + "file": "/Users/dvernier/.claude/skills/release/release_helper.py", + "tokens_estimated": 120, + "action": "edit" + }, + { + "file": "/Users/dvernier/.claude/skills/release/release_helper.py", + "tokens_estimated": 124, + "action": "edit" + }, + { + "file": "/Users/dvernier/.claude/skills/release/release_helper.py", + "tokens_estimated": 95, + "action": "edit" + }, + { + "file": "/Users/dvernier/.claude/skills/release/release_helper.py", + "tokens_estimated": 73, + "action": "edit" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/.github/workflows/tag-monitor.yml", + "tokens_estimated": 1673, + "action": "create" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/.github/CODEOWNERS", + "tokens_estimated": 238, + "action": "create" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/CONTRIBUTING.md", + "tokens_estimated": 406, + "action": "edit" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/RELEASING.md", + "tokens_estimated": 564, + "action": "edit" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/.github/workflows/tag-monitor.yml", + "tokens_estimated": 81, + "action": "edit" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/.github/workflows/tag-monitor.yml", + "tokens_estimated": 516, + "action": "edit" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/FORK_WORKFLOW_SETUP.md", + "tokens_estimated": 1957, + "action": "create" + } + ], + "totals": { + "input_tokens_estimated": 44569, + "output_tokens_estimated": 9007, + "reads_count": 9, + "writes_count": 13, + "repeated_reads_blocked": 3, + "anatomy_lookups": 6 + } + }, + { + "id": "session-2026-04-08-0929", + "started": "2026-04-08T13:29:20.612Z", + "ended": "2026-04-08T14:21:20.785Z", + "reads": [ + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/AGENTS.md", + "tokens_estimated": 21442, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/.claude/projects/-Users-dvernier-development-devaiflow-devaiflow/4ae7f50f-9be8-45d5-bc21-43781148c4fe/tool-results/b1hys292b.txt", + "tokens_estimated": 0, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/RELEASING.md", + "tokens_estimated": 3523, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/devflow/release/manager.py", + "tokens_estimated": 14891, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/.claude/skills/release/SKILL.md", + "tokens_estimated": 0, + "was_repeated": true, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/.github/workflows/publish.yml", + "tokens_estimated": 582, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/CONTRIBUTING.md", + "tokens_estimated": 2458, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/.claude/skills/release/release_helper.py", + "tokens_estimated": 0, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/.github/workflows/tag-monitor.yml", + "tokens_estimated": 1673, + "was_repeated": true, + "anatomy_had_description": false + } + ], + "writes": [ + { + "file": "/Users/dvernier/.claude/skills/release/SKILL.md", + "tokens_estimated": 3073, + "action": "create" + }, + { + "file": "/Users/dvernier/.claude/skills/release/release_helper.py", + "tokens_estimated": 87, + "action": "edit" + }, + { + "file": "/Users/dvernier/.claude/skills/release/release_helper.py", + "tokens_estimated": 120, + "action": "edit" + }, + { + "file": "/Users/dvernier/.claude/skills/release/release_helper.py", + "tokens_estimated": 124, + "action": "edit" + }, + { + "file": "/Users/dvernier/.claude/skills/release/release_helper.py", + "tokens_estimated": 95, + "action": "edit" + }, + { + "file": "/Users/dvernier/.claude/skills/release/release_helper.py", + "tokens_estimated": 73, + "action": "edit" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/.github/workflows/tag-monitor.yml", + "tokens_estimated": 1673, + "action": "create" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/.github/CODEOWNERS", + "tokens_estimated": 238, + "action": "create" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/CONTRIBUTING.md", + "tokens_estimated": 406, + "action": "edit" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/RELEASING.md", + "tokens_estimated": 564, + "action": "edit" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/.github/workflows/tag-monitor.yml", + "tokens_estimated": 81, + "action": "edit" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/.github/workflows/tag-monitor.yml", + "tokens_estimated": 516, + "action": "edit" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/FORK_WORKFLOW_SETUP.md", + "tokens_estimated": 1957, + "action": "create" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/FORK_WORKFLOW_SETUP.md", + "tokens_estimated": 235, + "action": "edit" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/FORK_WORKFLOW_SETUP.md", + "tokens_estimated": 87, + "action": "edit" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/FORK_WORKFLOW_SETUP.md", + "tokens_estimated": 108, + "action": "edit" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/FORK_WORKFLOW_SETUP.md", + "tokens_estimated": 187, + "action": "edit" + }, + { + "file": "/Users/dvernier/development/devaiflow/devaiflow/FORK_WORKFLOW_SETUP.md", + "tokens_estimated": 163, + "action": "edit" + } + ], + "totals": { + "input_tokens_estimated": 44569, + "output_tokens_estimated": 9787, + "reads_count": 9, + "writes_count": 18, + "repeated_reads_blocked": 3, + "anatomy_lookups": 6 + } } ], "daemon_usage": [], diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4d1fb46..efa766c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,8 +2,44 @@ Thank you for your interest in contributing to DevAIFlow! This document provides guidelines and instructions for contributing. +## ⚠️ Fork-Based Workflow + +**IMPORTANT**: This repository uses a fork-based workflow for all external contributions. + +### Quick Start for Contributors + +```bash +# 1. Fork the repository on GitHub +gh repo fork itdove/devaiflow --clone +cd devaiflow + +# 2. Create feature branch +git checkout -b feature-name + +# 3. Make changes and commit +git add . +git commit -m "feat: description" + +# 4. Push to your fork +git push origin feature-name + +# 5. Create pull request +gh pr create --web +``` + +### Release Authorization + +**Contributors CANNOT create releases** - Only repository maintainers can: + +- ✅ **You CAN**: Submit PRs with features/fixes, update CHANGELOG.md in your PR +- ❌ **You CANNOT**: Create version tags, modify version numbers, push production releases +- ✅ **Maintainers handle**: All releases via the `/release` skill + +See [RELEASING.md](RELEASING.md) for the complete release authorization policy. + ## Table of Contents +- [Fork-Based Workflow](#fork-based-workflow) - [Getting Started](#getting-started) - [Development Setup](#development-setup) - [Making Changes](#making-changes) diff --git a/RELEASING.md b/RELEASING.md index 87da660..fc3f2bd 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -2,15 +2,69 @@ This document describes the release management process for DevAIFlow (daf tool). -> **💡 Recommended**: Use the automated `daf release` command instead of following these manual steps. See [docs/08-release-management.md](docs/08-release-management.md) for the automated workflow. +> **💡 Recommended**: Use the automated `/release` skill instead of following these manual steps. > > This document is maintained as a reference for: > - Understanding the release process details > - Troubleshooting release issues > - Custom scenarios not covered by automation +## ⚠️ Release Authorization Policy + +**IMPORTANT**: This repository uses a fork-based workflow with strict release authorization. + +### Repository Access Model + +**Fork-Based Workflow:** + +- **Maintainers** (@itdove): Write/Admin access + - Can push tags + - Can create releases + - Can use `/release` skill + - Handle PyPI publications + +- **Contributors**: Must use forks + - Cannot push tags + - All changes via PRs + - See [CONTRIBUTING.md](CONTRIBUTING.md) + +### Authorized Release Managers + +Currently authorized to create production releases: +- **@itdove** (Repository Owner) + +### For Contributors + +**DO NOT create release tags.** + +Instead: +1. Fork the repository +2. Submit PRs with your changes +3. Update CHANGELOG.md in your PR +4. Maintainers will handle releases + +### For Maintainers + +Use the `/release` skill for automated release management: + +```bash +/release minor # 2.1.0 -> 2.2.0 +/release patch # 2.2.0 -> 2.2.1 +/release major # 2.0.0 -> 3.0.0 +/release test # 2.2.0-dev -> 2.2.0-test1 +``` + +### Tag Monitoring + +The `.github/workflows/tag-monitor.yml` workflow: +- Logs all tag creation events +- Verifies authorization for production tags +- Creates security issues for unauthorized attempts +- Provides audit trail for all releases + ## Table of Contents +- [Release Authorization Policy](#release-authorization-policy) - [Version Numbering](#version-numbering) - [Branch Strategy](#branch-strategy) - [Release Workflow](#release-workflow)