Docker Helper Scripts
Przegląd
System zawiera zestaw helper scripts dostępnych w środowisku Docker, które automatyzują kluczowe operacje w lifecycle zadania. Helper scripts są montowane do kontenera i dostępne pod /workspace/files/helpers/.
Przegląd Helper Scripts
| Script | Faza | Opis | Executor |
|---|---|---|---|
init_workspace.sh | START | Inicjalizacja workspace - klonowanie repozytoriów | bash |
backup_task_md.sh | START | Backup oryginalnego task.md | bash |
move_task_md.sh | END | Przeniesienie task_plan.md + restore task.md | bash |
persist_git_changes.sh | END | Commitowanie zmian + diff | bash |
github_push_mr.sh | END | Push + utworzenie PR/MR | bash |
create_subtask | ANY | Dynamiczne tworzenie follow-up subtasków | bash |
init_workspace.sh
Cel
Inicjalizuje workspace poprzez klonowanie wszystkich repozytoriów zdefiniowanych w task.json i checkout na odpowiednie branches.
Użycie
W task.json (start_commands):
{
"id": "init_workspace",
"catalog": "START",
"executor": "bash",
"command": "bash /workspace/files/helpers/init_workspace.sh",
"dependencies": []
}Workflow
1. Odczyt task.json
↓
2. Dla każdego repository w task.json.repositories[]:
↓
2.1. Clone repository do workspace/{folder}
git clone {git_url} workspace/{folder}
↓
2.2. Checkout target_branch
git checkout {target_branch}
↓
2.3. Create lub checkout working_branch
git checkout -b {working_branch} || git checkout {working_branch}
↓
2.4. Pull latest changes (jeśli branch już istnieje remote)
git pull origin {working_branch}
↓
3. Log rezultatuPrzykład task.json
{
"repositories": [
{
"folder": "sembot-angular",
"git_url": "[email protected]:sembot-io/sembot-angular.git",
"target_branch": "master",
"working_branch": "feature/DEV-7315"
},
{
"folder": "sembot-backend",
"git_url": "[email protected]:sembot-io/sembot-backend.git",
"target_branch": "develop",
"working_branch": "feature/DEV-7315-backend"
}
]
}Output
📦 Initializing workspace...
📂 Repository 1/2: sembot-angular
🔽 Cloning repository...
git clone [email protected]:sembot-io/sembot-angular.git workspace/sembot-angular
✅ Cloned successfully
🌿 Checking out target branch: master
✅ On branch: master
🔀 Creating working branch: feature/DEV-7315
✅ Branch created and checked out
📂 Repository 2/2: sembot-backend
...
✅ Workspace initialized successfully
Repositories: 2
Working directory: /workspaceError Handling
Clone failed:
- Log error z git output
- Exit code: 1
- Task zostaje przeniesiony do
failed/
Branch creation failed:
- Próba checkout istniejącego brancha
- Jeśli nadal błąd → exit code: 1
SSH key issues:
- Sprawdzenie czy SSH key jest dostępny w kontenerze
- Hint w logach o konfiguracji SSH
backup_task_md.sh
Cel
Tworzy backup oryginalnego task.md przed jego modyfikacją przez planning commands. Backup jest używany później do restore w fazie END.
Użycie
W task.json (start_commands):
{
"id": "backup_task",
"catalog": "START",
"executor": "bash",
"command": "bash /workspace/files/helpers/backup_task_md.sh",
"dependencies": ["init_workspace"]
}Workflow
1. Sprawdź czy task.md istnieje
↓
2. Skopiuj task.md → task_original.md
cp /task/task.md /task/task_original.md
↓
3. Log rezultatuStruktura Plików
Przed backup:
/task/
├── task.json
└── task.md ← oryginalne wymagania użytkownikaPo backup:
/task/
├── task.json
├── task.md ← oryginalne wymagania
└── task_original.md ← backupPo planning (task.md zostaje nadpisany):
/task/
├── task.json
├── task.md ← plan wygenerowany przez AI
└── task_original.md ← oryginalne wymagania (backup)Output
📋 Backing up task.md...
📂 Source: /task/task.md
📂 Destination: /task/task_original.md
✅ Backup created successfullyError Handling
task.md nie istnieje:
❌ Error: task.md not found at /task/task.md
Cannot create backup.Exit code: 1
Brak uprawnień do zapisu:
❌ Error: Permission denied when creating backupExit code: 1
move_task_md.sh
Cel
W fazie END, przenosi plan wygenerowany przez AI (task.md) do task_plan.md oraz przywraca oryginalne wymagania użytkownika (task_original.md → task.md).
Użycie
W task.json (start_commands):
{
"id": "move_task_spec",
"catalog": "END",
"executor": "bash",
"command": "bash /workspace/files/helpers/move_task_md.sh",
"dependencies": ["plan_task"]
}Workflow
1. Sprawdź czy task_original.md istnieje
↓
2. Przenieś task.md → task_plan.md
mv /task/task.md /task/task_plan.md
↓
3. Przywróć task_original.md → task.md
cp /task/task_original.md /task/task.md
↓
4. Log rezultatuStruktura Plików
Przed move_task_md.sh:
/task/
├── task.json
├── task.md ← plan wygenerowany przez AI
└── task_original.md ← backup oryginalnych wymagańPo move_task_md.sh:
/task/
├── task.json
├── task.md ← oryginalne wymagania (przywrócone)
├── task_plan.md ← plan wygenerowany przez AI (przeniesiony)
└── task_original.md ← backup (zachowany)Uzasadnienie
Dlaczego restore task.md?
- Oryginalny task.md zawiera wymagania użytkownika
- task_plan.md to tylko plan wykonania (artefakt pośredni)
- W final verification potrzebujemy oryginalnych wymagań
- Dla biznesu/review ważne są user requirements, nie plan
Output
📋 Moving task spec files...
📂 Moving task.md → task_plan.md
✅ Plan saved as task_plan.md
📂 Restoring task_original.md → task.md
✅ Original requirements restored
✅ Task spec files organized successfullyError Handling
task_original.md nie istnieje:
⚠️ Warning: task_original.md not found
Skipping restore, keeping current task.mdExit code: 0 (warning, nie error - może nie było backup)
Brak task.md:
❌ Error: task.md not found, nothing to moveExit code: 1
persist_git_changes.sh
Cel
Commituje wszystkie zmiany w repozytoriach i generuje git diff dla dokumentacji.
Użycie
W task.json (start_commands):
{
"id": "persist_git",
"catalog": "END",
"executor": "bash",
"command": "bash /workspace/files/helpers/persist_git_changes.sh",
"dependencies": ["move_task_spec"]
}Workflow
1. Dla każdego repository w task.json.repositories[]:
↓
1.1. Git add wszystkie zmiany
git add .
↓
1.2. Sprawdź czy są zmiany do commit
git diff --cached --quiet
↓
1.3. Jeśli są zmiany:
- Wygeneruj commit message (przez AI lub template)
- Git commit z message
- Zapisz git diff do /task/artifacts/diffs/{folder}.diff
↓
1.4. Jeśli brak zmian:
- Log "No changes"
- Skip commit
↓
2. Podsumowanie wszystkich repozytoriówCommit Message
AI-generated (domyślnie):
# Używa AI (Haiku) do wygenerowania commit message
AI_PROVIDER="claude"
AI_MODEL="haiku"
# Prompt dla AI
PROMPT="Generate concise commit message for these changes:
$(git diff --cached --stat)
Format: <type>: <description>
Types: feat, fix, refactor, test, docs"
COMMIT_MSG=$(ai_generate "$PROMPT")Template (fallback):
# Jeśli AI niedostępne
COMMIT_MSG="feat: Implement changes for ${TASK_ID}
Generated with Claude Code
Co-Authored-By: Claude Sonnet 4.5 <[email protected]>"Git Diff Export
Struktura:
/task/artifacts/diffs/
├── sembot-angular.diff # diff dla pierwszego repo
├── sembot-backend.diff # diff dla drugiego repo
└── summary.md # podsumowanie wszystkich zmianFormat diff:
diff --git a/src/app/settings/settings.component.ts b/src/app/settings/settings.component.ts
index 1234567..abcdefg 100644
--- a/src/app/settings/settings.component.ts
+++ b/src/app/settings/settings.component.ts
@@ -10,6 +10,10 @@ export class SettingsComponent {
+ toggleDarkMode() {
+ this.isDarkMode = !this.isDarkMode;
+ }
+
ngOnInit() {
// ...
}Output
📝 Persisting git changes...
📂 Repository 1/2: sembot-angular
📊 Changes detected:
5 files changed, 120 insertions(+), 30 deletions(-)
💬 Generating commit message...
feat: Add dark mode toggle to settings
✅ Changes committed
Commit: a1b2c3d4
📄 Diff exported: /task/artifacts/diffs/sembot-angular.diff
📂 Repository 2/2: sembot-backend
ℹ️ No changes detected
Skipping commit
✅ Git changes persisted successfully
Committed repositories: 1/2
Total changes: 5 files, 120 insertions(+), 30 deletions(-)Error Handling
Git commit failed:
❌ Error: Git commit failed for repository: sembot-angular
Output: [git error message]Exit code: 1
Diff export failed:
⚠️ Warning: Could not export diff for sembot-angular
Continuing with commit...Exit code: 0 (warning)
github_push_mr.sh
Cel
Pushuje zmiany do remote repository i tworzy Pull Request (GitHub) lub Merge Request (GitLab) z automatycznym assignee.
Użycie
W task.json (start_commands):
{
"id": "github_push_mr",
"catalog": "END",
"executor": "bash",
"command": "bash /workspace/files/helpers/github_push_mr.sh",
"dependencies": ["persist_git"]
}Workflow
1. Dla każdego repository w task.json.repositories[]:
↓
1.1. Push do remote branch
git push -u origin {working_branch}
↓
1.2. Sprawdź czy istnieje MR/PR
- Odczyt merge_request_id z task.json
- Jeśli null → create new
- Jeśli not null → skip (already exists)
↓
1.3. Create Pull Request/Merge Request
- GitHub: gh pr create
- GitLab: glab mr create
↓
1.4. Assign PR/MR
- Assignee z issue.assignee_github_id
- GitHub: gh pr edit --add-assignee
- GitLab: glab mr update --assignee
↓
1.5. Zapisz MR/PR info do task.json
- merge_request_id
- merge_request_url
↓
2. Podsumowanie wszystkich repozytoriówPR/MR Title i Body
Title:
{issue.id}: {title}
Przykład: DEV-7315: Settings UI UnificationBody (template):
## Summary
[1-3 bullet points z podsumowaniem zmian]
## Changes
- [Lista głównych zmian]
- [Per repository]
## Test Plan
- [ ] Build passes
- [ ] Unit tests pass
- [ ] Visual verification completed
- [ ] Manual testing done
## Related
- Issue: {issue.url}
- Task: {task_id}
---
🤖 Generated with [Claude Code](https://claude.com/claude-code)Draft PR Support
W task.json:
{
"repositories": [
{
"folder": "sembot-angular",
"merge_request_create_as_draft": true // ← create as draft
}
]
}GitHub:
if [ "$CREATE_AS_DRAFT" = true ]; then
gh pr create --draft --title "$TITLE" --body "$BODY"
else
gh pr create --title "$TITLE" --body "$BODY"
fiGitLab:
if [ "$CREATE_AS_DRAFT" = true ]; then
glab mr create --draft --title "$TITLE" --description "$BODY"
else
glab mr create --title "$TITLE" --description "$BODY"
fiAktualizacja task.json
Przed push:
{
"repositories": [
{
"folder": "sembot-angular",
"working_branch": "feature/DEV-7315",
"merge_request_id": null,
"merge_request_url": null
}
]
}Po push i create PR:
{
"repositories": [
{
"folder": "sembot-angular",
"working_branch": "feature/DEV-7315",
"merge_request_id": "123", // ← PR number
"merge_request_url": "https://github.com/org/repo/pull/123" // ← PR URL
}
]
}Output
🚀 Pushing changes and creating PR/MR...
📂 Repository 1/2: sembot-angular
📤 Pushing to remote...
git push -u origin feature/DEV-7315
✅ Pushed successfully
🔍 Checking for existing PR/MR...
ℹ️ No existing PR found (merge_request_id: null)
📝 Creating Pull Request...
Title: DEV-7315: Settings UI Unification
Base: master ← feature/DEV-7315
✅ PR created: https://github.com/sembot-io/sembot-angular/pull/123
👤 Assigning PR...
Assignee: techleadgithub
✅ Assigned successfully
💾 Updating task.json...
✅ MR info saved
📂 Repository 2/2: sembot-backend
ℹ️ No changes to push (no commits)
✅ Push and PR creation completed
PRs created: 1/2
Total PRs: 1Error Handling
Push failed (no permissions):
❌ Error: Push failed for repository: sembot-angular
Permission denied (publickey)
Hint: Check SSH key configuration in DockerExit code: 1
PR creation failed (already exists):
⚠️ Warning: PR already exists for branch feature/DEV-7315
URL: https://github.com/sembot-io/sembot-angular/pull/123
Skipping PR creation, updating task.json with existing PRExit code: 0
Assignee not found:
⚠️ Warning: Could not assign PR to: techleadgithub
User not found or no permissions
PR created successfully but not assignedExit code: 0
create_subtask (Helper)
Cel
Umożliwia dynamiczne tworzenie follow-up subtasków podczas wykonywania innych subtasków. Używane głównie przez review/test/qa role do tworzenia tasków fix.
Użycie
W subtask (np. podczas review):
create_subtask <priority> <role> <title> <description> [dependencies]Parametry
| Parameter | Required | Description | Example |
|---|---|---|---|
| priority | Yes | START, P0, P1, P2, P3, END | P0 |
| role | Yes | frontend, backend, test, qa, reviewer, etc. | frontend |
| title | Yes | Krótki, opisowy tytuł | Fix Login Form Crash |
| description | Yes | Szczegółowy opis (wielolinijkowy OK) | Security vulnerability found... |
| dependencies | No | Oddzielone przecinkami ID tasków | frontend_abc123,backend_def456 |
Przykłady Użycia
1. Prosty fix (bez dependencies):
create_subtask P0 frontend \
"Fix Login Form Crash" \
"Login form crashes when user clicks submit with empty email field.
Error: Cannot read property 'value' of null.
Steps to reproduce:
1. Open login page
2. Click submit without entering email
3. App crashes
Expected: Show validation error
Actual: App crashes"2. Fix z dependencies:
create_subtask P1 backend \
"Fix Password Validation Bug" \
"Password validation accepts passwords shorter than 8 characters.
Should enforce minimum 8 characters.
Found during testing: test_auth_validation_ghi789" \
"backend_auth_api_def456"3. Multiple dependencies:
create_subtask P0 frontend \
"Fix Settings Menu Icons" \
"Menu icons not visible on mobile viewport.
Affects: Settings, Profile, Dashboard" \
"frontend_settings_abc123,ux_design_icons_xyz789"Workflow
1. Parsowanie parametrów
↓
2. Generowanie unique ID
{role}_{random_hash}
↓
3. Tworzenie katalog subtask
/task/subtasks/{priority}/todo/{role}_{id}/
↓
4. Tworzenie task.json
- Przepisanie ai.provider, ai.model z parent
- Ustawienie dependencies
- Metadata (created_at, etc.)
↓
5. Tworzenie task.md
- Title jako header
- Description jako content
- Evidence links (jeśli dostępne)
↓
6. Log creation
- Orchestration log
- Webhook notification
↓
7. Return subtask IDGenerowany task.json
{
"task_id": "frontend_fix_login_a1b2c3d4",
"priority": "P0",
"title": "Fix Login Form Crash",
"why": "Created automatically during review - critical bug found",
"dependencies": ["frontend_login_form_abc123"],
"ai": {
"provider": "claude",
"model": "claude-sonnet-4",
"start_command": "/frontend /task/subtasks/P0/todo/frontend_fix_login_a1b2c3d4",
"sessions": {
"claude": null,
"codex": null,
"gemini": null
}
},
"created_at": "2025-12-31T14:30:00Z",
"created_by": "reviewer_tech_xyz789",
"updated_at": "2025-12-31T14:30:00Z",
"started_at": null,
"completed_at": null
}Generowany task.md
# Fix Login Form Crash
## Problem
Login form crashes when user clicks submit with empty email field.
Error: Cannot read property 'value' of null.
## Steps to Reproduce
1. Open login page
2. Click submit without entering email
3. App crashes
## Expected Behavior
Show validation error
## Actual Behavior
App crashes
## Evidence
- Created by: reviewer_tech_xyz789
- Found during: Technical review
- Related task: frontend_login_form_abc123
## Acceptance Criteria
- [ ] Form does not crash with empty email
- [ ] Validation error shown to user
- [ ] Unit test added to prevent regressionOutput
📝 Creating follow-up subtask...
🆔 Subtask ID: frontend_fix_login_a1b2c3d4
📊 Priority: P0
👤 Role: frontend
📌 Title: Fix Login Form Crash
🔗 Dependencies: frontend_login_form_abc123
📂 Creating directory: /task/subtasks/P0/todo/frontend_fix_login_a1b2c3d4/
📄 Writing task.json...
✅ task.json created
📄 Writing task.md...
✅ task.md created
📝 Logging to orchestration.log...
✅ Logged
🔔 Sending webhook notification...
Event: subtask_created
✅ Webhook sent
✅ Follow-up subtask created successfully
ID: frontend_fix_login_a1b2c3d4
Path: /task/subtasks/P0/todo/frontend_fix_login_a1b2c3d4/Role Commands z create_subtask
Przykład w /reviewer_product command:
# Krok 9: Jeśli znaleziono problemy
if [ $CRITICAL_ISSUES -gt 0 ] || [ $MAJOR_ISSUES -gt 0 ]; then
echo "⚠️ Issues found - creating follow-up tasks..."
# Critical issue
create_subtask P0 frontend \
"Fix Critical: Menu Icons Missing" \
"Menu icons not visible on mobile. Critical UX issue blocking release." \
"frontend_settings_menu_abc123"
# Major issue
create_subtask P1 frontend \
"Improve Error Messages" \
"Error messages not user-friendly. Confusing for end users." \
"frontend_validation_def456"
fiBest Practices
1. Jeden task = Jeden problem
# ❌ Źle: grupowanie wielu problemów
create_subtask P0 frontend \
"Fix Multiple Issues" \
"Fix crash, improve validation, update styles, add tests"
# ✅ Dobrze: osobny task per problem
create_subtask P0 frontend "Fix Crash" "..."
create_subtask P1 frontend "Improve Validation" "..."
create_subtask P2 frontend "Update Styles" "..."2. Dołącz dowody
# ✅ Link do evidence
create_subtask P0 frontend \
"Fix Visual Bug" \
"Menu icons missing on mobile.
Evidence:
- Screenshot: /task/verification/screenshots/23-mobile-settings.png
- Video: /task/verification/video/menu-bug.webm"3. Oznacz dependencies
# ✅ Jeśli fix zależy od innego taska
create_subtask P0 backend \
"Fix API Validation" \
"API accepts invalid data.
Depends on: backend_api_endpoint_def456 (must be completed first)" \
"backend_api_endpoint_def456"4. Priorytet based on impact
| Priority | Use Case | Example |
|---|---|---|
| P0 | Crashes, data loss, security, broken core features | App crashes, XSS vulnerability |
| P1 | Broken features, significant UX/performance issues | Feature doesn't work, slow page load |
| P2 | Minor issues, refactoring, coverage gaps | Missing error message, code duplication |
| P3 | Polish, documentation, nice-to-haves | Better styling, additional docs |
Montowanie Helper Scripts do Docker
docker-compose.yml Configuration
Wszystkie workery muszą mieć:
services:
worker:
image: your-worker-image
volumes:
- ./helpers:/workspace/files/helpers:ro # ← helper scripts (read-only)
- workspace_volume:/workspace # ← workspace dla repo
- ./task:/task # ← task spec i artifactsStruktura Katalogów w Docker
/workspace/
├── files/
│ └── helpers/
│ ├── init_workspace.sh
│ ├── backup_task_md.sh
│ ├── move_task_md.sh
│ ├── persist_git_changes.sh
│ ├── github_push_mr.sh
│ └── create_subtask
├── sembot-angular/ # ← repo 1
├── sembot-backend/ # ← repo 2
└── ...
/task/
├── task.json
├── task.md
├── artifacts/
│ ├── logs/
│ └── diffs/
└── subtasks/Permissions
Helper scripts muszą być executable:
chmod +x helpers/*.sh
chmod +x helpers/create_subtaskW Dockerfile:
# Upewnij się że helper scripts są executable
RUN chmod +x /workspace/files/helpers/*.sh
RUN chmod +x /workspace/files/helpers/create_subtaskError Handling - Ogólne Zasady
Exit Codes
| Code | Meaning | Action |
|---|---|---|
| 0 | Success | Continue |
| 1 | Error (recoverable) | Retry (jeśli retry_count < 1) |
| 2 | Error (permanent) | Fail immediately |
| 130 | User interrupt | Fail immediately |
Logging
Wszystkie helper scripts logują do:
/task/artifacts/logs/helpers/{script_name}.logFormat logu:
[2025-12-31 14:30:00] [INFO] init_workspace.sh: Starting workspace initialization
[2025-12-31 14:30:05] [INFO] init_workspace.sh: Cloning repository: sembot-angular
[2025-12-31 14:30:15] [SUCCESS] init_workspace.sh: Workspace initialized successfullyWebhook Notifications
Helper scripts mogą wysyłać webhooks:
# send_webhook.sh helper
send_webhook() {
local event_type=$1
local payload=$2
curl -X POST "$N8N_WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d "$payload"
}
# Przykład użycia w github_push_mr.sh
send_webhook "pr_created" '{
"task_id": "'"$TASK_ID"'",
"repository": "'"$REPO_FOLDER"'",
"pr_url": "'"$PR_URL"'",
"pr_number": "'"$PR_NUMBER"'"
}'Changelog
v2.0 - Advanced Helpers
- ✅ AI-generated commit messages (persist_git_changes.sh)
- ✅ Draft PR support (github_push_mr.sh)
- ✅ Dynamic subtask creation (create_subtask)
- ✅ Dependency tracking across helpers
- ✅ Webhook notifications per helper
v1.0 - Basic Helpers
- ✅ init_workspace.sh - Repository cloning
- ✅ backup_task_md.sh - Task backup
- ✅ move_task_md.sh - Spec organization
- ✅ persist_git_changes.sh - Git commits
- ✅ github_push_mr.sh - PR/MR creation