fraim-framework 2.0.4 → 2.0.7
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/.ai-agents/workflows/test.md +89 -89
- package/.github/workflows/ci.yml +51 -0
- package/.github/workflows/phase-change.yml +251 -0
- package/.github/workflows/status-change.yml +68 -0
- package/.github/workflows/sync-on-pr-review.yml +66 -0
- package/package.json +2 -1
- package/setup.js +112 -932
- package/DISTRIBUTION.md +0 -187
- package/PUBLISH_INSTRUCTIONS.md +0 -93
- package/getting-started.md +0 -143
- package/linkedin-post.md +0 -23
|
@@ -1,90 +1,90 @@
|
|
|
1
|
-
# Testing Phase
|
|
2
|
-
|
|
3
|
-
## INTENT
|
|
4
|
-
To create comprehensive test coverage that accurately reproduces issues and validates solutions, ensuring robust testing through proper test structure, failure verification, and systematic test execution.
|
|
5
|
-
|
|
6
|
-
## PRINCIPLES
|
|
7
|
-
- **Test-Driven**: Write tests that reproduce the issue before fixing
|
|
8
|
-
- **Comprehensive Coverage**: Ensure all scenarios are tested
|
|
9
|
-
- **Failure Verification**: Confirm tests fail before implementation
|
|
10
|
-
- **Proper Structure**: Use established test patterns and frameworks
|
|
11
|
-
- **Systematic Execution**: Follow consistent testing procedures
|
|
12
|
-
|
|
13
|
-
## TESTING WORKFLOW
|
|
14
|
-
|
|
15
|
-
### Step 1: Issue Identification
|
|
16
|
-
Ask for {issue_number} (and optional {slug}); confirm target branch feature/{issue_number}-{slug}.
|
|
17
|
-
|
|
18
|
-
### Step 2: Phase Initiation
|
|
19
|
-
Label the issue 'phase:tests'. (GitHub Action will automatically label the issue `status:wip` and update the existing draft PR)
|
|
20
|
-
|
|
21
|
-
### Step 3: Environment Setup
|
|
22
|
-
**IMPORTANT**: The user has already run `prep-issue.sh` which has:
|
|
23
|
-
- ✅ Created the feature branch
|
|
24
|
-
- ✅ Checked out the branch
|
|
25
|
-
- ✅ Created draft PR
|
|
26
|
-
- ✅ Indexed the codebase with Serena
|
|
27
|
-
- ✅ Opened the editor in the prepared workspace
|
|
28
|
-
|
|
29
|
-
You can start working immediately in the prepared environment. No need to create branches or wait for GitHub Actions.
|
|
30
|
-
|
|
31
|
-
### Step 4: Work Location
|
|
32
|
-
You are already in the correct workspace prepared by the user. Confirm you're on the right branch and start working.
|
|
33
|
-
|
|
34
|
-
### Step 5: Testing Work
|
|
35
|
-
Your work entails the following:
|
|
36
|
-
|
|
37
|
-
- Review the RFC associated with this issue.
|
|
38
|
-
- Determine whether tests need to be added to an existing test suite, or a new one needs to be created.
|
|
39
|
-
- **CRITICAL: Write INTEGRATION tests that demonstrate the REAL USER SCENARIO**
|
|
40
|
-
- Test the actual end-to-end user experience, not unit tests for hypothetical fixes
|
|
41
|
-
- Use real services and APIs where possible (not mocks)
|
|
42
|
-
- Verify the issue occurs in the real system as described in the issue
|
|
43
|
-
- Example: For messaging threading issues, actually send messages and verify they appear as new messages vs replies
|
|
44
|
-
- Run the test cases to ensure they fail (demonstrating the issue exists)
|
|
45
|
-
- Flip issue to 'status:needs-review' and remove 'status:wip'
|
|
46
|
-
|
|
47
|
-
**❌ DO NOT:**
|
|
48
|
-
- Write unit tests for code that doesn't exist yet
|
|
49
|
-
- Test hypothetical fixes or solutions
|
|
50
|
-
- Create mock tests that don't use real services
|
|
51
|
-
- Test individual components in isolation
|
|
52
|
-
|
|
53
|
-
**✅ DO:**
|
|
54
|
-
- Test the complete user workflow end-to-end
|
|
55
|
-
- Use real APIs and services when possible
|
|
56
|
-
- Verify the actual problem described in the issue
|
|
57
|
-
- Create tests that will pass AFTER the fix is implemented
|
|
58
|
-
|
|
59
|
-
### Step 6: Iteration
|
|
60
|
-
If workflow actions or reviewer feedback indicates more work is needed, ensure the issue is set back to `status:wip` and continue working as above.
|
|
61
|
-
|
|
62
|
-
## EXAMPLES
|
|
63
|
-
|
|
64
|
-
### Good: Comprehensive Testing Process
|
|
65
|
-
```
|
|
66
|
-
Issue #84: "Fix API integration timeout"
|
|
67
|
-
1. ✅ Identified: Issue #84, branch feature/84-fix-api
|
|
68
|
-
2. ✅ Phase: Set phase:tests, PR created
|
|
69
|
-
3. ✅ Environment: User ran prep-issue.sh, ready to work
|
|
70
|
-
4. ✅ Location: Working in prepared workspace with Serena indexing
|
|
71
|
-
5. ✅ RFC Review: Read docs/rfcs/84-fix-api-timeout.md
|
|
72
|
-
6. ✅ Analysis: Determined need to add timeout tests
|
|
73
|
-
7. ✅ Test Creation: Added test cases for timeout scenarios
|
|
74
|
-
8. ✅ Failure Verification: Confirmed tests fail before fix
|
|
75
|
-
9. ✅ Review: Set status:needs-review
|
|
76
|
-
10. ✅ Iteration: Incorporated feedback, updated tests
|
|
77
|
-
Result: Comprehensive test coverage with proper structure
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### Bad: Incomplete Testing Process
|
|
81
|
-
```
|
|
82
|
-
Issue #84: "Fix API integration timeout"
|
|
83
|
-
1. ✅ Identified: Issue #84
|
|
84
|
-
2. ❌ Skip: Didn't review RFC
|
|
85
|
-
3. ❌ Skip: Started testing without understanding requirements
|
|
86
|
-
4. ❌ Skip: No test cases written
|
|
87
|
-
5. ❌ Skip: Didn't verify tests fail
|
|
88
|
-
6. ❌ Skip: No test structure followed
|
|
89
|
-
Result: Incomplete, ineffective testing
|
|
1
|
+
# Testing Phase
|
|
2
|
+
|
|
3
|
+
## INTENT
|
|
4
|
+
To create comprehensive test coverage that accurately reproduces issues and validates solutions, ensuring robust testing through proper test structure, failure verification, and systematic test execution.
|
|
5
|
+
|
|
6
|
+
## PRINCIPLES
|
|
7
|
+
- **Test-Driven**: Write tests that reproduce the issue before fixing
|
|
8
|
+
- **Comprehensive Coverage**: Ensure all scenarios are tested
|
|
9
|
+
- **Failure Verification**: Confirm tests fail before implementation
|
|
10
|
+
- **Proper Structure**: Use established test patterns and frameworks
|
|
11
|
+
- **Systematic Execution**: Follow consistent testing procedures
|
|
12
|
+
|
|
13
|
+
## TESTING WORKFLOW
|
|
14
|
+
|
|
15
|
+
### Step 1: Issue Identification
|
|
16
|
+
Ask for {issue_number} (and optional {slug}); confirm target branch feature/{issue_number}-{slug}.
|
|
17
|
+
|
|
18
|
+
### Step 2: Phase Initiation
|
|
19
|
+
Label the issue 'phase:tests'. (GitHub Action will automatically label the issue `status:wip` and update the existing draft PR)
|
|
20
|
+
|
|
21
|
+
### Step 3: Environment Setup
|
|
22
|
+
**IMPORTANT**: The user has already run `prep-issue.sh` which has:
|
|
23
|
+
- ✅ Created the feature branch
|
|
24
|
+
- ✅ Checked out the branch
|
|
25
|
+
- ✅ Created draft PR
|
|
26
|
+
- ✅ Indexed the codebase with Serena
|
|
27
|
+
- ✅ Opened the editor in the prepared workspace
|
|
28
|
+
|
|
29
|
+
You can start working immediately in the prepared environment. No need to create branches or wait for GitHub Actions.
|
|
30
|
+
|
|
31
|
+
### Step 4: Work Location
|
|
32
|
+
You are already in the correct workspace prepared by the user. Confirm you're on the right branch and start working.
|
|
33
|
+
|
|
34
|
+
### Step 5: Testing Work
|
|
35
|
+
Your work entails the following:
|
|
36
|
+
|
|
37
|
+
- Review the RFC associated with this issue.
|
|
38
|
+
- Determine whether tests need to be added to an existing test suite, or a new one needs to be created.
|
|
39
|
+
- **CRITICAL: Write INTEGRATION tests that demonstrate the REAL USER SCENARIO**
|
|
40
|
+
- Test the actual end-to-end user experience, not unit tests for hypothetical fixes
|
|
41
|
+
- Use real services and APIs where possible (not mocks)
|
|
42
|
+
- Verify the issue occurs in the real system as described in the issue
|
|
43
|
+
- Example: For messaging threading issues, actually send messages and verify they appear as new messages vs replies
|
|
44
|
+
- Run the test cases to ensure they fail (demonstrating the issue exists)
|
|
45
|
+
- Flip issue to 'status:needs-review' and remove 'status:wip'
|
|
46
|
+
|
|
47
|
+
**❌ DO NOT:**
|
|
48
|
+
- Write unit tests for code that doesn't exist yet
|
|
49
|
+
- Test hypothetical fixes or solutions
|
|
50
|
+
- Create mock tests that don't use real services
|
|
51
|
+
- Test individual components in isolation
|
|
52
|
+
|
|
53
|
+
**✅ DO:**
|
|
54
|
+
- Test the complete user workflow end-to-end
|
|
55
|
+
- Use real APIs and services when possible
|
|
56
|
+
- Verify the actual problem described in the issue
|
|
57
|
+
- Create tests that will pass AFTER the fix is implemented
|
|
58
|
+
|
|
59
|
+
### Step 6: Iteration
|
|
60
|
+
If workflow actions or reviewer feedback indicates more work is needed, ensure the issue is set back to `status:wip` and continue working as above.
|
|
61
|
+
|
|
62
|
+
## EXAMPLES
|
|
63
|
+
|
|
64
|
+
### Good: Comprehensive Testing Process
|
|
65
|
+
```
|
|
66
|
+
Issue #84: "Fix API integration timeout"
|
|
67
|
+
1. ✅ Identified: Issue #84, branch feature/84-fix-api
|
|
68
|
+
2. ✅ Phase: Set phase:tests, PR created
|
|
69
|
+
3. ✅ Environment: User ran prep-issue.sh, ready to work
|
|
70
|
+
4. ✅ Location: Working in prepared workspace with Serena indexing
|
|
71
|
+
5. ✅ RFC Review: Read docs/rfcs/84-fix-api-timeout.md
|
|
72
|
+
6. ✅ Analysis: Determined need to add timeout tests
|
|
73
|
+
7. ✅ Test Creation: Added test cases for timeout scenarios
|
|
74
|
+
8. ✅ Failure Verification: Confirmed tests fail before fix
|
|
75
|
+
9. ✅ Review: Set status:needs-review
|
|
76
|
+
10. ✅ Iteration: Incorporated feedback, updated tests
|
|
77
|
+
Result: Comprehensive test coverage with proper structure
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Bad: Incomplete Testing Process
|
|
81
|
+
```
|
|
82
|
+
Issue #84: "Fix API integration timeout"
|
|
83
|
+
1. ✅ Identified: Issue #84
|
|
84
|
+
2. ❌ Skip: Didn't review RFC
|
|
85
|
+
3. ❌ Skip: Started testing without understanding requirements
|
|
86
|
+
4. ❌ Skip: No test cases written
|
|
87
|
+
5. ❌ Skip: Didn't verify tests fail
|
|
88
|
+
6. ❌ Skip: No test structure followed
|
|
89
|
+
Result: Incomplete, ineffective testing
|
|
90
90
|
```
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- 'master'
|
|
7
|
+
schedule:
|
|
8
|
+
- cron: '0 6 * * *' # 11 PM PST is 6 AM UTC
|
|
9
|
+
|
|
10
|
+
# Sets permissions of the GITHUB_TOKEN
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
checks: write
|
|
14
|
+
|
|
15
|
+
# Cancel in-progress runs on same branch
|
|
16
|
+
concurrency:
|
|
17
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
18
|
+
cancel-in-progress: true
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
build:
|
|
22
|
+
if: github.event_name == 'push'
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
timeout-minutes: 15
|
|
25
|
+
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v4
|
|
28
|
+
- uses: actions/setup-node@v4
|
|
29
|
+
with:
|
|
30
|
+
node-version: 20
|
|
31
|
+
- run: npm install
|
|
32
|
+
- name: Build
|
|
33
|
+
run: npm run build
|
|
34
|
+
- name: Test Smoke CI
|
|
35
|
+
run: npm run test-smoke-ci
|
|
36
|
+
|
|
37
|
+
full-test:
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
if: github.event_name == 'schedule' && github.ref == 'refs/heads/master'
|
|
40
|
+
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/checkout@v4
|
|
43
|
+
- uses: actions/setup-node@v4
|
|
44
|
+
with:
|
|
45
|
+
node-version: 20
|
|
46
|
+
- run: npm install
|
|
47
|
+
- name: Build
|
|
48
|
+
run: npm run build
|
|
49
|
+
- name: Test All CI
|
|
50
|
+
run: npm run test-all-ci
|
|
51
|
+
timeout-minutes: 30
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
name: Phase Change Handler
|
|
2
|
+
|
|
3
|
+
# This workflow now assumes branches are created by prep-issue.sh
|
|
4
|
+
# It only handles PR creation/updating and status management
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
issues:
|
|
8
|
+
types: [labeled]
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
issues: write
|
|
12
|
+
pull-requests: write
|
|
13
|
+
contents: write
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
handle-phase-change:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
if: |
|
|
19
|
+
contains(github.event.label.name, 'phase:') ||
|
|
20
|
+
(github.event.action == 'unlabeled' && contains(github.event.label.name, 'phase:'))
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- name: Checkout repository
|
|
24
|
+
uses: actions/checkout@v4
|
|
25
|
+
with:
|
|
26
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
27
|
+
fetch-depth: 0
|
|
28
|
+
|
|
29
|
+
- name: Setup Git
|
|
30
|
+
run: |
|
|
31
|
+
git config --global user.name "github-actions[bot]"
|
|
32
|
+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
33
|
+
|
|
34
|
+
- name: Auth GitHub CLI
|
|
35
|
+
run: echo "${{ secrets.GITHUB_TOKEN }}" | gh auth login --with-token
|
|
36
|
+
|
|
37
|
+
- name: Extract issue details
|
|
38
|
+
id: issue-details
|
|
39
|
+
run: |
|
|
40
|
+
ISSUE_NUMBER="${{ github.event.issue.number }}"
|
|
41
|
+
ISSUE_TITLE="${{ github.event.issue.title }}"
|
|
42
|
+
BRANCH_NAME="feature/${ISSUE_NUMBER}-$(echo "$ISSUE_TITLE" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-\|-$//g')"
|
|
43
|
+
|
|
44
|
+
echo "issue_number=$ISSUE_NUMBER" >> $GITHUB_OUTPUT
|
|
45
|
+
echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
|
|
46
|
+
echo "issue_title=$ISSUE_TITLE" >> $GITHUB_OUTPUT
|
|
47
|
+
|
|
48
|
+
- name: Determine current phase
|
|
49
|
+
id: current-phase
|
|
50
|
+
run: |
|
|
51
|
+
LABELS='${{ toJson(github.event.issue.labels) }}'
|
|
52
|
+
CURRENT_PHASE=""
|
|
53
|
+
|
|
54
|
+
# Extract current phase from labels
|
|
55
|
+
for label in $(echo "$LABELS" | jq -r '.[].name'); do
|
|
56
|
+
if [[ $label == phase:* ]]; then
|
|
57
|
+
CURRENT_PHASE=$label
|
|
58
|
+
break
|
|
59
|
+
fi
|
|
60
|
+
done
|
|
61
|
+
|
|
62
|
+
echo "current_phase=$CURRENT_PHASE" >> $GITHUB_OUTPUT
|
|
63
|
+
echo "Current phase: $CURRENT_PHASE"
|
|
64
|
+
|
|
65
|
+
- name: Verify branch exists (created by prep-issue.sh)
|
|
66
|
+
run: |
|
|
67
|
+
BRANCH_NAME="${{ steps.issue-details.outputs.branch_name }}"
|
|
68
|
+
|
|
69
|
+
# Check if branch exists remotely
|
|
70
|
+
if git ls-remote --exit-code --heads origin "$BRANCH_NAME" >/dev/null 2>&1; then
|
|
71
|
+
echo "✓ Branch $BRANCH_NAME exists remotely"
|
|
72
|
+
git fetch origin "$BRANCH_NAME"
|
|
73
|
+
else
|
|
74
|
+
echo "⚠️ Branch $BRANCH_NAME does not exist remotely"
|
|
75
|
+
echo " This should have been created by prep-issue.sh"
|
|
76
|
+
echo " Please run prep-issue.sh before invoking agent workflows"
|
|
77
|
+
exit 1
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
- name: Check if PR already exists
|
|
81
|
+
id: pr-check
|
|
82
|
+
run: |
|
|
83
|
+
BRANCH_NAME="${{ steps.issue-details.outputs.branch_name }}"
|
|
84
|
+
EXISTING_PR=$(gh pr list --head "$BRANCH_NAME" --json number --jq '.[0].number' 2>/dev/null || echo "")
|
|
85
|
+
echo "existing_pr=$EXISTING_PR" >> $GITHUB_OUTPUT
|
|
86
|
+
if [ -n "$EXISTING_PR" ]; then
|
|
87
|
+
echo "✓ PR #$EXISTING_PR already exists"
|
|
88
|
+
else
|
|
89
|
+
echo "ℹ️ No PR exists yet, will create one for phase: ${{ steps.current-phase.outputs.current_phase }}"
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
- name: phase:spec → create/update PR for Specification phase
|
|
93
|
+
if: steps.current-phase.outputs.current_phase == 'phase:spec'
|
|
94
|
+
shell: bash
|
|
95
|
+
env:
|
|
96
|
+
ISSUE: ${{ github.event.issue.number }}
|
|
97
|
+
run: |
|
|
98
|
+
ISSUE_NUMBER="${{ steps.issue-details.outputs.issue_number }}"
|
|
99
|
+
ISSUE_TITLE="${{ steps.issue-details.outputs.issue_title }}"
|
|
100
|
+
BRANCH_NAME="${{ steps.issue-details.outputs.branch_name }}"
|
|
101
|
+
|
|
102
|
+
# Create or update PR for Specification phase
|
|
103
|
+
PR_TITLE="[Specification] Feature Spec for Issue #$ISSUE_NUMBER: $ISSUE_TITLE"
|
|
104
|
+
PR_BODY="## Feature Specification for Issue #$ISSUE_NUMBER
|
|
105
|
+
|
|
106
|
+
This PR contains the feature specification for: $ISSUE_TITLE
|
|
107
|
+
|
|
108
|
+
**Phase:** Specification
|
|
109
|
+
**Issue:** #$ISSUE_NUMBER
|
|
110
|
+
**Branch:** \`$BRANCH_NAME\`
|
|
111
|
+
|
|
112
|
+
### Specification Document
|
|
113
|
+
- 📋 [Feature Specification]($SPEC_FILE)
|
|
114
|
+
|
|
115
|
+
**Note:** This is a Specification PR. Design and Implementation will follow after specification approval.
|
|
116
|
+
|
|
117
|
+
"
|
|
118
|
+
|
|
119
|
+
EXISTING_PR="${{ steps.pr-check.outputs.existing_pr }}"
|
|
120
|
+
|
|
121
|
+
if [ -n "$EXISTING_PR" ]; then
|
|
122
|
+
echo "Updating existing PR #$EXISTING_PR for Specification phase"
|
|
123
|
+
gh pr edit "$EXISTING_PR" --title "$PR_TITLE" --body "$PR_BODY"
|
|
124
|
+
gh pr edit "$EXISTING_PR" --add-label "phase:spec" --remove-label "phase:design" --remove-label "phase:tests" --remove-label "phase:impl"
|
|
125
|
+
else
|
|
126
|
+
echo "Creating new PR for Specification phase"
|
|
127
|
+
gh pr create --title "$PR_TITLE" --body "$PR_BODY" --base master --head "$BRANCH_NAME" --draft
|
|
128
|
+
gh pr edit --add-label "phase:spec"
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
- name: phase:design → create/update PR for Design phase
|
|
132
|
+
if: steps.current-phase.outputs.current_phase == 'phase:design'
|
|
133
|
+
shell: bash
|
|
134
|
+
env:
|
|
135
|
+
ISSUE: ${{ github.event.issue.number }}
|
|
136
|
+
run: |
|
|
137
|
+
ISSUE_NUMBER="${{ steps.issue-details.outputs.issue_number }}"
|
|
138
|
+
ISSUE_TITLE="${{ steps.issue-details.outputs.issue_title }}"
|
|
139
|
+
BRANCH_NAME="${{ steps.issue-details.outputs.branch_name }}"
|
|
140
|
+
|
|
141
|
+
# Create or update PR for Design phase
|
|
142
|
+
PR_TITLE="[Design] RFC for Issue #$ISSUE_NUMBER: $ISSUE_TITLE"
|
|
143
|
+
PR_BODY="## Design RFC for Issue #$ISSUE_NUMBER
|
|
144
|
+
|
|
145
|
+
This PR contains the design RFC for: $ISSUE_TITLE
|
|
146
|
+
|
|
147
|
+
**Phase:** Design
|
|
148
|
+
**Issue:** #$ISSUE_NUMBER
|
|
149
|
+
**Branch:** \`$BRANCH_NAME\`
|
|
150
|
+
|
|
151
|
+
### RFC Document
|
|
152
|
+
- 📋 [RFC Document]($RFC_FILE)
|
|
153
|
+
|
|
154
|
+
**Note:** This is a Design PR. Implementation will follow in a separate PR after design approval.
|
|
155
|
+
|
|
156
|
+
"
|
|
157
|
+
|
|
158
|
+
EXISTING_PR="${{ steps.pr-check.outputs.existing_pr }}"
|
|
159
|
+
|
|
160
|
+
if [ -n "$EXISTING_PR" ]; then
|
|
161
|
+
echo "Updating existing PR #$EXISTING_PR for Design phase"
|
|
162
|
+
gh pr edit "$EXISTING_PR" --title "$PR_TITLE" --body "$PR_BODY"
|
|
163
|
+
gh pr edit "$EXISTING_PR" --add-label "phase:design" --remove-label "phase:spec" --remove-label "phase:tests" --remove-label "phase:impl"
|
|
164
|
+
else
|
|
165
|
+
echo "Creating new PR for Design phase"
|
|
166
|
+
gh pr create --title "$PR_TITLE" --body "$PR_BODY" --base master --head "$BRANCH_NAME" --draft
|
|
167
|
+
gh pr edit --add-label "phase:design"
|
|
168
|
+
fi
|
|
169
|
+
|
|
170
|
+
- name: phase:tests → create/update PR for Test phase
|
|
171
|
+
if: steps.current-phase.outputs.current_phase == 'phase:tests'
|
|
172
|
+
run: |
|
|
173
|
+
ISSUE_NUMBER="${{ steps.issue-details.outputs.issue_number }}"
|
|
174
|
+
ISSUE_TITLE="${{ steps.issue-details.outputs.issue_title }}"
|
|
175
|
+
BRANCH_NAME="${{ steps.issue-details.outputs.branch_name }}"
|
|
176
|
+
|
|
177
|
+
# Create or update PR for Test phase
|
|
178
|
+
PR_TITLE="[Testing] Test Cases for Issue #$ISSUE_NUMBER: $ISSUE_TITLE"
|
|
179
|
+
PR_BODY="## Test cases for Issue #$ISSUE_NUMBER
|
|
180
|
+
|
|
181
|
+
This PR contains the test cases for: $ISSUE_TITLE
|
|
182
|
+
|
|
183
|
+
**Phase:** Tests
|
|
184
|
+
**Issue:** #$ISSUE_NUMBER
|
|
185
|
+
**Branch:** \`$BRANCH_NAME\`
|
|
186
|
+
|
|
187
|
+
### Test Cases
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
**Note:** This is a Test PR. Implementation will follow after test approval.
|
|
191
|
+
|
|
192
|
+
"
|
|
193
|
+
|
|
194
|
+
EXISTING_PR="${{ steps.pr-check.outputs.existing_pr }}"
|
|
195
|
+
|
|
196
|
+
if [ -n "$EXISTING_PR" ]; then
|
|
197
|
+
echo "Updating existing PR #$EXISTING_PR for Test phase"
|
|
198
|
+
gh pr edit "$EXISTING_PR" --title "$PR_TITLE" --body "$PR_BODY"
|
|
199
|
+
gh pr edit "$EXISTING_PR" --add-label "phase:tests" --remove-label "phase:spec" --remove-label "phase:design" --remove-label "phase:impl"
|
|
200
|
+
else
|
|
201
|
+
echo "Creating new PR for Test phase"
|
|
202
|
+
gh pr create --title "$PR_TITLE" --body "$PR_BODY" --base master --head "$BRANCH_NAME" --draft
|
|
203
|
+
gh pr edit --add-label "phase:tests"
|
|
204
|
+
fi
|
|
205
|
+
|
|
206
|
+
- name: phase:impl → create/update PR for Implementation phase
|
|
207
|
+
if: steps.current-phase.outputs.current_phase == 'phase:impl'
|
|
208
|
+
run: |
|
|
209
|
+
ISSUE_NUMBER="${{ steps.issue-details.outputs.issue_number }}"
|
|
210
|
+
ISSUE_TITLE="${{ steps.issue-details.outputs.issue_title }}"
|
|
211
|
+
BRANCH_NAME="${{ steps.issue-details.outputs.branch_name }}"
|
|
212
|
+
|
|
213
|
+
# Create or update PR for Implementation phase
|
|
214
|
+
PR_TITLE="[Implementation] Fixes for Issue #$ISSUE_NUMBER: $ISSUE_TITLE"
|
|
215
|
+
PR_BODY="## Fixes for Issue #$ISSUE_NUMBER
|
|
216
|
+
|
|
217
|
+
This PR contains the fixes for: $ISSUE_TITLE
|
|
218
|
+
|
|
219
|
+
**Phase:** Implementation
|
|
220
|
+
**Issue:** #$ISSUE_NUMBER
|
|
221
|
+
**Branch:** \`$BRANCH_NAME\`
|
|
222
|
+
|
|
223
|
+
### Fixes
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
Closes #$ISSUE_NUMBER
|
|
227
|
+
|
|
228
|
+
"
|
|
229
|
+
|
|
230
|
+
EXISTING_PR="${{ steps.pr-check.outputs.existing_pr }}"
|
|
231
|
+
|
|
232
|
+
if [ -n "$EXISTING_PR" ]; then
|
|
233
|
+
echo "Updating existing PR #$EXISTING_PR for Implementation phase"
|
|
234
|
+
gh pr edit "$EXISTING_PR" --title "$PR_TITLE" --body "$PR_BODY"
|
|
235
|
+
gh pr edit "$EXISTING_PR" --add-label "phase:impl" --remove-label "phase:spec" --remove-label "phase:design" --remove-label "phase:tests"
|
|
236
|
+
else
|
|
237
|
+
echo "Creating new PR for Implementation phase"
|
|
238
|
+
gh pr create --title "$PR_TITLE" --body "$PR_BODY" --base master --head "$BRANCH_NAME" --draft
|
|
239
|
+
gh pr edit --add-label "phase:impl"
|
|
240
|
+
fi
|
|
241
|
+
|
|
242
|
+
- name: Normalize ISSUE and PR status to WIP (authoritative)
|
|
243
|
+
run: |
|
|
244
|
+
gh issue edit ${{ github.event.issue.number }} --add-label "status:wip" --remove-label "status:needs-review" --remove-label "status:complete" || true
|
|
245
|
+
|
|
246
|
+
# Use the PR number from the check step
|
|
247
|
+
EXISTING_PR="${{ steps.pr-check.outputs.existing_pr }}"
|
|
248
|
+
|
|
249
|
+
if [ -n "$EXISTING_PR" ]; then
|
|
250
|
+
gh pr edit "$EXISTING_PR" --add-label "status:wip" --remove-label "status:needs-review" --remove-label "status:complete" || true
|
|
251
|
+
fi
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
name: Status Change → Flip PR Draft/Ready
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
issues:
|
|
5
|
+
types: [labeled]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
pull-requests: write
|
|
9
|
+
issues: read
|
|
10
|
+
contents: write
|
|
11
|
+
|
|
12
|
+
# Serialize per ISSUE; last status wins
|
|
13
|
+
concurrency:
|
|
14
|
+
group: status-change-${{ github.event.issue.number }}
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
status-change:
|
|
19
|
+
if: startsWith(github.event.label.name, 'status:')
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
steps:
|
|
22
|
+
- name: Checkout repository
|
|
23
|
+
uses: actions/checkout@v4
|
|
24
|
+
with:
|
|
25
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
26
|
+
fetch-depth: 0
|
|
27
|
+
|
|
28
|
+
- name: Setup Git
|
|
29
|
+
run: |
|
|
30
|
+
git config --global user.name "github-actions[bot]"
|
|
31
|
+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
32
|
+
|
|
33
|
+
- name: Auth GitHub CLI
|
|
34
|
+
run: echo "${{ secrets.GITHUB_TOKEN }}" | gh auth login --with-token
|
|
35
|
+
|
|
36
|
+
- name: Derive branch + find PR
|
|
37
|
+
id: pr
|
|
38
|
+
shell: bash
|
|
39
|
+
env:
|
|
40
|
+
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
|
41
|
+
ISSUE_TITLE: ${{ github.event.issue.title }}
|
|
42
|
+
run: |
|
|
43
|
+
set -euo pipefail
|
|
44
|
+
slug=$(echo "$ISSUE_TITLE" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g;s/^-+|-+$//g')
|
|
45
|
+
BR="feature/${ISSUE_NUMBER}-${slug}"
|
|
46
|
+
PR=$(gh pr list --state open --head "$BR" --json number --jq '.[0].number')
|
|
47
|
+
echo "pr=$PR" >> $GITHUB_OUTPUT
|
|
48
|
+
echo "label=${{ github.event.label.name }}" >> $GITHUB_OUTPUT
|
|
49
|
+
|
|
50
|
+
- name: Flip PR state (Draft/Ready) based on label
|
|
51
|
+
if: steps.pr.outputs.pr != ''
|
|
52
|
+
shell: bash
|
|
53
|
+
env:
|
|
54
|
+
PR: ${{ steps.pr.outputs.pr }}
|
|
55
|
+
LABEL: ${{ steps.pr.outputs.label }}
|
|
56
|
+
run: |
|
|
57
|
+
set -euo pipefail
|
|
58
|
+
case "$LABEL" in
|
|
59
|
+
status:needs-review)
|
|
60
|
+
gh pr ready "$PR"
|
|
61
|
+
gh pr edit "$PR" --add-label "status:needs-review" --remove-label "status:wip" --remove-label "status:complete" || true
|
|
62
|
+
;;
|
|
63
|
+
status:wip)
|
|
64
|
+
gh pr edit "$PR" --add-label "status:wip" --remove-label "status:needs-review" --remove-label "status:complete" || true
|
|
65
|
+
;;
|
|
66
|
+
*)
|
|
67
|
+
echo "No action for label: $LABEL" ;;
|
|
68
|
+
esac
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
name: Sync Issue on PR Review
|
|
2
|
+
on:
|
|
3
|
+
pull_request_review:
|
|
4
|
+
types: [submitted]
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
pull-requests: write
|
|
8
|
+
issues: write
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: review-sync-${{ github.event.pull_request.number }}
|
|
12
|
+
cancel-in-progress: true
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
sync-on-review:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
# no job-level `if` — we branch inside the script
|
|
18
|
+
env:
|
|
19
|
+
GH_TOKEN: ${{ secrets.PR_AUTOMATION_TOKEN || secrets.GITHUB_TOKEN }}
|
|
20
|
+
REPO: ${{ github.repository }}
|
|
21
|
+
steps:
|
|
22
|
+
- name: Derive review state, issue number, and branch
|
|
23
|
+
id: vars
|
|
24
|
+
shell: bash
|
|
25
|
+
run: |
|
|
26
|
+
set -euo pipefail
|
|
27
|
+
STATE="${{ github.event.review.state }}"
|
|
28
|
+
BR="${{ github.event.pull_request.head.ref }}" # e.g., feature/26-slug
|
|
29
|
+
ISSUE="$(sed -nE 's#^feature/([0-9]+)-.*#\1#p' <<< "$BR" || true)"
|
|
30
|
+
echo "state=$STATE" >> $GITHUB_OUTPUT
|
|
31
|
+
echo "issue=$ISSUE" >> $GITHUB_OUTPUT
|
|
32
|
+
echo "branch=$BR" >> $GITHUB_OUTPUT
|
|
33
|
+
echo "Detected review state: $STATE; branch: $BR; issue: $ISSUE"
|
|
34
|
+
|
|
35
|
+
- name: Handle review states
|
|
36
|
+
if: steps.vars.outputs.issue != ''
|
|
37
|
+
shell: bash
|
|
38
|
+
env:
|
|
39
|
+
STATE: ${{ steps.vars.outputs.state }}
|
|
40
|
+
ISSUE: ${{ steps.vars.outputs.issue }}
|
|
41
|
+
PRNUM: ${{ github.event.pull_request.number }}
|
|
42
|
+
REPO: ${{ env.REPO }}
|
|
43
|
+
run: |
|
|
44
|
+
set -euo pipefail
|
|
45
|
+
case "$STATE" in
|
|
46
|
+
changes_requested)
|
|
47
|
+
# Flip to WIP
|
|
48
|
+
gh issue edit "$ISSUE" --repo "$REPO" \
|
|
49
|
+
--add-label "status:wip" --remove-label "status:needs-review" --remove-label "status:complete" || true
|
|
50
|
+
gh pr edit "$PRNUM" --repo "$REPO" \
|
|
51
|
+
--add-label "status:wip" --remove-label "status:needs-review" --remove-label "status:complete" || true
|
|
52
|
+
;;
|
|
53
|
+
approved)
|
|
54
|
+
# Flip to Complete
|
|
55
|
+
gh issue edit "$ISSUE" --repo "$REPO" \
|
|
56
|
+
--add-label "status:complete" --remove-label "status:wip" --remove-label "status:needs-review" || true
|
|
57
|
+
gh pr edit "$PRNUM" --repo "$REPO" --add-label "status:complete" --remove-label "status:wip" --remove-label "status:needs-review" || true
|
|
58
|
+
;;
|
|
59
|
+
commented)
|
|
60
|
+
# No-op; comments don't change state
|
|
61
|
+
echo "Review was 'commented' — no state change."
|
|
62
|
+
;;
|
|
63
|
+
*)
|
|
64
|
+
echo "Unknown review state: $STATE"
|
|
65
|
+
;;
|
|
66
|
+
esac
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fraim-framework",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.7",
|
|
4
4
|
"description": "FRAIM v2: Framework for Rigor-based AI Management - Transform from solo developer to AI manager orchestrating production-ready code with enterprise-grade discipline",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
},
|
|
52
52
|
"files": [
|
|
53
53
|
".ai-agents/",
|
|
54
|
+
".github/",
|
|
54
55
|
"examples/",
|
|
55
56
|
"bin/",
|
|
56
57
|
"*.js",
|