Skip to content

Commit d50f1c4

Browse files
mcj-codermartincjarvisclaude
authored
feat: implement CraftingSystem for Epic 4.7 (#135)
* feat: implement CraftingSystem for Epic 4.7 Implements the CraftingSystem that processes active crafting sessions, determines outcomes using CraftingOutcomeRule, and awards XP. Changes: - Add CraftId value object for unique craft identification - Add ActiveCraft component to track in-progress crafts - Add CraftingCompletedEvent for craft completion notifications - Extend Character with ClassProgress and ActiveCraft properties - Implement CraftingSystem with outcome determination and XP awarding - Add comprehensive test suite (8 tests) covering: - System name and empty world scenarios - Craft completion and event emission - XP awarding for successful crafts - Multi-class XP distribution - Failed craft handling - Active craft clearing after completion All 511 tests pass (427 Core + 84 Simulation). Refs #38 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * docs: update progress tracking for Epic 4.7 completion Epic 4.7 (CraftingSystem) complete - 7/8 tasks in Epic 4 Refs #38 * docs: add credential verification to prevent account mix-ups Add automated verification script and workflow checks to ensure git config and GitHub CLI are using the correct account before commits and PRs. Changes: - Add scripts/verify-credentials.sh for automated credential checking - Script reads from environment variables (no hardcoded account details) - Update PROMPT.md workflow rules with mandatory verification steps: - Step 1: Verify credentials before starting work - Step 8: Re-verify before commits - Step 10: Re-verify before creating PRs - Update CLAUDE.local.md with environment variable setup instructions This closes the loophole where git config was correct (Contributor) but GitHub CLI was authenticated with the wrong account (Maintainer), causing PRs to be created with the wrong account. Refs #38 * refactor: parse credentials from CLAUDE.local.md table Update verification script to read credentials directly from the CLAUDE.local.md markdown table instead of requiring environment variables. This makes the script self-contained and eliminates the need for manual environment variable setup. Refs #38 * docs: specify squash merge with conventional commits for auto-merge Update all auto-merge documentation to specify: - Use --squash flag for squash commits - Use --subject for conventional commit format (type: summary) - Use --body with detailed description, rationale, and issue reference - Include commit type definitions (feat, fix, refactor, docs, test, chore) Updated files: - CLAUDE.md: Added detailed auto-merge example in Code Review Flow - AGENTS.md: Updated auto-merge step with full command syntax - docs/roles/tech-lead.md: Added squash merge configuration - docs/playbooks/workflow-verification.md: Updated CI workflow reference - CLAUDE.local.md: Added comprehensive Auto-Merge Configuration section This ensures all squash merge commits follow conventional commit standards and include proper documentation of changes and rationale. Refs #38 --------- Co-authored-by: Martin Jarvis <m.c.j@live.co.uk> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent fab4744 commit d50f1c4

13 files changed

Lines changed: 750 additions & 35 deletions

File tree

AGENTS.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,23 @@ Closes #[number]
242242
3. **Tech Lead** collates all feedback into **line-level PR comments** (not issue comments)
243243
4. **Switch to Maintainer account:** `gh auth switch --user <maintainer-account>`
244244
5. **Maintainer** submits final review and approval
245-
6. **Maintainer** enables auto-merge: `gh pr merge --auto --squash --delete-branch`
245+
6. **Maintainer** enables auto-merge with squash commit in conventional format:
246+
247+
```bash
248+
gh pr merge <PR_NUMBER> --auto --squash --delete-branch \
249+
--subject "<type>: <concise summary>" \
250+
--body "$(cat <<'EOF'
251+
<detailed description>
252+
253+
<rationale>
254+
255+
Closes #<issue-number>
256+
EOF
257+
)"
258+
```
259+
260+
Types: `feat`, `fix`, `refactor`, `docs`, `test`, `chore`
261+
246262
7. **PR automatically merges** when all CI checks pass (DangerJS, lint, build, tests)
247263
8. **Issue auto-closes** via `Closes #N` in PR description
248264
9. **Tech Lead** monitors merge, coordinates fixes for any blockers

CLAUDE.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,38 @@ Or specify inline: "Review this as the Casual Game Expert."
9292
2. **Contributor** opens PR from feature branch
9393
1. Monitors PR and ISSUE for feedback comments that require fixing
9494
2. When fixes are committed update PR/ISSUE with details
95-
3. **Maintainer** enables auto-merge (`gh pr merge --auto --delete-branch`)
95+
3. **Maintainer** enables auto-merge with squash commit in conventional format:
96+
97+
```bash
98+
gh pr merge <PR_NUMBER> --auto --squash --delete-branch \
99+
--subject "feat: <concise summary in imperative mood>" \
100+
--body "$(cat <<'EOF'
101+
<Detailed description of changes>
102+
103+
<Why these changes were made>
104+
105+
Closes #<issue-number>
106+
EOF
107+
)"
108+
```
109+
110+
**Example:**
111+
112+
```bash
113+
gh pr merge 135 --auto --squash --delete-branch \
114+
--subject "feat: implement CraftingSystem for Epic 4.7" \
115+
--body "$(cat <<'EOF'
116+
Implements the CraftingSystem that processes active crafting sessions,
117+
determines outcomes using CraftingOutcomeRule, and awards XP.
118+
119+
This completes Epic 4.7 by adding the system that executes craft
120+
attempts and integrates with the existing class progression system.
121+
122+
Closes #38
123+
EOF
124+
)"
125+
```
126+
96127
4. **Maintainer** starts code review
97128
1. Persona subagents review (Fantasy Author, Casual Game Expert, .NET Specialist)
98129
2. Tech Lead persona collates all feedback into consolidated review:

PROMPT.md

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
> - Read CLAUDE.md and AGENTS.md before starting
77
> - Never use `--no-verify` to bypass git-hook verifications - always fix the root cause
88
> - Never use `--admin` to force the merge of a PR
9-
> - **Always verify GitHub account before PR operations** - Contributor opens PRs, Maintainer - CLAUDE.local.md for account details
9+
> - **MANDATORY: Verify BOTH git config AND GitHub CLI account before ANY PR operations**
10+
> - Run `git config user.email` AND `gh auth status` to verify correct account
11+
> - Contributor (martincjarvis) opens PRs and commits code
12+
> - Maintainer (mcj-coder) reviews and merges PRs
13+
> - See CLAUDE.local.md "CRITICAL: Verify Both Git and GitHub CLI Credentials" section
1014
> - All changes need to be done via feature branch and merged via PR
1115
> - Work as `Contributor` implementing code changes and raising PR's. Do not review PR's unless explicitly prompted by the user - just monitor active PR and Issues for comment feedback.
1216
@@ -104,14 +108,17 @@ See **[docs/plans/rules-engine-design.md](docs/plans/rules-engine-design.md)** f
104108

105109
### Workflow Rules (CRITICAL)
106110

107-
1. Work as Contributor
108-
2. Check for GitHub issue before any work
109-
3. Create feature branch: `feature/<issue>-<description>`
110-
4. Write failing tests first
111-
5. Implement to pass tests
112-
6. Run `dotnet build --warnaserror && dotnet test`
113-
7. Commit with: `<type>: <description>\n\nRefs #<issue>`
114-
8. Create PR and request review
111+
1. **FIRST: Verify credentials** - Run `./scripts/verify-credentials.sh contributor` before any work
112+
2. Work as Contributor
113+
3. Check for GitHub issue before any work
114+
4. Create feature branch: `feature/<issue>-<description>`
115+
5. Write failing tests first
116+
6. Implement to pass tests
117+
7. Run `dotnet build --warnaserror && dotnet test`
118+
8. **BEFORE COMMIT: Re-verify credentials** - Run `./scripts/verify-credentials.sh contributor`
119+
9. Commit with: `<type>: <description>\n\nRefs #<issue>`
120+
10. **BEFORE PR: Re-verify credentials** - Run `./scripts/verify-credentials.sh contributor`
121+
11. Create PR and request review
115122

116123
### Commit Types
117124

docs/plans/rules-engine-design.md

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Complete Epic 4 (Crafting and Class Progression) to enable full crafting mechani
2323
| 1 | Project Foundation | ✅ Complete | 5/5 | #3 |
2424
| 2 | Time and Simulation Loop | ✅ Complete | 6/6 | #4 |
2525
| 3 | NPC Decision Making | ✅ Complete | 6/6 | #5 |
26-
| 4 | Crafting and Class Progression | 🔄 In Progress | 6/8 | #6 |
26+
| 4 | Crafting and Class Progression | 🔄 In Progress | 7/8 | #6 |
2727
| 5 | Economy and Inventory | ⏳ Planned | 0/6 | #7 |
2828
| 6 | Contracts and Commitments | 🔄 Partial | 2/6 | #8 |
2929
| 7 | Settlement and Guild | ⏳ Planned | 0/6 | #9 |
@@ -32,25 +32,23 @@ Complete Epic 4 (Crafting and Class Progression) to enable full crafting mechani
3232
| 10 | Apprenticeship and Role Stacking | ⏳ Planned | 0/4 | #12 |
3333
| 11 | Full Progression Scenario | ⏳ Planned | 0/5 | #13 |
3434

35-
**Total Progress**: 25/58 tasks complete (43%)
35+
**Total Progress**: 26/58 tasks complete (45%)
3636

3737
### Recent Completions
3838

39+
-**2026-01-19**: Epic 4.7 - CraftingSystem (#38, PR #135)
3940
-**2026-01-19**: Epic 4.6 - CraftingOutcomeRule (#37, PR #134)
4041
-**2026-01-19**: Epic 4.5 - Define RecipeDefinition (#36, PR #127, commit 8148f26)
4142
-**2026-01-19**: Epic 4.4 - ClassUnlockRule (#35, PR #126)
4243
-**2026-01-19**: Epic 4.3 - XpCalculator (#34, PR #125)
4344
-**2026-01-19**: Epic 4.2 - ClassProgressCollection (#33, PR #124)
4445
-**2026-01-19**: Epic 4.1 - ClassDefinition and SkillDefinition (#32, PR #122, #121)
45-
-**2026-01-18**: Epic 3.6 - Test personality effects (#31, PR #119, #123)
4646

4747
### Next Tasks
4848

4949
Priority order for remaining work:
5050

51-
1. **Epic 4.6** - #37: Implement CraftingOutcomeRule
52-
2. **Epic 4.7** - #38: Implement CraftingSystem
53-
3. **Epic 4.8** - #39: Implement Masterwork → Master rank trigger
51+
1. **Epic 4.8** - #39: Implement Masterwork → Master rank trigger
5452

5553
## Key Design Decisions
5654

@@ -190,7 +188,7 @@ _For implementation patterns, examine referenced code paths._
190188

191189
**Goal**: Crafting produces items, gains XP, unlocks classes
192190

193-
**Status**: In Progress (6/8 tasks) | **Epic Issue**: #6
191+
**Status**: In Progress (7/8 tasks) | **Epic Issue**: #6
194192

195193
#### Sub-issues
196194

@@ -240,13 +238,17 @@ _For implementation patterns, examine referenced code paths._
240238
- ✅ Distribution verification (reasonable outcome probabilities)
241239
- **Verified**: 20+ tests pass, outcomes distributed correctly
242240

243-
**4.7 Implement CraftingSystem**_Issue #38_
244-
245-
- Execute craft action
246-
- Consume materials, produce item
247-
- Award XP
248-
- Emit CraftingCompletedEvent
249-
- **Verify**: Crafting produces items, awards XP
241+
**4.7 Implement CraftingSystem**_Issue #38, PR #135_
242+
243+
- ✅ CraftId value object for unique craft identification
244+
- ✅ ActiveCraft component for tracking in-progress crafts
245+
- ✅ CraftingCompletedEvent for completion notifications
246+
- ✅ Extended Character with ClassProgress and ActiveCraft properties
247+
- ✅ CraftingSystem processes active crafts at completion time
248+
- ✅ Outcome determination via CraftingOutcomeRule
249+
- ✅ XP calculation and awarding to applicable classes
250+
- ✅ Event emission with outcome details
251+
- **Verified**: 8 tests pass, crafting produces items and awards XP, all 511 tests pass
250252

251253
**4.8 Implement Masterwork → Master rank trigger**_Issue #39_
252254

docs/playbooks/workflow-verification.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,13 @@ This playbook documents the verification of CI/CD and development workflow compo
2121
- [x] Build job runs unit tests
2222
- [x] Build job runs Reqnroll BDD scenario tests
2323
- [x] Danger job runs on PRs only (validates process)
24-
- [x] **PR auto-merges** when all checks pass (`gh pr merge --auto --delete-branch`)
24+
- [x] **PR auto-merges** when all checks pass with squash commit:
25+
26+
```bash
27+
gh pr merge <PR> --auto --squash --delete-branch \
28+
--subject "<type>: <summary>" \
29+
--body "<description>\n\nCloses #<issue>"
30+
```
2531

2632
### DangerJS Validations (All Failures, No Warnings)
2733

docs/roles/tech-lead.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,23 @@ All major decisions should have ADRs:
153153
- Casual Game Expert (UX/engagement)
154154
- .NET Specialist (implementation)
155155
3. **Tech Lead** collates all feedback into consolidated review
156-
4. **Maintainer** submits review and enables auto-merge:
156+
4. **Maintainer** submits review and enables auto-merge with squash commit:
157157

158158
```bash
159-
gh pr merge --auto --delete-branch
159+
gh pr merge <PR_NUMBER> --auto --squash --delete-branch \
160+
--subject "<type>: <summary>" \
161+
--body "$(cat <<'EOF'
162+
<detailed description>
163+
164+
<rationale>
165+
166+
Closes #<issue-number>
167+
EOF
168+
)"
160169
```
161170
171+
Use conventional commit types: `feat`, `fix`, `refactor`, `docs`, `test`, `chore`
172+
162173
5. **PR auto-merges** when all CI checks pass (lint, build, tests, DangerJS)
163174
6. **Issue auto-closes** via `Closes #N` in PR description
164175

scripts/verify-credentials.sh

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#!/bin/bash
2+
# Verify that git config and GitHub CLI authentication are consistent
3+
# Reads expected credentials from CLAUDE.local.md table
4+
# Exit with error if mismatch detected
5+
6+
set -e
7+
8+
ROLE="${1:-contributor}" # Default to contributor role
9+
ROLE_CAPITALIZED="$(tr '[:lower:]' '[:upper:]' <<< ${ROLE:0:1})${ROLE:1}" # Capitalize first letter
10+
11+
# Path to CLAUDE.local.md
12+
CLAUDE_LOCAL="${CLAUDE_LOCAL:-./CLAUDE.local.md}"
13+
14+
if [ ! -f "$CLAUDE_LOCAL" ]; then
15+
echo "❌ ERROR: $CLAUDE_LOCAL not found"
16+
echo ""
17+
echo "This script requires CLAUDE.local.md with role configuration table."
18+
echo "See CLAUDE.md for setup instructions."
19+
exit 1
20+
fi
21+
22+
# Parse CLAUDE.local.md table to extract credentials for the role
23+
# Table format: | Role | GitHub Account | Git Email | Git GPG Key | Git Username |
24+
# Find the line with the role and extract the GitHub account (column 3) and email (column 4)
25+
ACCOUNT_LINE=$(grep -i "| $ROLE_CAPITALIZED" "$CLAUDE_LOCAL" | grep -E '\| [^ ]+ +\|' | head -1)
26+
EXPECTED_GH_ACCOUNT=$(echo "$ACCOUNT_LINE" | awk -F'|' '{gsub(/^[ \t]+|[ \t]+$/, "", $3); print $3}')
27+
EXPECTED_GIT_EMAIL=$(echo "$ACCOUNT_LINE" | awk -F'|' '{gsub(/^[ \t]+|[ \t]+$/, "", $4); print $4}')
28+
29+
# Validate that we found the role in the table
30+
if [ -z "$EXPECTED_GIT_EMAIL" ] || [ -z "$EXPECTED_GH_ACCOUNT" ]; then
31+
echo "❌ ERROR: Could not find credentials for role '$ROLE' in $CLAUDE_LOCAL"
32+
echo ""
33+
echo "Available roles should be listed in the GitHub & Git Accounts table."
34+
exit 1
35+
fi
36+
37+
# Get current credentials
38+
CURRENT_GIT_EMAIL=$(git config user.email)
39+
CURRENT_GH_ACCOUNT=$(gh auth status 2>&1 | grep "Logged in to github.com account" | sed 's/.*account \([^ ]*\).*/\1/')
40+
41+
echo "🔍 Verifying credentials for role: $ROLE"
42+
echo ""
43+
echo "Git config:"
44+
echo " Expected: $EXPECTED_GIT_EMAIL"
45+
echo " Current: $CURRENT_GIT_EMAIL"
46+
echo ""
47+
echo "GitHub CLI:"
48+
echo " Expected: $EXPECTED_GH_ACCOUNT"
49+
echo " Current: $CURRENT_GH_ACCOUNT"
50+
echo ""
51+
52+
ERRORS=0
53+
54+
if [ "$CURRENT_GIT_EMAIL" != "$EXPECTED_GIT_EMAIL" ]; then
55+
echo "❌ ERROR: Git email mismatch!"
56+
echo " Run: git config user.email \"$EXPECTED_GIT_EMAIL\""
57+
ERRORS=$((ERRORS + 1))
58+
fi
59+
60+
if [ "$CURRENT_GH_ACCOUNT" != "$EXPECTED_GH_ACCOUNT" ]; then
61+
echo "❌ ERROR: GitHub CLI account mismatch!"
62+
echo " Run: gh auth login (and authenticate as $EXPECTED_GH_ACCOUNT)"
63+
ERRORS=$((ERRORS + 1))
64+
fi
65+
66+
if [ $ERRORS -eq 0 ]; then
67+
echo "✅ All credentials verified for $ROLE role"
68+
exit 0
69+
else
70+
echo ""
71+
echo "❌ Found $ERRORS credential mismatch(es)"
72+
echo ""
73+
echo "See CLAUDE.local.md for account switching instructions"
74+
exit 1
75+
fi
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using FantasyRpgWorld.Core.Domain.ValueObjects;
2+
3+
namespace FantasyRpgWorld.Core.Domain.Components;
4+
5+
/// <summary>
6+
/// Represents an active crafting session in progress.
7+
/// Tracks the recipe being crafted, timing, and quality modifiers.
8+
/// </summary>
9+
public sealed record ActiveCraft
10+
{
11+
public CraftId CraftId { get; init; }
12+
public RecipeId RecipeId { get; init; }
13+
public CharacterId CrafterId { get; init; }
14+
public GameTime StartTime { get; init; }
15+
public GameTime CompletionTime { get; init; }
16+
public int SkillModifier { get; init; }
17+
public int MaterialModifier { get; init; }
18+
public int ToolModifier { get; init; }
19+
public int WorkspaceModifier { get; init; }
20+
21+
private ActiveCraft(
22+
CraftId craftId,
23+
RecipeId recipeId,
24+
CharacterId crafterId,
25+
GameTime startTime,
26+
GameTime completionTime,
27+
int skillModifier,
28+
int materialModifier,
29+
int toolModifier,
30+
int workspaceModifier)
31+
{
32+
CraftId = craftId;
33+
RecipeId = recipeId;
34+
CrafterId = crafterId;
35+
StartTime = startTime;
36+
CompletionTime = completionTime;
37+
SkillModifier = skillModifier;
38+
MaterialModifier = materialModifier;
39+
ToolModifier = toolModifier;
40+
WorkspaceModifier = workspaceModifier;
41+
}
42+
43+
/// <summary>
44+
/// Starts a new crafting session.
45+
/// </summary>
46+
public static ActiveCraft Start(
47+
CraftId craftId,
48+
RecipeId recipeId,
49+
CharacterId crafterId,
50+
GameTime startTime,
51+
GameTime completionTime,
52+
int skillModifier = 0,
53+
int materialModifier = 0,
54+
int toolModifier = 0,
55+
int workspaceModifier = 0)
56+
{
57+
return new ActiveCraft(
58+
craftId,
59+
recipeId,
60+
crafterId,
61+
startTime,
62+
completionTime,
63+
skillModifier,
64+
materialModifier,
65+
toolModifier,
66+
workspaceModifier);
67+
}
68+
69+
/// <summary>
70+
/// Updates the quality modifiers for this crafting session.
71+
/// </summary>
72+
public ActiveCraft WithModifiers(
73+
int skillModifier,
74+
int materialModifier,
75+
int toolModifier,
76+
int workspaceModifier)
77+
{
78+
return this with
79+
{
80+
SkillModifier = skillModifier,
81+
MaterialModifier = materialModifier,
82+
ToolModifier = toolModifier,
83+
WorkspaceModifier = workspaceModifier
84+
};
85+
}
86+
87+
/// <summary>
88+
/// Checks if the craft is complete at the given time.
89+
/// </summary>
90+
public bool IsComplete(GameTime currentTime) => currentTime >= CompletionTime;
91+
}

0 commit comments

Comments
 (0)