feat: archive zoo_backup for home sync
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
# Skill: code-review
|
||||
|
||||
Structured code review against implementation plan.
|
||||
|
||||
## Invoked by
|
||||
|
||||
🔍 Reviewer mode
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TICKET_KEY` | Jira issue key | `ESIDEPAISY-12081` |
|
||||
| `MODULE` | PAISY module name | `eau`, `eubp`, `svmeldungen` |
|
||||
|
||||
## Output
|
||||
|
||||
Markdown file: `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-review.md`
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Read the plan document
|
||||
|
||||
```bash
|
||||
cat docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-plan.md
|
||||
```
|
||||
|
||||
Extract: planned changes, affected files, expected patterns, acceptance criteria.
|
||||
|
||||
### 2. Read the test plan (if exists)
|
||||
|
||||
```bash
|
||||
cat docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-testplan.md
|
||||
```
|
||||
|
||||
Cross-reference: are all planned test cases implemented?
|
||||
|
||||
### 3. Get the diff
|
||||
|
||||
```bash
|
||||
cd /Users/pplate/git/paisy-<TICKET_KEY>
|
||||
git diff origin/current --name-only
|
||||
git diff origin/current --stat
|
||||
git diff origin/current
|
||||
```
|
||||
|
||||
### 4. Read changed files
|
||||
|
||||
For each changed file, read the full file to understand context — not just the diff hunks.
|
||||
|
||||
```bash
|
||||
cd /Users/pplate/git/paisy-<TICKET_KEY>
|
||||
git diff origin/current --name-only | while read f; do echo "=== $f ==="; done
|
||||
```
|
||||
|
||||
### 5. Run the review checklist
|
||||
|
||||
For each changed file, verify:
|
||||
|
||||
| # | Check | What to look for |
|
||||
|---|-------|-----------------|
|
||||
| 1 | Plan compliance | All plan items implemented? Nothing missing, nothing extra? |
|
||||
| 2 | Pattern correctness | Correct PAISY patterns used? (AbstractMeldung, Datenbaustein, ServiceCenter, EMFactory, JAXB) |
|
||||
| 3 | No `src.gen/` changes | Generated sources must never be modified manually |
|
||||
| 4 | Logging | `@Slf4j` or `@Log4j2` with parameterized messages (`log.debug("x: {}", v)`) — no string concatenation |
|
||||
| 5 | German domain terms | Domain terms preserved: `Fehlzeiten`, `Lohnkonto`, `Vorlaufsatz`, `Nachlaufsatz` |
|
||||
| 6 | Error handling | PAISY `F;` responses checked before parsing? Null-safe patterns? |
|
||||
| 7 | Date handling | Correct formatters? Empty date checks (`00.00.0000`, `0000000`, `9999999`)? |
|
||||
| 8 | Test coverage | Every new/modified public method has a test? Edge cases covered? |
|
||||
| 9 | Flyway migrations | Correct naming convention? Dual H2/Oracle? Type mapping correct? |
|
||||
| 10 | No hardcoded values | No hardcoded BBNR, sprint IDs, Epic keys, instance names? |
|
||||
| 11 | Field visibility | `protected` for shared fields, `private` with Lombok for DTOs? |
|
||||
| 12 | Annotations | Correct use of `@Service`/`@Lazy`, `@Transactional`, `@XmlElement`? |
|
||||
|
||||
### 6. Check test quality
|
||||
|
||||
```bash
|
||||
cd /Users/pplate/git/paisy-<TICKET_KEY>
|
||||
# Find new/modified test files
|
||||
git diff origin/current --name-only | grep -E "Test\.java$"
|
||||
```
|
||||
|
||||
For each test file:
|
||||
- Meaningful assertions (not just `assertNotNull`)?
|
||||
- Edge cases covered?
|
||||
- Mocking done correctly (Mockito patterns)?
|
||||
- Test naming convention: `test<What>_<Scenario>_<Expected>()`?
|
||||
|
||||
### 7. Run tests
|
||||
|
||||
```bash
|
||||
cd /Users/pplate/git/paisy-<TICKET_KEY>
|
||||
mvn test -pl java/modules/cs-modules/<MODULE> -f java/pom.xml
|
||||
```
|
||||
|
||||
### 8. Generate review document
|
||||
|
||||
Write `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-review.md`:
|
||||
|
||||
```markdown
|
||||
# Code Review: <TICKET_KEY> — <Summary>
|
||||
|
||||
**Datum:** <today>
|
||||
**Modul:** <MODULE>
|
||||
**Reviewer:** Roo (Reviewer)
|
||||
**Branch:** <branch name>
|
||||
**Status:** ✅ Approved / ⚠️ Approved with comments / ❌ Changes requested
|
||||
|
||||
---
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
<1-2 sentence summary of the review outcome>
|
||||
|
||||
## Geprüfte Dateien
|
||||
|
||||
| Datei | Änderung | Bewertung |
|
||||
|-------|---------|-----------|
|
||||
| `<path>` | Neu/Geändert | ✅ / ⚠️ / ❌ |
|
||||
|
||||
## Checkliste
|
||||
|
||||
| # | Prüfpunkt | Ergebnis | Anmerkung |
|
||||
|---|-----------|----------|-----------|
|
||||
| 1 | Plan-Konformität | ✅ | Alle geplanten Änderungen umgesetzt |
|
||||
| 2 | Pattern-Korrektheit | ✅ | AbstractMeldung korrekt erweitert |
|
||||
| 3 | Keine src.gen/ Änderungen | ✅ | — |
|
||||
| 4 | Logging | ⚠️ | Zeile 42: String-Konkatenation → parameterized |
|
||||
| 5 | Deutsche Domänenbegriffe | ✅ | — |
|
||||
| 6 | Fehlerbehandlung | ✅ | F;-Prüfung vorhanden |
|
||||
| 7 | Datumsbehandlung | ✅ | — |
|
||||
| 8 | Testabdeckung | ✅ | 7 Tests, alle bestanden |
|
||||
| 9 | Flyway-Migrationen | ✅ | H2 + Oracle korrekt |
|
||||
| 10 | Keine Hardcoded-Werte | ✅ | — |
|
||||
| 11 | Feld-Sichtbarkeit | ✅ | — |
|
||||
| 12 | Annotationen | ✅ | — |
|
||||
|
||||
## Befunde
|
||||
|
||||
### ⚠️ Hinweise (non-blocking)
|
||||
|
||||
1. **<file>:<line>** — <description of finding>
|
||||
- Empfehlung: <suggested fix>
|
||||
|
||||
### ❌ Blocker (must fix)
|
||||
|
||||
1. **<file>:<line>** — <description of critical finding>
|
||||
- Begründung: <why this must be fixed>
|
||||
|
||||
## Tests
|
||||
|
||||
- **Ausgeführt:** <N> Tests
|
||||
- **Bestanden:** <N> ✅
|
||||
- **Fehlgeschlagen:** <N> ❌
|
||||
- **Build:** ✅ Grün / ❌ Rot
|
||||
|
||||
## Empfehlung
|
||||
|
||||
<Final recommendation: merge / fix and re-review / reject>
|
||||
```
|
||||
|
||||
### 9. Store in BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"{TICKET_KEY}: Code review completed — {status}. {findings_count} findings ({blockers} blockers)."
|
||||
)
|
||||
```
|
||||
|
||||
## Expected Output
|
||||
|
||||
- Review document at `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-review.md`
|
||||
- All tests executed and results documented
|
||||
- Clear recommendation: merge / fix / reject
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| No plan document found | Review without plan — note in review that plan was missing |
|
||||
| Build fails | Document build failure as blocker, don't proceed with detailed review |
|
||||
| No tests found | Flag as blocker — every change needs tests |
|
||||
| Worktree not found | Check if `/Users/pplate/git/paisy-<TICKET_KEY>` exists, or use main repo with branch checkout |
|
||||
|
||||
## Severity Levels
|
||||
|
||||
| Level | Symbol | Meaning | Action |
|
||||
|-------|--------|---------|--------|
|
||||
| Blocker | ❌ | Must fix before merge | Changes requested |
|
||||
| Warning | ⚠️ | Should fix, not blocking | Approved with comments |
|
||||
| Info | ℹ️ | Suggestion for improvement | Approved |
|
||||
| OK | ✅ | No issues | — |
|
||||
|
||||
## Language
|
||||
|
||||
- Review document: **German**
|
||||
- Code references (class names, methods, patterns): English as-is
|
||||
- Checklist items: German
|
||||
@@ -0,0 +1,202 @@
|
||||
# Skill: create-flyway-migration
|
||||
|
||||
Generate Flyway migration SQL files for H2 and Oracle.
|
||||
|
||||
## Invoked by
|
||||
|
||||
💻 Code mode
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TICKET_KEY` | Jira issue key | `ESIDEPAISY-12081` |
|
||||
| `MODULE` | PAISY module name | `eau`, `eubp`, `svmeldungen`, `dabpv` |
|
||||
| `ENTITY_NAME` | Table or entity being changed | `eau_rueckmeldung`, `eubp_archiv` |
|
||||
| `CHANGE_TYPE` | Type of DDL change | `CREATE TABLE`, `ALTER TABLE`, `CREATE INDEX` |
|
||||
|
||||
## Output
|
||||
|
||||
- H2 migration: `java/modules/cs-modules/<MODULE>/src/main/resources/db/migration/H2/V{timestamp}__C_{revision}_{entity}.sql`
|
||||
- Oracle migration: `java/modules/cs-modules/<MODULE>/src/main/resources/db/migration/ORACLE/V{timestamp}__C_{revision}_{entity}.sql`
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Determine timestamp
|
||||
|
||||
Generate the Flyway version timestamp in the required format:
|
||||
|
||||
```bash
|
||||
date -u +"%Y_%m_%d_%H_%M_%S"
|
||||
```
|
||||
|
||||
Result format: `2026_04_23_10_06_07`
|
||||
|
||||
### 2. Get app revision
|
||||
|
||||
Read the current app revision from `version.json` in the repo root:
|
||||
|
||||
```bash
|
||||
cat version.json
|
||||
```
|
||||
|
||||
Or extract from the parent POM:
|
||||
|
||||
```bash
|
||||
grep -A1 '<revision>' java/pom.xml | head -2
|
||||
```
|
||||
|
||||
The revision is the major version number (e.g., `123` from `123.4.2`).
|
||||
|
||||
### 3. Construct filename
|
||||
|
||||
```
|
||||
V{timestamp}__C_{revision}_{entity_name}.sql
|
||||
```
|
||||
|
||||
Example: `V2026_04_23_10_06_07__C_123_eau_rueckmeldung.sql`
|
||||
|
||||
**Note:** Double underscore `__` between version and description is mandatory Flyway convention.
|
||||
|
||||
### 4. Determine migration directories
|
||||
|
||||
Locate the module's migration directories:
|
||||
|
||||
```bash
|
||||
ls java/modules/cs-modules/<MODULE>/src/main/resources/db/migration/
|
||||
```
|
||||
|
||||
Expected structure:
|
||||
- `db/migration/H2/` — H2-specific migrations
|
||||
- `db/migration/ORACLE/` — Oracle-specific migrations
|
||||
|
||||
If only one directory exists, the module may use a shared migration path. Check the module's `application.properties` for `spring.flyway.locations`.
|
||||
|
||||
### 5. Create H2 migration
|
||||
|
||||
H2 supports `IF NOT EXISTS` / `IF EXISTS` clauses:
|
||||
|
||||
```sql
|
||||
-- CREATE TABLE
|
||||
CREATE TABLE IF NOT EXISTS <ENTITY_NAME> (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
-- columns...
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- ALTER TABLE (add column)
|
||||
ALTER TABLE <ENTITY_NAME> ADD COLUMN IF NOT EXISTS <column_name> <type>;
|
||||
|
||||
-- CREATE INDEX
|
||||
CREATE INDEX IF NOT EXISTS idx_<entity>_<column> ON <ENTITY_NAME>(<column>);
|
||||
|
||||
-- DROP COLUMN
|
||||
ALTER TABLE <ENTITY_NAME> DROP COLUMN IF EXISTS <column_name>;
|
||||
```
|
||||
|
||||
### 6. Create Oracle migration
|
||||
|
||||
Oracle does NOT support `IF NOT EXISTS` — use PL/SQL blocks for idempotency when needed:
|
||||
|
||||
```sql
|
||||
-- CREATE TABLE (simple — fails if exists, which is expected for versioned migrations)
|
||||
CREATE TABLE <ENTITY_NAME> (
|
||||
id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||
-- columns...
|
||||
created_at TIMESTAMP DEFAULT SYSTIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT SYSTIMESTAMP
|
||||
);
|
||||
|
||||
-- ALTER TABLE (add column — idempotent wrapper)
|
||||
BEGIN
|
||||
EXECUTE IMMEDIATE 'ALTER TABLE <ENTITY_NAME> ADD <column_name> <type>';
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
IF SQLCODE = -1430 THEN NULL; -- column already exists
|
||||
ELSE RAISE;
|
||||
END IF;
|
||||
END;
|
||||
/
|
||||
|
||||
-- CREATE INDEX
|
||||
CREATE INDEX idx_<entity>_<column> ON <ENTITY_NAME>(<column>);
|
||||
```
|
||||
|
||||
### 7. Type mapping reference
|
||||
|
||||
| Java/H2 Type | Oracle Type | Notes |
|
||||
|--------------|-------------|-------|
|
||||
| `BIGINT` | `NUMBER(19)` | Primary keys |
|
||||
| `INTEGER` | `NUMBER(10)` | Standard integers |
|
||||
| `VARCHAR(n)` | `VARCHAR2(n)` | Strings |
|
||||
| `BOOLEAN` | `NUMBER(1)` | Oracle has no native boolean |
|
||||
| `TIMESTAMP` | `TIMESTAMP` | Same |
|
||||
| `CLOB` | `CLOB` | Same |
|
||||
| `BLOB` | `BLOB` | Same |
|
||||
| `AUTO_INCREMENT` | `GENERATED ALWAYS AS IDENTITY` | Identity columns |
|
||||
| `CURRENT_TIMESTAMP` | `SYSTIMESTAMP` | Default timestamp |
|
||||
|
||||
### 8. Register migration location (if new module)
|
||||
|
||||
If this is the first migration for the module, ensure the Flyway location is configured in the module's properties or EMFactory:
|
||||
|
||||
```java
|
||||
// In EMFactory or FlywayController setup
|
||||
flyway.migrate("<MODULE>", "<timestamp>");
|
||||
```
|
||||
|
||||
Check existing modules for the pattern:
|
||||
```bash
|
||||
grep -rn "flyway.migrate" java/modules/cs-modules/<MODULE>/src/
|
||||
```
|
||||
|
||||
### 9. Verify migration
|
||||
|
||||
Run the module's Flyway migration test to ensure the SQL is valid:
|
||||
|
||||
```bash
|
||||
cd /Users/pplate/git/paisy-<TICKET_KEY>
|
||||
mvn test -pl java/modules/cs-modules/<MODULE> -Dtest="*FlywayMigrationTest*" -f java/pom.xml
|
||||
```
|
||||
|
||||
### 10. Store in BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"{TICKET_KEY}: Flyway migration V{timestamp}__C_{revision}_{entity} created for H2 + Oracle in {MODULE}"
|
||||
)
|
||||
```
|
||||
|
||||
## Expected Output
|
||||
|
||||
- H2 migration SQL file created in `db/migration/H2/`
|
||||
- Oracle migration SQL file created in `db/migration/ORACLE/`
|
||||
- Both files use correct Flyway naming convention
|
||||
- Migration test passes
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| Duplicate version timestamp | Increment the seconds portion by 1 |
|
||||
| H2 syntax error in test | Check H2-specific syntax (e.g., `IDENTITY` vs `AUTO_INCREMENT`) |
|
||||
| Oracle PL/SQL block error | Ensure `/` terminator after PL/SQL blocks |
|
||||
| Migration already applied | Flyway won't re-run versioned migrations — create a new version |
|
||||
| Missing migration directory | Create `db/migration/H2/` and/or `db/migration/ORACLE/` directories |
|
||||
|
||||
## Conventions
|
||||
|
||||
- One migration file per logical change (don't combine unrelated DDL)
|
||||
- H2 and Oracle files must produce equivalent schema
|
||||
- Use `IF NOT EXISTS` / `IF EXISTS` in H2 for idempotency
|
||||
- Oracle versioned migrations don't need idempotency (Flyway tracks them)
|
||||
- Repeatable migrations use `R__` prefix instead of `V{timestamp}__`
|
||||
- Comments in SQL: `-- <description>` at the top of each file
|
||||
|
||||
## Language
|
||||
|
||||
- SQL comments: English
|
||||
- Column names: English (snake_case)
|
||||
- Table names: English (snake_case), prefixed with module abbreviation where applicable
|
||||
@@ -0,0 +1,168 @@
|
||||
# Skill: create-pr
|
||||
|
||||
Create a Bitbucket pull request from a PAISY worktree branch.
|
||||
|
||||
## Invoked by
|
||||
|
||||
🎫 JiraOps mode (or 🪃 Orchestrator delegating to JiraOps)
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TICKET_KEY` | Jira issue key | `ESIDEPAISY-12081` |
|
||||
| `MODULE` | PAISY module name | `eau`, `eubp`, `svmeldungen` |
|
||||
|
||||
## Output
|
||||
|
||||
- Bitbucket PR created targeting `current` branch
|
||||
- Jira comment with PR link added
|
||||
- BigMind fact stored
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Get current branch
|
||||
|
||||
```bash
|
||||
cd /Users/pplate/git/paisy-<TICKET_KEY>
|
||||
git branch --show-current
|
||||
```
|
||||
|
||||
Expected format: `current/feature/<module>/<TICKET_KEY>-<desc>` or `current/bugfix/<module>/<TICKET_KEY>-<desc>`
|
||||
|
||||
### 2. Ensure all changes are committed
|
||||
|
||||
```bash
|
||||
cd /Users/pplate/git/paisy-<TICKET_KEY>
|
||||
git status
|
||||
```
|
||||
|
||||
If uncommitted changes exist, warn the user before proceeding.
|
||||
|
||||
### 3. Push branch to origin
|
||||
|
||||
```bash
|
||||
cd /Users/pplate/git/paisy-<TICKET_KEY>
|
||||
git push -u origin <BRANCH>
|
||||
```
|
||||
|
||||
### 4. Gather diff statistics
|
||||
|
||||
```bash
|
||||
cd /Users/pplate/git/paisy-<TICKET_KEY>
|
||||
git diff origin/current --stat
|
||||
git diff origin/current --name-only
|
||||
```
|
||||
|
||||
Use the stats to build the PR description.
|
||||
|
||||
### 5. Read Jira ticket for context
|
||||
|
||||
```python
|
||||
ticket = retrieve_ticket_details(TICKET_KEY)
|
||||
# Extract: summary, description for PR title/description
|
||||
```
|
||||
|
||||
### 6. Compose PR title and description
|
||||
|
||||
PR title format (German):
|
||||
```
|
||||
<TICKET_KEY>: <Jira summary>
|
||||
```
|
||||
|
||||
PR description template (German):
|
||||
```markdown
|
||||
## Jira
|
||||
|
||||
<TICKET_KEY>: <summary>
|
||||
|
||||
## Beschreibung
|
||||
|
||||
<Brief description of what was changed and why, derived from Jira ticket and plan doc>
|
||||
|
||||
## Änderungen
|
||||
|
||||
<List of changed files grouped by component, from git diff --stat>
|
||||
|
||||
### <Component 1>
|
||||
- `<file1>` — <what changed>
|
||||
- `<file2>` — <what changed>
|
||||
|
||||
### <Component 2>
|
||||
- `<file3>` — <what changed>
|
||||
|
||||
## Tests
|
||||
|
||||
- <N> Unit-Tests
|
||||
- <M> Integrationstests
|
||||
- Alle Tests bestanden ✅
|
||||
|
||||
## Checkliste
|
||||
|
||||
- [ ] Code Review durchgeführt
|
||||
- [ ] Tests bestanden
|
||||
- [ ] Flyway-Migrationen geprüft (H2 + Oracle)
|
||||
- [ ] Keine `src.gen/` Änderungen
|
||||
```
|
||||
|
||||
### 7. Create the pull request
|
||||
|
||||
```python
|
||||
create_pull_request(
|
||||
project_key="ESIDEPAISY",
|
||||
repo_slug="paisy",
|
||||
title=f"{TICKET_KEY}: {summary}",
|
||||
description=<composed description>,
|
||||
from_branch=<BRANCH>,
|
||||
to_branch="current"
|
||||
)
|
||||
```
|
||||
|
||||
### 8. Add Jira comment with PR link
|
||||
|
||||
```python
|
||||
add_comment_to_ticket(
|
||||
issue_key=TICKET_KEY,
|
||||
comment=f"*Pull Request erstellt*\n\nBranch: {BRANCH}\nPR: [PR #{pr_id}|<pr_url>]\n\nÄnderungen: {N} Dateien geändert, {M} neu"
|
||||
)
|
||||
```
|
||||
|
||||
### 9. Store in BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"{TICKET_KEY}: PR #{pr_id} created — {BRANCH} → current. {N} files changed."
|
||||
)
|
||||
```
|
||||
|
||||
## Expected Output
|
||||
|
||||
- Branch pushed to origin
|
||||
- Bitbucket PR created with German title/description
|
||||
- Jira comment added with PR link
|
||||
- BigMind fact stored
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| Branch not pushed | Run `git push -u origin <BRANCH>` first |
|
||||
| Uncommitted changes | Warn user, suggest `git add` + `git commit` |
|
||||
| PR already exists | Check `list_prs_for_repository` for existing PR from same branch |
|
||||
| Merge conflicts | Run `git fetch origin current && git merge origin/current` in worktree, resolve conflicts |
|
||||
| No diff (empty PR) | Branch is identical to `current` — nothing to merge |
|
||||
|
||||
## Conventions
|
||||
|
||||
- PR title: always starts with `TICKET_KEY:` for Jira auto-linking
|
||||
- PR description: German (matches Jira language)
|
||||
- Target branch: always `current` (never `master` or `main`)
|
||||
- Repo: `project_key="ESIDEPAISY"`, `repo_slug="paisy"`
|
||||
- One PR per ticket — don't create multiple PRs for the same branch
|
||||
|
||||
## Language
|
||||
|
||||
- PR title and description: **German**
|
||||
- Branch names, file paths: English as-is
|
||||
- Jira comment: **German**
|
||||
@@ -0,0 +1,109 @@
|
||||
# Skill: create-worktree
|
||||
|
||||
Git worktree setup for a PAISY Jira ticket.
|
||||
|
||||
## Invoked by
|
||||
|
||||
🎫 JiraOps mode (or 🪃 Orchestrator delegating to JiraOps)
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TICKET_ID` | Jira issue key | `ESIDEPAISY-12081` |
|
||||
| `MODULE` | Ticket context or user input | `eau`, `eubp`, `svmeldungen`, `dabpv`, `rvbea` |
|
||||
| `TYPE` | Ticket issue type (Story → feature, Bug → bugfix) | `feature` or `bugfix` |
|
||||
| `SHORT_DESC` | Kebab-case summary (2-4 words) | `leftover-rueckmeldungen` |
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Parse ticket metadata
|
||||
|
||||
```
|
||||
TICKET_KEY = e.g. "ESIDEPAISY-12081"
|
||||
TICKET_NUM = e.g. "12081" (numeric part only)
|
||||
```
|
||||
|
||||
If MODULE or TYPE are not provided, retrieve them from Jira:
|
||||
- `retrieve_ticket_details(TICKET_KEY)` → read `issuetype` and `summary`
|
||||
- Map issue type: `Story` / `Task` → `feature`, `Bug` → `bugfix`
|
||||
- Infer module from summary keywords or ask the user
|
||||
|
||||
### 2. Determine branch name
|
||||
|
||||
```
|
||||
BRANCH = current/<TYPE>/<MODULE>/<TICKET_KEY>-<SHORT_DESC>
|
||||
```
|
||||
|
||||
Examples:
|
||||
- `current/feature/eau/ESIDEPAISY-12081-leftover-rueckmeldungen`
|
||||
- `current/bugfix/eau/ESIDEPAISY-12261-azvu-package-placeholder`
|
||||
|
||||
### 3. Ensure base branch is up to date
|
||||
|
||||
```bash
|
||||
cd /Users/pplate/git/paisy
|
||||
git fetch origin current
|
||||
```
|
||||
|
||||
### 4. Create worktree
|
||||
|
||||
```bash
|
||||
git worktree add /Users/pplate/git/paisy-<TICKET_KEY> -b <BRANCH> origin/current
|
||||
```
|
||||
|
||||
This creates:
|
||||
- Worktree directory: `/Users/pplate/git/paisy-<TICKET_KEY>`
|
||||
- New branch: `<BRANCH>` tracking `origin/current`
|
||||
|
||||
### 5. Verify
|
||||
|
||||
```bash
|
||||
cd /Users/pplate/git/paisy-<TICKET_KEY> && git branch --show-current
|
||||
```
|
||||
|
||||
Expected output: the branch name from step 2.
|
||||
|
||||
### 6. Store in BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"{TICKET_KEY}: Worktree at /Users/pplate/git/paisy-{TICKET_KEY}, branch {BRANCH}"
|
||||
)
|
||||
```
|
||||
|
||||
### 7. Announce focus
|
||||
|
||||
```python
|
||||
memory_announce_focus(
|
||||
session_id=SESSION_ID,
|
||||
description=f"Working on {TICKET_KEY} in worktree",
|
||||
files=[f"/Users/pplate/git/paisy-{TICKET_KEY}"],
|
||||
ide_hint="Roo"
|
||||
)
|
||||
```
|
||||
|
||||
## Expected Output
|
||||
|
||||
- Worktree directory exists at `/Users/pplate/git/paisy-<TICKET_KEY>`
|
||||
- Branch `<BRANCH>` is checked out
|
||||
- BigMind fact stored with worktree path
|
||||
- Focus announced
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| Worktree already exists | Check if branch matches. If yes, reuse. If no, ask user. |
|
||||
| Branch already exists | `git worktree add /Users/pplate/git/paisy-<TICKET_KEY> <BRANCH>` (without `-b`) |
|
||||
| `origin/current` not found | Try `git fetch origin` first, then retry |
|
||||
| Directory already exists (not a worktree) | Ask user to remove or choose different path |
|
||||
|
||||
## Cleanup (when ticket is done)
|
||||
|
||||
```bash
|
||||
cd /Users/pplate/git/paisy
|
||||
git worktree remove /Users/pplate/git/paisy-<TICKET_KEY>
|
||||
git branch -d <BRANCH> # only after merge
|
||||
```
|
||||
@@ -0,0 +1,161 @@
|
||||
# Skill: domain-lookup
|
||||
|
||||
Structured domain knowledge search across all PAISY knowledge sources.
|
||||
|
||||
## Invoked by
|
||||
|
||||
Any mode (📋 Planner, ❓ Ask, 🔍 Reviewer, 💻 Code)
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TOPIC` | Domain topic or question | `"EuBP Archivierung"`, `"DSAK Änderungserkennung"`, `"Fehlzeiten DBFZ"` |
|
||||
| `CONTEXT` | Additional context (optional) | `"for ESIDEPAISY-12081"`, `"Oracle migration syntax"` |
|
||||
|
||||
## Output
|
||||
|
||||
- Structured summary with sources cited
|
||||
- New findings stored in BigMind for future reuse
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Search BigMind facts
|
||||
|
||||
```python
|
||||
memory_search_facts("<2-3 keywords from TOPIC>")
|
||||
```
|
||||
|
||||
FTS5 rule: AND-matches every token. Max 3 short keywords. Long queries return 0 results.
|
||||
|
||||
### 2. Search BigMind chunks
|
||||
|
||||
```python
|
||||
memory_search_chunks("<2-3 keywords from TOPIC>")
|
||||
```
|
||||
|
||||
Check for past decisions, code snippets, or session notes related to the topic.
|
||||
|
||||
### 3. Semantic search (if 1+2 return nothing)
|
||||
|
||||
```python
|
||||
memory_search_semantic("<natural language description of what you're looking for>")
|
||||
```
|
||||
|
||||
Use this when keyword search fails — it matches by meaning, not exact words.
|
||||
|
||||
### 4. Check ADP Docs Wiki index
|
||||
|
||||
```python
|
||||
memory_search_facts("<topic> adpdocs")
|
||||
```
|
||||
|
||||
Known page IDs (from BigMind `adpdocs-index` facts):
|
||||
- EAU → 25123 | EuBP → 26666 | DaBPV → 27242 | DSBD → 26747 | DSAK → 26748
|
||||
- DSVV → 18714 | RvBEA → 21174 | EEL → 2724 | ELStAM → 2737 | DEÜV → 5876
|
||||
- Programmabläufe → 15201 | Einzelaufrufe BATCH → 15250 | Umgebungsvariablen → 22767
|
||||
- PAISY verwalten → 15180 | Datenbanken verwalten → 15184 | Fehlermeldungen → 15196
|
||||
|
||||
### 5. Fetch Wiki page (if page ID known)
|
||||
|
||||
```python
|
||||
set-wiki(uri="mcp://wikis/adpdocs.de.adp.com")
|
||||
get-page(title="<page title>")
|
||||
```
|
||||
|
||||
### 6. Search Wiki (if page ID not known)
|
||||
|
||||
```python
|
||||
set-wiki(uri="mcp://wikis/adpdocs.de.adp.com")
|
||||
search-page(query="<domain keywords>")
|
||||
```
|
||||
|
||||
Or browse by category:
|
||||
```python
|
||||
get-category-members(category="Meldeverfahren")
|
||||
```
|
||||
|
||||
Key categories: `Meldeverfahren`, `Verwalterhandbuch`, `Batchabläufe`, `Client Server (CS)`, `PAISYadvanced`, `Installationshandbuch für Windows und UNIX`
|
||||
|
||||
### 7. Search Confluence
|
||||
|
||||
```python
|
||||
search_confluence_by_cql("text ~ '<topic keywords>' AND space = 'ESIDEPAISY'")
|
||||
```
|
||||
|
||||
Or broader:
|
||||
```python
|
||||
search_confluence_by_cql("text ~ '<topic keywords>'")
|
||||
```
|
||||
|
||||
### 8. Search Bitbucket (for code-level context)
|
||||
|
||||
```python
|
||||
# Check recent PRs for related changes
|
||||
list_prs_for_repository(project_key="ESIDEPAISY", repo_slug="paisy", status="MERGED")
|
||||
|
||||
# Or find a specific file
|
||||
find_file(project_key="ESIDEPAISY", repo_slug="paisy", file_path="<path>", branch="current")
|
||||
```
|
||||
|
||||
### 9. Web scraper (last resort only)
|
||||
|
||||
```python
|
||||
webscraper_fetch(url="<relevant URL>")
|
||||
```
|
||||
|
||||
**Only use if all previous sources returned nothing.** Never skip to webscraper if BigMind or Wiki MCP can answer.
|
||||
|
||||
### 10. Store new findings
|
||||
|
||||
After finding useful information, immediately store it:
|
||||
|
||||
```python
|
||||
# For Wiki page discoveries
|
||||
memory_store_fact(
|
||||
category="adpdocs-index",
|
||||
fact=f"ADP Docs Wiki: '<page title>' (Page ID: {page_id}) — <brief description of content>"
|
||||
)
|
||||
|
||||
# For domain knowledge
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"<domain topic>: <key finding>. Source: <where it came from>"
|
||||
)
|
||||
|
||||
# For detailed findings
|
||||
memory_append_chunk(
|
||||
session_id=SESSION_ID,
|
||||
content=f"Domain lookup for '{TOPIC}':\n<detailed findings with sources>",
|
||||
flag_reason="domain knowledge"
|
||||
)
|
||||
```
|
||||
|
||||
## Expected Output
|
||||
|
||||
- Structured answer with cited sources
|
||||
- Priority: BigMind facts → BigMind chunks → ADP Docs Wiki → Confluence → Bitbucket → webscraper
|
||||
- New findings stored in BigMind for future lookups
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| BigMind FTS returns 0 | Reduce to 2 keywords, try synonyms, then use semantic search |
|
||||
| Wiki page not found | Try `search-page` with different keywords, or browse category members |
|
||||
| Confluence returns nothing | Broaden CQL query, remove space filter |
|
||||
| All sources empty | Report "no information found" honestly — don't fabricate answers |
|
||||
| Wiki connection error | Ensure `set-wiki` was called first with correct URI |
|
||||
|
||||
## Search Strategy Tips
|
||||
|
||||
- **German domain terms** often work better than English: `Fehlzeiten` not `absences`, `Lohnkonto` not `payroll account`
|
||||
- **Abbreviations** are common: `DSAK`, `DSBD`, `DSVV`, `EuBP`, `DaBPV`, `RvBEA`, `EEL`
|
||||
- **PAISY program names** are searchable: `PAI022`, `PAI028`, `PAI030`, `PAIBATCH`
|
||||
- **Error codes** from PAISY start with `F;` — search for the specific code in Wiki Fehlermeldungen page (15196)
|
||||
|
||||
## Language
|
||||
|
||||
- Search queries: match the source language (German for Wiki/Confluence, English for code)
|
||||
- Output summary: match the user's language
|
||||
- Stored facts: English (BigMind convention)
|
||||
@@ -0,0 +1,154 @@
|
||||
# Skill: generate-assessment
|
||||
|
||||
Structured assessment document from Jira ticket and code analysis.
|
||||
|
||||
## Invoked by
|
||||
|
||||
📋 Planner mode
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TICKET_KEY` | Jira issue key | `ESIDEPAISY-12081` |
|
||||
| `MODULE` | PAISY module name | `eau`, `eubp`, `svmeldungen` |
|
||||
|
||||
## Output
|
||||
|
||||
Markdown file: `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-assessment.md`
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Gather context from BigMind
|
||||
|
||||
```python
|
||||
memory_search_facts("<MODULE> <relevant keywords>")
|
||||
memory_search_chunks("<MODULE> <relevant keywords>")
|
||||
memory_search_semantic("<natural language description of the problem>")
|
||||
```
|
||||
|
||||
### 2. Read Jira ticket
|
||||
|
||||
```python
|
||||
retrieve_ticket_details(TICKET_KEY)
|
||||
# Extract: summary, description, acceptance criteria (customfield_10510)
|
||||
# Note the Feature Link (customfield_10001) for traceability
|
||||
```
|
||||
|
||||
### 3. Search ADP Wiki for domain context
|
||||
|
||||
```python
|
||||
# Check BigMind index first
|
||||
memory_search_facts("<domain topic> adpdocs")
|
||||
|
||||
# If page ID known, fetch directly
|
||||
set-wiki(uri="mcp://wikis/adpdocs.de.adp.com")
|
||||
get-page(title="<relevant page>")
|
||||
|
||||
# If not known, search
|
||||
search-page(query="<domain keywords>")
|
||||
```
|
||||
|
||||
### 4. Search Confluence for prior decisions
|
||||
|
||||
```python
|
||||
search_confluence_by_cql("text ~ '<TICKET_KEY>' OR text ~ '<topic keywords>'")
|
||||
```
|
||||
|
||||
### 5. Analyze affected source code
|
||||
|
||||
- Identify the module entry point: `java/modules/cs-modules/<MODULE>/`
|
||||
- Read key classes mentioned in the ticket
|
||||
- Trace the data flow through the affected components
|
||||
- Note patterns used: AbstractMeldung, Datenbaustein, ServiceCenter, EMFactory, JAXB, etc.
|
||||
|
||||
### 6. Generate assessment document
|
||||
|
||||
Write `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-assessment.md` with this structure:
|
||||
|
||||
```markdown
|
||||
# Assessment: <TICKET_KEY> — <Summary>
|
||||
|
||||
**Datum:** <today>
|
||||
**Modul:** <MODULE>
|
||||
**Autor:** Patrick Plate / Roo (Planner)
|
||||
**Status:** Entwurf v1
|
||||
|
||||
---
|
||||
|
||||
## 1. Problemanalyse
|
||||
|
||||
<What is the problem? Why does it need to be solved? Reference Jira ticket.>
|
||||
|
||||
## 2. Betroffene Komponenten
|
||||
|
||||
| Komponente | Pfad | Rolle |
|
||||
|-----------|------|-------|
|
||||
| <Class> | <path> | <what it does> |
|
||||
|
||||
## 3. Ist-Zustand
|
||||
|
||||
<How does the current code work? Data flow, key methods, patterns used.>
|
||||
|
||||
## 4. Risikobewertung
|
||||
|
||||
| Risiko | Wahrscheinlichkeit | Auswirkung | Mitigation |
|
||||
|--------|-------------------|------------|------------|
|
||||
| <risk> | Hoch/Mittel/Niedrig | <impact> | <mitigation> |
|
||||
|
||||
## 5. Lösungsoptionen
|
||||
|
||||
### Option A: <name>
|
||||
- **Beschreibung:** ...
|
||||
- **Vorteile:** ...
|
||||
- **Nachteile:** ...
|
||||
- **Aufwand:** ...
|
||||
|
||||
### Option B: <name>
|
||||
- **Beschreibung:** ...
|
||||
- **Vorteile:** ...
|
||||
- **Nachteile:** ...
|
||||
- **Aufwand:** ...
|
||||
|
||||
## 6. Empfehlung
|
||||
|
||||
<Which option and why. Reference PAISY patterns, domain constraints, prior art.>
|
||||
|
||||
## 7. Offene Fragen
|
||||
|
||||
- [ ] <question 1>
|
||||
- [ ] <question 2>
|
||||
```
|
||||
|
||||
### 7. Present to user
|
||||
|
||||
- Show the assessment summary
|
||||
- Explicitly ask: **"Assessment v1 erstellt. GO / Feedback?"**
|
||||
- On feedback: revise and increment version (v2, v3, ...)
|
||||
|
||||
### 8. Store findings in BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"{TICKET_KEY}: Assessment completed. <key finding summary>"
|
||||
)
|
||||
memory_append_chunk(
|
||||
session_id=SESSION_ID,
|
||||
content=f"Assessment for {TICKET_KEY}: <detailed findings>",
|
||||
flag_reason="assessment findings"
|
||||
)
|
||||
```
|
||||
|
||||
## Language
|
||||
|
||||
- Document content: **German** (PAISY domain convention)
|
||||
- Technical terms (class names, patterns, tools): keep as-is in English
|
||||
- Section headers: German
|
||||
|
||||
## Conventions
|
||||
|
||||
- Date format: `dd.MM.yyyy` (German)
|
||||
- Version tracking: v1, v2, v3 in the Status field
|
||||
- File location: always under `docs/<MODULE>/<TICKET_KEY>/`
|
||||
- Reference existing plan docs if they exist (check `ls docs/<MODULE>/<TICKET_KEY>/`)
|
||||
@@ -0,0 +1,185 @@
|
||||
# Skill: generate-handover
|
||||
|
||||
Generate handover document for session or person transfer.
|
||||
|
||||
## Invoked by
|
||||
|
||||
📝 DocGen mode (or 🪃 Orchestrator delegating to DocGen)
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TICKET_KEY` | Jira issue key | `ESIDEPAISY-12081` |
|
||||
| `MODULE` | PAISY module name | `eau`, `eubp`, `svmeldungen` |
|
||||
| `SESSION_ID` | BigMind session to hand over (optional) | `d8a0f4fa-59ee-48c0-b863-a51bc6294331` |
|
||||
|
||||
## Output
|
||||
|
||||
Markdown file: `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-handover-<date>.md`
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Read BigMind session context
|
||||
|
||||
```python
|
||||
# If SESSION_ID provided, get the full session detail
|
||||
memory_get_session_detail(session_id=SESSION_ID)
|
||||
|
||||
# Also search for all facts related to this ticket
|
||||
memory_search_facts("<TICKET_KEY>")
|
||||
memory_search_chunks("<TICKET_KEY>")
|
||||
```
|
||||
|
||||
### 2. Read git status
|
||||
|
||||
```bash
|
||||
cd /Users/pplate/git/paisy-<TICKET_KEY>
|
||||
git branch --show-current
|
||||
git status
|
||||
git log origin/current..HEAD --oneline
|
||||
git diff origin/current --stat
|
||||
```
|
||||
|
||||
### 3. Read Jira ticket status
|
||||
|
||||
```python
|
||||
ticket = retrieve_ticket_details(TICKET_KEY)
|
||||
# Extract: status, assignee, summary, checklist state
|
||||
checklist = get_checklist(TICKET_KEY)
|
||||
comments = retrieve_ticket_comments(TICKET_KEY)
|
||||
```
|
||||
|
||||
### 4. Read existing documentation
|
||||
|
||||
```bash
|
||||
ls docs/<MODULE>/<TICKET_KEY>/
|
||||
```
|
||||
|
||||
Read all available docs:
|
||||
- Assessment (`*-assessment.md`)
|
||||
- Plan (`*-plan.md`)
|
||||
- Test plan (`*-testplan.md`)
|
||||
- Solution doc (`*-solution.md`)
|
||||
- Review (`*-review.md`)
|
||||
|
||||
### 5. Analyze what's done vs. remaining
|
||||
|
||||
Cross-reference:
|
||||
- Jira checklist items (done vs. open)
|
||||
- Git commits (what's been implemented)
|
||||
- Test plan status (which tests pass/fail/pending)
|
||||
- Plan document (which steps are complete)
|
||||
|
||||
### 6. Generate handover document
|
||||
|
||||
Write `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-handover-<YYYY-MM-DD>.md`:
|
||||
|
||||
```markdown
|
||||
# Handover: <TICKET_KEY> — <Summary>
|
||||
|
||||
**Datum:** <today>
|
||||
**Modul:** <MODULE>
|
||||
**Autor:** Roo (DocGen)
|
||||
**BigMind Session:** `<SESSION_ID>`
|
||||
**Branch:** <current branch>
|
||||
|
||||
---
|
||||
|
||||
## 1. Aktueller Stand
|
||||
|
||||
**Jira-Status:** <status>
|
||||
**Fortschritt:** <X>/<Y> Checklist-Punkte erledigt
|
||||
|
||||
<1-3 sentence summary of where things stand>
|
||||
|
||||
## 2. Erledigte Arbeiten
|
||||
|
||||
| # | Beschreibung | Dateien | Commit |
|
||||
|---|-------------|---------|--------|
|
||||
| 1 | <what was done> | `<file1>`, `<file2>` | `<short hash>` |
|
||||
| 2 | <what was done> | `<file3>` | `<short hash>` |
|
||||
|
||||
## 3. Offene Arbeiten
|
||||
|
||||
| # | Beschreibung | Priorität | Geschätzter Aufwand |
|
||||
|---|-------------|-----------|-------------------|
|
||||
| 1 | <what remains> | Hoch/Mittel/Niedrig | <estimate> |
|
||||
| 2 | <what remains> | Hoch/Mittel/Niedrig | <estimate> |
|
||||
|
||||
## 4. Offene Fragen / Blocker
|
||||
|
||||
| # | Frage/Blocker | Kontext | Ansprechpartner |
|
||||
|---|-------------|---------|----------------|
|
||||
| 1 | <question or blocker> | <context> | <who can help> |
|
||||
|
||||
## 5. Wichtige Entscheidungen
|
||||
|
||||
<Key decisions made during this work, extracted from BigMind chunks>
|
||||
|
||||
| Entscheidung | Begründung | Datum |
|
||||
|-------------|-----------|-------|
|
||||
| <decision> | <rationale> | <date> |
|
||||
|
||||
## 6. Technische Hinweise
|
||||
|
||||
<Important technical context the next person needs to know:>
|
||||
- <Pattern used, gotcha, workaround, etc.>
|
||||
- <Environment setup needed>
|
||||
- <Test data requirements>
|
||||
|
||||
## 7. Kontext-Wiederherstellung
|
||||
|
||||
Für die Weiterarbeit:
|
||||
- **Worktree:** `/Users/pplate/git/paisy-<TICKET_KEY>`
|
||||
- **Branch:** `<branch name>`
|
||||
- **BigMind Session:** `<SESSION_ID>` — `memory_get_session_detail("<SESSION_ID>")` für Details
|
||||
- **Relevante BigMind Facts:** <list fact IDs if available>
|
||||
- **Dokumentation:** `docs/<MODULE>/<TICKET_KEY>/`
|
||||
```
|
||||
|
||||
### 7. Store in BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"{TICKET_KEY}: Handover doc created at docs/{MODULE}/{TICKET_KEY}/{TICKET_KEY}-handover-{date}.md. Status: {done}/{total} items done."
|
||||
)
|
||||
memory_append_chunk(
|
||||
session_id=SESSION_ID,
|
||||
content=f"Handover for {TICKET_KEY}: <summary of state and remaining work>",
|
||||
flag_reason="handover documentation"
|
||||
)
|
||||
```
|
||||
|
||||
## Expected Output
|
||||
|
||||
- Handover document at `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-handover-<date>.md`
|
||||
- Complete picture of done/remaining work
|
||||
- Context recovery instructions for the next person/session
|
||||
- BigMind fact stored for traceability
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| No BigMind session found | Generate handover from git + Jira only — note missing session context |
|
||||
| No worktree found | Check if work was done in main repo with branch checkout |
|
||||
| No plan/assessment docs | Generate handover from Jira ticket + git history only |
|
||||
| Empty git history | Branch may not have diverged from `current` yet — note "no commits" |
|
||||
|
||||
## When to Use
|
||||
|
||||
| Scenario | Trigger |
|
||||
|----------|---------|
|
||||
| End of day | Capture progress before stopping work |
|
||||
| Person transfer | Handing ticket to another developer |
|
||||
| Session recovery | After IDE crash, use to restore context |
|
||||
| Long pause | Before vacation or multi-day break |
|
||||
| Mode switch | When Orchestrator hands off between modes |
|
||||
|
||||
## Language
|
||||
|
||||
- Document content: **German**
|
||||
- Technical terms (class names, branch names, BigMind IDs): English as-is
|
||||
- Section headers: German
|
||||
@@ -0,0 +1,192 @@
|
||||
# Skill: generate-solution-doc
|
||||
|
||||
Solution documentation from implementation results.
|
||||
|
||||
## Invoked by
|
||||
|
||||
📝 DocGen mode
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TICKET_KEY` | Jira issue key | `ESIDEPAISY-12081` |
|
||||
| `MODULE` | PAISY module name | `eau` |
|
||||
| `PLAN_PATH` | Path to plan.md | `docs/EAU/ESIDEPAISY-12081/ESIDEPAISY-12081-plan.md` |
|
||||
| `TESTPLAN_PATH` | Path to testplan.md | `docs/EAU/ESIDEPAISY-12081/ESIDEPAISY-12081-testplan.md` |
|
||||
| `REVIEW_PATH` | Path to review.md (optional) | `docs/EAU/ESIDEPAISY-12081/ESIDEPAISY-12081-review.md` |
|
||||
|
||||
## Output
|
||||
|
||||
- Markdown: `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-solution.md`
|
||||
- PDF: `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-solution.pdf`
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Read input documents
|
||||
|
||||
Read all available docs in `docs/<MODULE>/<TICKET_KEY>/`:
|
||||
- Plan document (required)
|
||||
- Test plan (required)
|
||||
- Assessment (if exists)
|
||||
- Review findings (if exists)
|
||||
|
||||
### 2. Analyze actual changes
|
||||
|
||||
```bash
|
||||
# If in worktree
|
||||
cd /Users/pplate/git/paisy-<TICKET_KEY>
|
||||
git diff origin/current --stat
|
||||
git diff origin/current --name-only
|
||||
|
||||
# Or use git log for committed changes
|
||||
git log origin/current..HEAD --oneline
|
||||
```
|
||||
|
||||
Read the changed files to understand what was actually implemented vs. what was planned.
|
||||
|
||||
### 3. Gather test results
|
||||
|
||||
```bash
|
||||
# Check if tests were run
|
||||
# Look for surefire reports or test output
|
||||
find . -name "TEST-*.xml" -path "*/surefire-reports/*" | head -20
|
||||
```
|
||||
|
||||
Or reference the testplan status if already updated.
|
||||
|
||||
### 4. Generate solution document
|
||||
|
||||
Write `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-solution.md`:
|
||||
|
||||
```markdown
|
||||
# Lösungsdokumentation: <TICKET_KEY>
|
||||
|
||||
**Datum:** <today>
|
||||
**Modul:** <MODULE>
|
||||
**Autor:** Patrick Plate / Roo (DocGen)
|
||||
**Jira:** <TICKET_KEY>
|
||||
**Branch:** current/<type>/<module>/<TICKET_KEY>-<desc>
|
||||
|
||||
---
|
||||
|
||||
## 1. Problemstellung
|
||||
|
||||
<From assessment/plan: What was the problem? Why did it need solving?>
|
||||
|
||||
## 2. Lösungsansatz
|
||||
|
||||
<High-level approach chosen. Reference the plan document.>
|
||||
|
||||
## 3. Architektur-Entscheidungen
|
||||
|
||||
| Entscheidung | Begründung | Alternativen |
|
||||
|-------------|-----------|--------------|
|
||||
| <decision> | <why> | <what was considered> |
|
||||
|
||||
<Include Mermaid diagrams where helpful:>
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Component] --> B[Component]
|
||||
```
|
||||
|
||||
## 4. Implementierte Änderungen
|
||||
|
||||
### 4.1 <Component/File group>
|
||||
|
||||
| Datei | Änderung | Beschreibung |
|
||||
|-------|---------|-------------|
|
||||
| `<path>` | Neu/Geändert | <what changed> |
|
||||
|
||||
<Explain key code changes. Reference patterns used.>
|
||||
|
||||
### 4.2 <Next component group>
|
||||
...
|
||||
|
||||
### 4.n Datenbank-Migrationen
|
||||
|
||||
| Migration | Datenbank | Beschreibung |
|
||||
|-----------|----------|-------------|
|
||||
| `V{timestamp}__C_...` | H2/Oracle | <what it does> |
|
||||
|
||||
## 5. Testabdeckung
|
||||
|
||||
| ID | Beschreibung | Typ | Ergebnis |
|
||||
|----|-------------|-----|----------|
|
||||
| T-01 | <desc> | Unit | ✅ |
|
||||
| T-02 | <desc> | Integration | ✅ |
|
||||
|
||||
**Zusammenfassung:** <N> Tests, alle bestanden.
|
||||
|
||||
## 6. Offene Punkte
|
||||
|
||||
| # | Beschreibung | Priorität | Ticket |
|
||||
|---|-------------|-----------|--------|
|
||||
| 1 | <open item> | Hoch/Mittel/Niedrig | <linked ticket or "—"> |
|
||||
|
||||
<If no open items: "Keine offenen Punkte.">
|
||||
```
|
||||
|
||||
### 5. Ask for PDF color scheme
|
||||
|
||||
Before generating the PDF, ask Patrick:
|
||||
|
||||
> "Welches Farbschema für das PDF? Verfügbar: adp (rot), royal_purple, ocean, forest, sunset, slate, rose"
|
||||
|
||||
Default to `adp` if Patrick says "standard" or doesn't have a preference.
|
||||
|
||||
### 6. Generate PDF
|
||||
|
||||
```python
|
||||
generate_pdf(
|
||||
content=<markdown content>,
|
||||
title=f"Lösungsdokumentation {TICKET_KEY}",
|
||||
author="Patrick Plate",
|
||||
classification="ADP Internal",
|
||||
output_path=f"docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-solution.pdf",
|
||||
color_scheme=<chosen scheme>
|
||||
)
|
||||
```
|
||||
|
||||
### 7. Store in BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"{TICKET_KEY}: Solution doc at docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-solution.md, PDF generated"
|
||||
)
|
||||
memory_append_chunk(
|
||||
session_id=SESSION_ID,
|
||||
content=f"Solution doc for {TICKET_KEY}: <summary of changes and decisions>",
|
||||
flag_reason="solution documentation"
|
||||
)
|
||||
```
|
||||
|
||||
## Language
|
||||
|
||||
- Document content: **German**
|
||||
- Section headers: German (Problemstellung, Lösungsansatz, etc.)
|
||||
- Code references, class names, patterns: English as-is
|
||||
- Mermaid diagram labels: German or English depending on audience
|
||||
|
||||
## Template Variants
|
||||
|
||||
### Minimal (for small bugfixes)
|
||||
|
||||
Skip sections 3 (Architektur-Entscheidungen) and 6 (Offene Punkte) if not applicable. Keep sections 1, 2, 4, 5.
|
||||
|
||||
### Extended (for large features)
|
||||
|
||||
Add additional sections:
|
||||
- **Konfigurationsänderungen** — environment variables, properties
|
||||
- **Deployment-Hinweise** — special deployment steps needed
|
||||
- **Rückwärtskompatibilität** — backward compatibility considerations
|
||||
- **Performance-Auswirkungen** — performance impact analysis
|
||||
|
||||
## PDF Conventions
|
||||
|
||||
- Always use `generate_pdf` MCP tool (never write PDF bytes directly)
|
||||
- Color scheme must be confirmed by Patrick before generation
|
||||
- Author field: "Patrick Plate" (not "Roo")
|
||||
- Classification: "ADP Internal" unless told otherwise
|
||||
@@ -0,0 +1,166 @@
|
||||
# Skill: generate-testplan
|
||||
|
||||
Structured test plan from implementation plan / assessment.
|
||||
|
||||
## Invoked by
|
||||
|
||||
📋 Planner mode
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TICKET_KEY` | Jira issue key | `ESIDEPAISY-12081` |
|
||||
| `MODULE` | PAISY module name | `eau`, `eubp`, `svmeldungen` |
|
||||
| `PLAN_PATH` | Path to plan.md | `docs/EAU/ESIDEPAISY-12081/ESIDEPAISY-12081-plan.md` |
|
||||
|
||||
## Output
|
||||
|
||||
Markdown file: `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-testplan.md`
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Read the implementation plan
|
||||
|
||||
Read `PLAN_PATH` to understand:
|
||||
- Which classes/methods are being added or modified
|
||||
- Which data flows are affected
|
||||
- Which database changes are involved (Flyway migrations, new tables/columns)
|
||||
- Which integration points exist (ServiceCenter, NATS, external APIs)
|
||||
|
||||
### 2. Read the assessment (if exists)
|
||||
|
||||
Check for `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-assessment.md` — extract risk areas that need extra test coverage.
|
||||
|
||||
### 3. Identify testable units
|
||||
|
||||
For each component in the plan:
|
||||
|
||||
| Category | What to test | Test type |
|
||||
|----------|-------------|-----------|
|
||||
| New methods | Input/output, edge cases, null handling | Unit |
|
||||
| Modified methods | Regression + new behavior | Unit |
|
||||
| Database changes | Migration up/down, data integrity | Integration |
|
||||
| Data flows | End-to-end processing | Integration |
|
||||
| PAISY interaction | ServiceCenter calls, pgm responses | SSH (manual) |
|
||||
| Error paths | Invalid input, missing data, PAISY "F;" responses | Unit |
|
||||
|
||||
### 4. Generate test plan document
|
||||
|
||||
Write `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-testplan.md` with this structure:
|
||||
|
||||
```markdown
|
||||
# Testplan: <TICKET_KEY> — <Summary>
|
||||
|
||||
**Datum:** <today>
|
||||
**Modul:** <MODULE>
|
||||
**Autor:** Patrick Plate / Roo (Planner)
|
||||
**Status:** Entwurf v1
|
||||
**Basis:** <TICKET_KEY>-plan.md
|
||||
|
||||
---
|
||||
|
||||
## Testübersicht
|
||||
|
||||
| ID | Beschreibung | Typ | Klasse | Status |
|
||||
|----|-------------|-----|--------|--------|
|
||||
| T-01 | <short desc> | Unit | <TestClass> | ⬜ |
|
||||
| T-02 | <short desc> | Unit | <TestClass> | ⬜ |
|
||||
| T-03 | <short desc> | Integration | <TestClass> | ⬜ |
|
||||
| T-nn | <short desc> | SSH | manuell | ⬜ |
|
||||
|
||||
Status: ⬜ Offen | ✅ Bestanden | ❌ Fehlgeschlagen | ⏭️ Übersprungen
|
||||
|
||||
---
|
||||
|
||||
## Testfälle
|
||||
|
||||
### T-01: <Descriptive name>
|
||||
|
||||
**Typ:** Unit
|
||||
**Klasse:** `<package>.<TestClassName>`
|
||||
**Methode:** `test<MethodName>()`
|
||||
|
||||
**Vorbedingungen:**
|
||||
- <setup requirements>
|
||||
|
||||
**Szenarien:**
|
||||
|
||||
| # | Eingabe | Erwartetes Ergebnis |
|
||||
|---|---------|-------------------|
|
||||
| a | <input> | <expected> |
|
||||
| b | <input> | <expected> |
|
||||
| c | <edge case> | <expected> |
|
||||
|
||||
**Nachbedingungen:**
|
||||
- <what to verify after test>
|
||||
|
||||
---
|
||||
|
||||
### T-02: <Descriptive name>
|
||||
...
|
||||
|
||||
---
|
||||
|
||||
## Testdaten
|
||||
|
||||
<Describe any test data requirements, fixtures, or database setup needed.>
|
||||
|
||||
## Manuelle Tests (SSH)
|
||||
|
||||
| ID | Instanz | Programm | Eingabe | Erwartetes Ergebnis |
|
||||
|----|---------|----------|---------|-------------------|
|
||||
| T-nn | <instance> | <PAI program> | <input> | <expected> |
|
||||
|
||||
## Testabdeckung
|
||||
|
||||
| Komponente | Unit | Integration | SSH | Gesamt |
|
||||
|-----------|------|-------------|-----|--------|
|
||||
| <Class1> | 3 | 1 | 0 | 4 |
|
||||
| <Class2> | 2 | 0 | 1 | 3 |
|
||||
| **Summe** | **5** | **1** | **1** | **7** |
|
||||
```
|
||||
|
||||
### 5. Cross-reference with plan
|
||||
|
||||
Verify every implementation step in the plan has at least one test case:
|
||||
- New method → unit test
|
||||
- Modified method → regression test
|
||||
- Database migration → migration test
|
||||
- Integration point → integration test or SSH test
|
||||
|
||||
Flag any gaps as warnings in the testplan.
|
||||
|
||||
### 6. Present to user
|
||||
|
||||
- Show the test overview table
|
||||
- Explicitly ask: **"Testplan v1 erstellt mit <N> Testfällen. GO / Feedback?"**
|
||||
- On feedback: revise and increment version
|
||||
|
||||
### 7. Store in BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"{TICKET_KEY}: Testplan with {N} test cases (Unit: {u}, Integration: {i}, SSH: {s})"
|
||||
)
|
||||
```
|
||||
|
||||
## Test Naming Conventions
|
||||
|
||||
- Test class: `<OriginalClass>Test.java` or `<Feature>Test.java`
|
||||
- Test method: `test<What>_<Scenario>_<Expected>()` or `test<What>()` for simple cases
|
||||
- Location: mirror source structure under `src/test/java/`
|
||||
- Base classes: extend existing test bases where available (e.g., `EAUFlywayMigrationTestBase`)
|
||||
|
||||
## Test ID Format
|
||||
|
||||
- Sequential: T-01, T-02, ..., T-nn
|
||||
- Prefix by type if needed: UT-01 (unit), IT-01 (integration), MT-01 (manual/SSH)
|
||||
- IDs are stable — don't renumber on revision, append new tests at the end
|
||||
|
||||
## Language
|
||||
|
||||
- Document content: **German**
|
||||
- Test method names and code: **English** (Java convention)
|
||||
- Scenario descriptions in the table: German
|
||||
@@ -0,0 +1,174 @@
|
||||
# Skill: impact-analysis
|
||||
|
||||
Analyze impact of changes to shared modules across the PAISY monorepo.
|
||||
|
||||
## Invoked by
|
||||
|
||||
📋 Planner mode (or 🔍 Reviewer mode)
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TICKET_KEY` | Jira issue key | `ESIDEPAISY-12081` |
|
||||
| `CHANGED_MODULE` | Module being changed | `persistence`, `sv-common`, `flatfile-parser`, `paisy-common` |
|
||||
| `CHANGED_API` | Changed class/method (optional) | `EMFactory.getLeftoverSchemas()`, `AbstractMeldung.initBaustein()` |
|
||||
|
||||
## Output
|
||||
|
||||
- Impact summary with affected modules, files, and risk level
|
||||
- Stored in BigMind for future reference
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Identify the changed module's artifact
|
||||
|
||||
```bash
|
||||
grep -A2 '<artifactId>' java/modules/cs-modules/<CHANGED_MODULE>/pom.xml | head -3
|
||||
# Or for shared modules:
|
||||
grep -A2 '<artifactId>' java/modules/<CHANGED_MODULE>/pom.xml | head -3
|
||||
```
|
||||
|
||||
Extract the `groupId` and `artifactId` for dependency searching.
|
||||
|
||||
### 2. Find dependent modules (reverse dependency lookup)
|
||||
|
||||
```bash
|
||||
# Search all module POMs for the changed artifact
|
||||
grep -rn "<artifactId><CHANGED_MODULE></artifactId>" java/modules/cs-modules/*/pom.xml
|
||||
grep -rn "<artifactId><CHANGED_MODULE></artifactId>" java/modules/*/pom.xml
|
||||
```
|
||||
|
||||
Or use Maven dependency tree for a specific consumer:
|
||||
```bash
|
||||
cd /Users/pplate/git/paisy-<TICKET_KEY>
|
||||
mvn dependency:tree -pl java/modules/cs-modules/<consumer_module> -DoutputType=text -f java/pom.xml | grep <CHANGED_MODULE>
|
||||
```
|
||||
|
||||
### 3. For each dependent module, check API usage
|
||||
|
||||
```bash
|
||||
# Search for usage of the changed class/method
|
||||
grep -rn "ChangedClass\|changedMethod" java/modules/cs-modules/<dependent_module>/src/
|
||||
|
||||
# For import-level analysis
|
||||
grep -rn "import.*<package>.<ChangedClass>" java/modules/cs-modules/*/src/main/java/
|
||||
```
|
||||
|
||||
### 4. Classify impact per module
|
||||
|
||||
For each dependent module, determine:
|
||||
|
||||
| Impact Level | Criteria | Action |
|
||||
|-------------|----------|--------|
|
||||
| 🔴 High | Direct API consumer, method signature changed | Must update + test |
|
||||
| 🟡 Medium | Uses the module but not the changed API directly | Verify compilation, run tests |
|
||||
| 🟢 Low | Transitive dependency only, no direct usage | Monitor, no action needed |
|
||||
| ⚪ None | Not a dependency | Skip |
|
||||
|
||||
### 5. Check for test coverage in dependent modules
|
||||
|
||||
```bash
|
||||
# For each high/medium impact module, check if tests exist
|
||||
find java/modules/cs-modules/<dependent_module>/src/test -name "*Test.java" | wc -l
|
||||
|
||||
# Check if the dependent module's tests use the changed API
|
||||
grep -rn "ChangedClass\|changedMethod" java/modules/cs-modules/<dependent_module>/src/test/
|
||||
```
|
||||
|
||||
### 6. Verify compilation across affected modules
|
||||
|
||||
```bash
|
||||
cd /Users/pplate/git/paisy-<TICKET_KEY>
|
||||
# Compile all affected modules without running tests
|
||||
mvn compile -pl java/modules/cs-modules/<module1>,java/modules/cs-modules/<module2> -am -f java/pom.xml
|
||||
```
|
||||
|
||||
### 7. Generate impact report
|
||||
|
||||
Present the findings as a structured summary:
|
||||
|
||||
```markdown
|
||||
# Impact Analysis: <TICKET_KEY> — <Changed Module>
|
||||
|
||||
**Datum:** <today>
|
||||
**Geändertes Modul:** <CHANGED_MODULE>
|
||||
**Geänderte API:** <CHANGED_API>
|
||||
|
||||
---
|
||||
|
||||
## Abhängige Module
|
||||
|
||||
| Modul | Impact | Direkte Nutzung | Dateien | Aktion |
|
||||
|-------|--------|----------------|---------|--------|
|
||||
| `eau` | 🔴 Hoch | `EMFactory.getLeftoverSchemas()` in `Center.java` | 2 | Update + Test |
|
||||
| `eubp` | 🟡 Mittel | Nutzt EMFactory, aber nicht geänderte Methode | 1 | Kompilierung prüfen |
|
||||
| `svmeldungen` | 🟢 Niedrig | Transitive Abhängigkeit | 0 | Monitoring |
|
||||
|
||||
## Betroffene Dateien (Detail)
|
||||
|
||||
### 🔴 eau
|
||||
- `java/modules/cs-modules/eau/src/main/java/main/Center.java:142` — calls `EMFactory.getLeftoverSchemas()`
|
||||
- `java/modules/cs-modules/eau/src/test/java/main/CenterTest.java:55` — tests the call
|
||||
|
||||
### 🟡 eubp
|
||||
- `java/modules/cs-modules/eubp/src/main/java/main/EuBPCenter.java:88` — imports EMFactory
|
||||
|
||||
## Risikobewertung
|
||||
|
||||
| Risiko | Wahrscheinlichkeit | Auswirkung | Mitigation |
|
||||
|--------|-------------------|------------|------------|
|
||||
| Kompilierungsfehler in eau | Hoch | Hoch | Sofort anpassen |
|
||||
| Laufzeitfehler in eubp | Niedrig | Mittel | Tests ausführen |
|
||||
|
||||
## Empfehlung
|
||||
|
||||
<Summary of recommended actions>
|
||||
```
|
||||
|
||||
### 8. Store in BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"{TICKET_KEY}: Impact analysis for {CHANGED_MODULE} — {high} high, {medium} medium, {low} low impact modules."
|
||||
)
|
||||
memory_append_chunk(
|
||||
session_id=SESSION_ID,
|
||||
content=f"Impact analysis for {CHANGED_MODULE} change in {TICKET_KEY}:\n<detailed findings>",
|
||||
flag_reason="impact analysis"
|
||||
)
|
||||
```
|
||||
|
||||
## Expected Output
|
||||
|
||||
- Clear list of affected modules with impact levels
|
||||
- Specific file:line references for high-impact usages
|
||||
- Compilation verification results
|
||||
- Risk assessment with mitigation recommendations
|
||||
- BigMind fact stored
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| Module not found in POM | Check if it's a parent module or uses a different artifactId |
|
||||
| Too many dependents (>10) | Focus on high-impact only, list others as "low" without detail |
|
||||
| Compilation fails | Document the failure as part of the impact — it confirms the impact is real |
|
||||
| No tests in dependent module | Flag as risk — untested dependency on changed API |
|
||||
|
||||
## Common Shared Modules
|
||||
|
||||
| Module | Typical Dependents | Risk Profile |
|
||||
|--------|-------------------|-------------|
|
||||
| `persistence` | All modules with DB access | High — EMFactory, FlywayController |
|
||||
| `sv-common` | All SV-Meldeverfahren modules | High — shared SV logic |
|
||||
| `flatfile-parser` | Modules reading DSRV/ITSG files | Medium — parsing infrastructure |
|
||||
| `paisy-common` | Nearly all modules | Very High — core utilities |
|
||||
| `message-broker` | Modules using NATS | Medium — async messaging |
|
||||
|
||||
## Language
|
||||
|
||||
- Impact report: **German**
|
||||
- Code references (class names, methods, file paths): English as-is
|
||||
- BigMind facts: English
|
||||
@@ -0,0 +1,204 @@
|
||||
# Skill: jira-lifecycle
|
||||
|
||||
Full Jira ticket lifecycle management for ESIDEPAISY.
|
||||
|
||||
## Invoked by
|
||||
|
||||
🎫 JiraOps mode
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TICKET_KEY` | Jira issue key | `ESIDEPAISY-12081` |
|
||||
|
||||
## Overview
|
||||
|
||||
This skill manages a Jira ticket through its full lifecycle, from initial setup through to final acceptance. It handles field validation, Smart Checklist management, status transitions, attachments, and structured comments.
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Validate mandatory fields
|
||||
|
||||
```python
|
||||
ticket = retrieve_ticket_details(TICKET_KEY)
|
||||
```
|
||||
|
||||
Check and fix:
|
||||
|
||||
| Field | ID | Required | How to resolve |
|
||||
|-------|----|----------|---------------|
|
||||
| Feature Link | `customfield_10001` | ✅ Mandatory | Look up parent Epic via JQL: `project = ESIDEPAISY AND issuetype = Epic AND summary ~ "<module>"` |
|
||||
| Sprint | `customfield_10000` | ✅ Mandatory | Derive from active sprint: `get_agile_boards("ESIDEPAISY")` → `get_sprints_from_board(board_id, states="active")` |
|
||||
| Assignee | `assignee` | Recommended | `ticket_assignment(TICKET_KEY, assignee="currentUser()")` |
|
||||
|
||||
If Feature Link is missing:
|
||||
```python
|
||||
# Find the parent Epic
|
||||
epics = list_tickets(jql_search='project = ESIDEPAISY AND issuetype = Epic AND summary ~ "<module keyword>"')
|
||||
# Update the ticket
|
||||
update_ticket_fields(TICKET_KEY, fields={"customfield_10001": epics[0]["key"]})
|
||||
```
|
||||
|
||||
### 2. Create Smart Checklist
|
||||
|
||||
Set up the standard PAISY pipeline checklist:
|
||||
|
||||
```python
|
||||
update_checklist(TICKET_KEY, items=[
|
||||
{"name": "## Analyse & Planung"},
|
||||
{"name": "Assessment erstellt", "status": "-"},
|
||||
{"name": "Plan erstellt", "status": "-"},
|
||||
{"name": "Testplan erstellt", "status": "-"},
|
||||
{"name": "Plan Review bestanden", "status": "-!"}, # mandatory
|
||||
{"name": "GO erhalten", "status": "-!"}, # mandatory
|
||||
{"name": "---"},
|
||||
{"name": "## Implementierung"},
|
||||
{"name": "Code-Änderungen", "status": "-"},
|
||||
{"name": "Tests implementiert", "status": "-"},
|
||||
{"name": "Build grün", "status": "-!"}, # mandatory
|
||||
{"name": "---"},
|
||||
{"name": "## Security & Review"},
|
||||
{"name": "Security Review bestanden", "status": "-!"}, # mandatory
|
||||
{"name": "Code Review bestanden", "status": "-"},
|
||||
{"name": "---"},
|
||||
{"name": "## Dokumentation & Abschluss"},
|
||||
{"name": "Lösungsdokumentation", "status": "-"},
|
||||
{"name": "PDF generiert", "status": "-"},
|
||||
{"name": "Jira aktualisiert", "status": "-"},
|
||||
])
|
||||
```
|
||||
|
||||
### 3. Status transitions
|
||||
|
||||
Manage the ticket through the ESIDEPAISY workflow:
|
||||
|
||||
| Phase | Status | When |
|
||||
|-------|--------|------|
|
||||
| Start | `In Progress` | After worktree creation, before implementation |
|
||||
| Review | `In Review` | After implementation + tests, before code review |
|
||||
| Done | `Accepted` | After all checklist items complete |
|
||||
|
||||
```python
|
||||
update_status(TICKET_KEY, status="In Progress")
|
||||
```
|
||||
|
||||
### 4. Update checklist as work progresses
|
||||
|
||||
Update individual items as phases complete:
|
||||
|
||||
```python
|
||||
# After assessment is done
|
||||
update_checklist(TICKET_KEY, items=[
|
||||
{"name": "## Analyse"},
|
||||
{"name": "Assessment erstellt", "checked": True},
|
||||
{"name": "Plan erstellt", "status": "~"}, # in progress
|
||||
# ... rest unchanged
|
||||
])
|
||||
```
|
||||
|
||||
**Important:** `update_checklist` replaces ALL items. Always send the full checklist with updated statuses.
|
||||
|
||||
### 5. Add structured comments at phase boundaries
|
||||
|
||||
At each major phase transition, add a German comment:
|
||||
|
||||
```python
|
||||
# After planning + plan review
|
||||
add_comment_to_ticket(TICKET_KEY, comment="""
|
||||
*Phase 1-1.5 abgeschlossen: Analyse & Planung*
|
||||
|
||||
Assessment, Plan und Testplan erstellt:
|
||||
- Assessment: [TICKET_KEY-assessment.md]
|
||||
- Plan: [TICKET_KEY-plan.md]
|
||||
- Testplan: [TICKET_KEY-testplan.md] ({N} Testfälle)
|
||||
- Plan Review: [TICKET_KEY-plan-review.md] — ✅ APPROVED
|
||||
|
||||
GO erhalten am {date}.
|
||||
""")
|
||||
|
||||
# After implementation + security review
|
||||
add_comment_to_ticket(TICKET_KEY, comment="""
|
||||
*Phase 3-5.5 abgeschlossen: Implementierung, Tests & Security*
|
||||
|
||||
Branch: current/{type}/{module}/{TICKET_KEY}-{desc}
|
||||
Änderungen: {N} Dateien geändert, {M} neu
|
||||
Tests: {T} Tests, alle bestanden
|
||||
Security Review: ✅ PASS — [TICKET_KEY-security-review.md]
|
||||
""")
|
||||
|
||||
# After documentation
|
||||
add_comment_to_ticket(TICKET_KEY, comment="""
|
||||
*Phase 7-8 abgeschlossen: Dokumentation & Finalisierung*
|
||||
|
||||
Lösungsdokumentation als PDF angehängt.
|
||||
Alle Checklist-Punkte erledigt.
|
||||
""")
|
||||
```
|
||||
|
||||
### 6. Upload attachments
|
||||
|
||||
```python
|
||||
# Upload solution PDF
|
||||
add_attachment_to_ticket(TICKET_KEY, file_path="/absolute/path/to/<TICKET_KEY>-solution.pdf")
|
||||
```
|
||||
|
||||
### 7. Final checklist update
|
||||
|
||||
Mark all items as done:
|
||||
|
||||
```python
|
||||
update_checklist(TICKET_KEY, items=[
|
||||
{"name": "## Analyse & Planung"},
|
||||
{"name": "Assessment erstellt", "checked": True},
|
||||
{"name": "Plan erstellt", "checked": True},
|
||||
{"name": "Testplan erstellt", "checked": True},
|
||||
{"name": "Plan Review bestanden", "status": "+!"},
|
||||
{"name": "GO erhalten", "status": "+!"},
|
||||
{"name": "---"},
|
||||
{"name": "## Implementierung"},
|
||||
{"name": "Code-Änderungen", "checked": True},
|
||||
{"name": "Tests implementiert", "checked": True},
|
||||
{"name": "Build grün", "status": "+!"},
|
||||
{"name": "---"},
|
||||
{"name": "## Security & Review"},
|
||||
{"name": "Security Review bestanden", "status": "+!"},
|
||||
{"name": "Code Review bestanden", "checked": True},
|
||||
{"name": "---"},
|
||||
{"name": "## Dokumentation & Abschluss"},
|
||||
{"name": "Lösungsdokumentation", "checked": True},
|
||||
{"name": "PDF generiert", "checked": True},
|
||||
{"name": "Jira aktualisiert", "checked": True},
|
||||
])
|
||||
```
|
||||
|
||||
### 8. Final status transition
|
||||
|
||||
```python
|
||||
update_status(TICKET_KEY, status="Accepted")
|
||||
```
|
||||
|
||||
## Language
|
||||
|
||||
- All Jira content (summary, description, comments, checklist items): **German**
|
||||
- Technical terms (branch names, file paths, tool names): English as-is
|
||||
|
||||
## Conventions
|
||||
|
||||
- Feature Link (`customfield_10001`): always look up dynamically, never hardcode Epic keys
|
||||
- Sprint: always derive from active sprint, never hardcode sprint IDs
|
||||
- Comments: use Jira wiki markup (`*bold*`, `{code}`, etc.)
|
||||
- Attachments: use absolute file paths
|
||||
- Checklist: always send the FULL list (Railsware replaces all items on update)
|
||||
|
||||
## Partial Lifecycle
|
||||
|
||||
Not every ticket needs the full lifecycle. For quick fixes:
|
||||
|
||||
| Scenario | Skip |
|
||||
|----------|------|
|
||||
| Trivial bugfix (< 1 hour) | Skip assessment, testplan, review. Keep checklist minimal. |
|
||||
| Documentation-only change | Skip implementation, tests, review phases. |
|
||||
| Hotfix | Skip planning loop. Minimal checklist: Code → Test → Deploy. |
|
||||
|
||||
Adjust the checklist template accordingly when creating it.
|
||||
@@ -0,0 +1,253 @@
|
||||
# Skill: plan-review
|
||||
|
||||
Plan and testplan quality review before implementation.
|
||||
|
||||
## Description
|
||||
|
||||
Reviews assessment documents, implementation plans, and test plans for completeness, correctness, and feasibility. Produces a structured review with APPROVED/REVISE verdict. This creates a quality gate between planning and implementation — ensuring plans are solid before code is written.
|
||||
|
||||
## Invoked by
|
||||
|
||||
📋✅ Plan Reviewer mode
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TICKET_KEY` | Jira issue key | `ESIDEPAISY-12081` |
|
||||
| `MODULE` | PAISY module name | `eau`, `eubp`, `svmeldungen` |
|
||||
|
||||
## Output
|
||||
|
||||
Markdown file: `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-plan-review.md`
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Read the planning documents
|
||||
|
||||
Read all available docs in `docs/<MODULE>/<TICKET_KEY>/`:
|
||||
- Assessment (`*-assessment.md`) — required
|
||||
- Implementation plan (`*-plan.md`) — required
|
||||
- Test plan (`*-testplan.md`) — required
|
||||
|
||||
If any required document is missing, flag as REVISE immediately.
|
||||
|
||||
### 2. Read the Jira ticket
|
||||
|
||||
```python
|
||||
retrieve_ticket_details(TICKET_KEY)
|
||||
# Extract: summary, description, acceptance criteria (customfield_10510)
|
||||
```
|
||||
|
||||
Cross-reference: do the plan documents address ALL requirements from the ticket?
|
||||
|
||||
### 3. Read affected source code
|
||||
|
||||
For each file/class mentioned in the plan:
|
||||
- Verify the file exists at the stated path
|
||||
- Verify the class/method names are correct
|
||||
- Verify the patterns described match the actual code
|
||||
- Check if the plan missed any related files that should also be changed
|
||||
|
||||
### 4. Run the plan review checklist
|
||||
|
||||
#### Assessment Review
|
||||
|
||||
| # | Check | What to verify |
|
||||
|---|-------|---------------|
|
||||
| 1 | Problem statement complete | Is the problem clearly described? Does it match the Jira ticket? |
|
||||
| 2 | Affected components identified | Are all affected files/classes listed? Any missing? |
|
||||
| 3 | Current state accurate | Does the Ist-Zustand description match the actual code? |
|
||||
| 4 | Risk assessment realistic | Are risks properly categorized? Any missing risks? |
|
||||
| 5 | Solution options evaluated | Were alternatives considered? Is the recommendation justified? |
|
||||
|
||||
#### Implementation Plan Review
|
||||
|
||||
| # | Check | What to verify |
|
||||
|---|-------|---------------|
|
||||
| 6 | All requirements covered | Every Jira requirement maps to at least one implementation step |
|
||||
| 7 | Correct PAISY patterns | Plan references correct patterns (AbstractMeldung, Datenbaustein, ServiceCenter, EMFactory, JAXB) |
|
||||
| 8 | File paths correct | All referenced file paths exist and are accurate |
|
||||
| 9 | Implementation order logical | Steps are ordered correctly — dependencies before dependents |
|
||||
| 10 | No gaps in steps | No missing steps between plan items (e.g., missing Flyway migration, missing test) |
|
||||
| 11 | Flyway migrations planned | If DB changes needed: both H2 and Oracle variants mentioned? |
|
||||
| 12 | Error handling planned | Plan addresses error cases, not just happy path |
|
||||
| 13 | No scope creep | Plan doesn't include changes beyond what the ticket requires |
|
||||
|
||||
#### Test Plan Review
|
||||
|
||||
| # | Check | What to verify |
|
||||
|---|-------|---------------|
|
||||
| 14 | Coverage complete | Every implementation step has at least one test case |
|
||||
| 15 | Test types appropriate | Unit tests for logic, integration for DB/ServiceCenter, SSH for batch |
|
||||
| 16 | Edge cases covered | Null handling, empty dates, F; responses, boundary values |
|
||||
| 17 | Test class naming correct | Follows `<OriginalClass>Test.java` convention |
|
||||
| 18 | Test method naming correct | Follows `test<What>_<Scenario>_<Expected>()` pattern |
|
||||
| 19 | Test data defined | Required test fixtures and data are specified |
|
||||
| 20 | SSH tests identified | If batch/ServiceCenter changes: SSH test cases included? |
|
||||
|
||||
### 5. Verify cross-references
|
||||
|
||||
- Every class mentioned in the plan exists in the codebase
|
||||
- Every test case in the testplan maps to a plan step
|
||||
- Every plan step maps to a Jira requirement
|
||||
- Assessment risks are addressed by plan mitigations
|
||||
|
||||
### 5.5 Expert Panel Review (mandatory)
|
||||
|
||||
Before generating the verdict, run the `expert-panel-review` skill to get a multi-perspective analysis:
|
||||
|
||||
1. Load the `expert-panel-review` skill
|
||||
2. Execute with:
|
||||
- `ARTIFACT_TYPE`: `plan`
|
||||
- `ARTIFACT_PATH`: the plan document path (`docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-plan.md`)
|
||||
3. Incorporate the panel's findings into the review:
|
||||
- Panel blockers (❌) → add to "Muss überarbeitet werden" section
|
||||
- Panel warnings (⚠️) → add to "Hinweise" section
|
||||
- Panel confidence level → include in Verdict section
|
||||
4. If panel confidence < 70%: verdict MUST be 🔄 REVISE regardless of checklist results
|
||||
|
||||
The expert panel provides Domain Expert (🏛️), Architecture Expert (🔧), and Risk/Compliance Expert (🛡️) perspectives. This catches domain-level errors that the mechanical checklist alone cannot detect.
|
||||
|
||||
### 6. Generate plan review document
|
||||
|
||||
Write `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-plan-review.md`:
|
||||
|
||||
```markdown
|
||||
# Plan Review: <TICKET_KEY> — <Summary>
|
||||
|
||||
**Datum:** <today>
|
||||
**Modul:** <MODULE>
|
||||
**Reviewer:** Roo (Plan Reviewer)
|
||||
**Dokumente:** assessment.md v<N>, plan.md v<N>, testplan.md v<N>
|
||||
**Verdict:** ✅ APPROVED / 🔄 REVISE
|
||||
|
||||
---
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
<1-2 sentence summary of the review outcome>
|
||||
|
||||
## Geprüfte Dokumente
|
||||
|
||||
| Dokument | Version | Bewertung |
|
||||
|----------|---------|-----------|
|
||||
| Assessment | v<N> | ✅ / ⚠️ / ❌ |
|
||||
| Plan | v<N> | ✅ / ⚠️ / ❌ |
|
||||
| Testplan | v<N> | ✅ / ⚠️ / ❌ |
|
||||
|
||||
## Checkliste
|
||||
|
||||
### Assessment
|
||||
|
||||
| # | Prüfpunkt | Ergebnis | Anmerkung |
|
||||
|---|-----------|----------|-----------|
|
||||
| 1 | Problemstellung vollständig | ✅/❌ | |
|
||||
| 2 | Betroffene Komponenten identifiziert | ✅/❌ | |
|
||||
| 3 | Ist-Zustand korrekt | ✅/❌ | |
|
||||
| 4 | Risikobewertung realistisch | ✅/❌ | |
|
||||
| 5 | Lösungsoptionen bewertet | ✅/❌ | |
|
||||
|
||||
### Implementierungsplan
|
||||
|
||||
| # | Prüfpunkt | Ergebnis | Anmerkung |
|
||||
|---|-----------|----------|-----------|
|
||||
| 6 | Alle Anforderungen abgedeckt | ✅/❌ | |
|
||||
| 7 | Korrekte PAISY-Patterns | ✅/❌ | |
|
||||
| 8 | Dateipfade korrekt | ✅/❌ | |
|
||||
| 9 | Implementierungsreihenfolge logisch | ✅/❌ | |
|
||||
| 10 | Keine Lücken in Schritten | ✅/❌ | |
|
||||
| 11 | Flyway-Migrationen geplant | ✅/N/A | |
|
||||
| 12 | Fehlerbehandlung geplant | ✅/❌ | |
|
||||
| 13 | Kein Scope Creep | ✅/❌ | |
|
||||
|
||||
### Testplan
|
||||
|
||||
| # | Prüfpunkt | Ergebnis | Anmerkung |
|
||||
|---|-----------|----------|-----------|
|
||||
| 14 | Abdeckung vollständig | ✅/❌ | |
|
||||
| 15 | Testtypen angemessen | ✅/❌ | |
|
||||
| 16 | Randfälle abgedeckt | ✅/❌ | |
|
||||
| 17 | Testklassen-Benennung korrekt | ✅/❌ | |
|
||||
| 18 | Testmethoden-Benennung korrekt | ✅/❌ | |
|
||||
| 19 | Testdaten definiert | ✅/❌ | |
|
||||
| 20 | SSH-Tests identifiziert | ✅/N/A | |
|
||||
|
||||
## Befunde
|
||||
|
||||
### ❌ Muss überarbeitet werden (blocking)
|
||||
|
||||
1. **<document>** — <description of issue>
|
||||
- Empfehlung: <what needs to change>
|
||||
|
||||
### ⚠️ Hinweise (non-blocking)
|
||||
|
||||
1. **<document>** — <description of suggestion>
|
||||
- Empfehlung: <improvement suggestion>
|
||||
|
||||
## Traceability Matrix
|
||||
|
||||
| Jira-Anforderung | Plan-Schritt | Testfall | Status |
|
||||
|-----------------|-------------|----------|--------|
|
||||
| <requirement 1> | Step <N> | T-<NN> | ✅ Abgedeckt |
|
||||
| <requirement 2> | Step <N> | T-<NN> | ❌ Fehlt |
|
||||
|
||||
## Verdict
|
||||
|
||||
**✅ APPROVED** — Plan ist vollständig, korrekt und umsetzungsbereit. Empfehlung: GO erteilen.
|
||||
— oder —
|
||||
**🔄 REVISE** — <N> Punkte müssen überarbeitet werden. Zurück an Planner für v<N+1>.
|
||||
**Panel-Confidence:** <X>% (<Domain: Y%, Architecture: Z%, Risk: W%>)
|
||||
```
|
||||
|
||||
### 7. Store in BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"{TICKET_KEY}: Plan review completed — {verdict}. {findings_count} findings ({blockers} blocking)."
|
||||
)
|
||||
```
|
||||
|
||||
## Expected Output
|
||||
|
||||
- Plan review document at `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-plan-review.md`
|
||||
- Clear verdict: APPROVED or REVISE
|
||||
- Traceability matrix linking requirements → plan steps → test cases
|
||||
- BigMind fact stored
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| Assessment missing | Flag as REVISE — assessment is required before plan review |
|
||||
| Plan missing | Flag as REVISE — cannot review without a plan |
|
||||
| Testplan missing | Flag as REVISE — testplan is required |
|
||||
| Referenced file not found | Flag specific file path as incorrect in findings |
|
||||
| Worktree not found | Use main repo to verify file paths |
|
||||
|
||||
## Verdict Criteria
|
||||
|
||||
| Verdict | Criteria |
|
||||
|---------|---------|
|
||||
| ✅ APPROVED | All 20 checklist items pass (✅ or N/A). No blocking findings. |
|
||||
| 🔄 REVISE | Any checklist item fails (❌). One or more blocking findings. |
|
||||
|
||||
## Review Loop
|
||||
|
||||
The Plan Reviewer creates a feedback loop with the Planner:
|
||||
|
||||
1. Planner produces assessment v1, plan v1, testplan v1
|
||||
2. Plan Reviewer reviews → REVISE with specific findings
|
||||
3. Planner revises → assessment v2, plan v2, testplan v2
|
||||
4. Plan Reviewer reviews → APPROVED
|
||||
5. Patrick gives GO
|
||||
6. Pipeline proceeds to Phase 3 (JiraOps)
|
||||
|
||||
This loop continues until APPROVED. Maximum 3 iterations recommended — if still not approved after v3, escalate to Patrick for manual review.
|
||||
|
||||
## Language
|
||||
|
||||
- Document content: **German**
|
||||
- Code references (class names, methods, patterns): English as-is
|
||||
- Checklist items: German
|
||||
@@ -0,0 +1,452 @@
|
||||
# Skill: security-review
|
||||
|
||||
Security-focused code review against ADP security policies and PAISY patterns.
|
||||
|
||||
## Description
|
||||
|
||||
Analyzes code changes against ADP's 67 SEC-* security rules, OWASP guidelines, and 10 PAISY-specific security patterns. Integrates automated scan results (SonarQube via MCP, DataRake secrets detection) with a 16-item manual checklist. Produces a structured security review report with a clear PASS/FAIL verdict. PASS is required before code review can proceed.
|
||||
|
||||
## Invoked by
|
||||
|
||||
🔒 Security Reviewer mode
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TICKET_KEY` | Jira issue key | `ESIDEPAISY-12081` |
|
||||
| `MODULE` | PAISY module name | `eau`, `eubp`, `svmeldungen` |
|
||||
|
||||
## Output
|
||||
|
||||
Markdown file: `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-security-review.md`
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Get the diff
|
||||
|
||||
```bash
|
||||
cd /Users/pplate/git/paisy-<TICKET_KEY>
|
||||
git diff origin/current --name-only
|
||||
git diff origin/current --stat
|
||||
git diff origin/current
|
||||
```
|
||||
|
||||
Identify all changed files. Separate Java source files from test files, resources, and documentation.
|
||||
|
||||
### 2. Read changed files fully for context
|
||||
|
||||
For each changed Java file, read the full file — not just the diff hunks. Security issues often depend on surrounding context (e.g., a method that looks safe in isolation but is called with untrusted input).
|
||||
|
||||
```bash
|
||||
cd /Users/pplate/git/paisy-<TICKET_KEY>
|
||||
git diff origin/current --name-only | grep "\.java$"
|
||||
```
|
||||
|
||||
### 3. Run SonarQube analyze_code_snippet on changed files
|
||||
|
||||
For each changed Java file, use the SonarQube MCP tool:
|
||||
|
||||
```python
|
||||
# Read the full file content
|
||||
file_content = read_file("<path_to_changed_file>")
|
||||
|
||||
# Analyze with SonarQube
|
||||
analyze_code_snippet(
|
||||
fileContent=file_content,
|
||||
language=["java"],
|
||||
scope=["MAIN"] # or ["TEST"] for test files
|
||||
)
|
||||
```
|
||||
|
||||
Collect all SonarQube findings. Filter for security-relevant rules (SECURITY impact software quality).
|
||||
|
||||
#### 3.1 DataRake Secrets Scan (Pipeline-Äquivalent)
|
||||
|
||||
ADP's Jenkins-Pipeline ruft `secretsScan()` über das **DataRake**-Widget auf (regex-basierter Secrets-Detector). Der Reviewer simuliert dieses Verhalten manuell, da DataRake nicht als MCP-Tool verfügbar ist.
|
||||
|
||||
**Was DataRake erkennt:**
|
||||
- Passwörter (Literalwerte in sicherheitsrelevanten Kontexten)
|
||||
- Tokens (Basic Auth, Bearer, JWT)
|
||||
- Unverschlüsselte Private Keys
|
||||
- Gefährliche Dateien (`.netrc`, Java Keystores `.jks`/`.p12`, SSH Private Keys)
|
||||
- Gefährliche Kommandos, die Credentials offenlegen
|
||||
- Hartkodierte Secrets in JDBC-Connection-Strings (Oracle, MySQL, PostgreSQL, Informix)
|
||||
|
||||
**Detection-Regeln (wichtig für die Beurteilung):**
|
||||
- Passwort-Werte müssen **6–70 Zeichen** lang sein, um zu triggern (kürzere Werte werden als Placeholder gefiltert)
|
||||
- JDBC-Rakes erkennen `user/password` direkt in URL-Connection-Strings
|
||||
- Dateiendung entscheidet, welche Rakes greifen (`.java` → Java-spezifische Rakes)
|
||||
- **Nur Single-Line-Matching** — über mehrere Zeilen verteilte Secrets werden nicht erkannt
|
||||
|
||||
**Schweregrade laut DataRake:**
|
||||
|
||||
| Schweregrad | Kontext | Begründung |
|
||||
|-------------|---------|-----------|
|
||||
| CRITICAL | Passwort/Token in HTML oder JavaScript | Kann ADP-Netzwerk verlassen (Browser-deliverable) |
|
||||
| HIGH | Secrets in anderem Source-Code (`.java`, `.yml`, `.properties`, `.sh`) | Im Repository sichtbar |
|
||||
| MEDIUM / LOW | Review-würdige Items (Keystores, verdächtige Muster) | Manuelle Bewertung nötig |
|
||||
|
||||
**Manuelles Scan-Vorgehen:**
|
||||
|
||||
```bash
|
||||
# 1. Verdächtige Dateien identifizieren
|
||||
cd /Users/pplate/git/paisy-<TICKET_KEY>
|
||||
git diff origin/current --name-only | grep -E '\.(java|yml|yaml|properties|xml|sh|js|html|jsp)$'
|
||||
|
||||
# 2. Auf typische Secret-Patterns prüfen (6–70 Zeichen)
|
||||
git diff origin/current | grep -iE '(password|passwd|pwd|token|api[_-]?key|secret)\s*[:=]\s*["\x27][^"\x27]{6,70}["\x27]'
|
||||
|
||||
# 3. JDBC-Connection-Strings auf Inline-Credentials prüfen
|
||||
git diff origin/current | grep -iE 'jdbc:[^"\x27\s]*(user|password)='
|
||||
|
||||
# 4. Gefährliche Dateien finden
|
||||
git diff origin/current --name-only | grep -iE '(\.netrc|\.jks|\.p12|id_rsa|id_dsa|id_ecdsa)$'
|
||||
```
|
||||
|
||||
Quelle: Confluence EIT-Space, Seiten `3270157258` (DataRake), `3270157260` (FAQ), `3270157263` (JDBC Rakes).
|
||||
|
||||
### 4. Apply SEC-* rules — manual checklist (16 items)
|
||||
|
||||
For each changed file, systematically check:
|
||||
|
||||
| # | Rules | Check | What to look for |
|
||||
|---|-------|-------|-----------------|
|
||||
| 1 | SEC-001..004 | No hardcoded credentials | Passwords, API keys, tokens, JDBC credentials in string literals. Exclude test files. |
|
||||
| 2 | SEC-005 | Credentials via `@Value`/env | All credentials must come from `@Value("${...}")`, `System.getProperty()`, or `System.getenv()`. No `private static final String PASSWORD = "..."`. |
|
||||
| 3 | SEC-011 | No SQL injection | All SQL must use parameterized queries (`?` placeholders, `@Query` with `:param`, JPA Criteria API). No string concatenation in SQL. |
|
||||
| 4 | SEC-012 | No path traversal | File paths from external input must be sanitized. Check for `new File(userInput)`, `Paths.get(userInput)` without validation. |
|
||||
| 5 | SEC-016 | Input validation | All external data entry points (REST endpoints, file parsers, PAISY responses) must validate input before processing. |
|
||||
| 6 | SEC-018 | No info disclosure in errors | Error messages must not expose stack traces, internal paths, SQL queries, or system details to callers. |
|
||||
| 7 | SEC-033 | PII encryption | Payroll data, HR data, personal data must be encrypted at rest. Check for PII stored in plain text in new DB columns. |
|
||||
| 8 | SEC-035 | No PII in LLM processing | No personal data (names, BBNR, Versicherungsnummer) sent to AI/LLM services. |
|
||||
| 9 | SEC-040 | No sensitive data in logs | Log statements must not contain passwords, tokens, PII, or full payroll records. Check `log.debug/info/warn/error` calls. |
|
||||
| 10 | SEC-055 | No `src.gen/` modifications | Files under `src.gen/` are JAXB-generated. Any modification is silently overwritten and creates false security. |
|
||||
| 11 | SEC-057 | ServiceCenter `F;` response validation | Every `ServiceCenter.INSTANCE()` call must check if the response starts with `F;` before parsing. Unchecked `F;` responses can lead to corrupted payroll data sent to government agencies. |
|
||||
| 12 | SEC-058 | Date sentinel handling | Before parsing dates from PAISY, check for sentinel values: `00.00.0000`, `0000000`, `9999999`. Parsing these causes `DateTimeParseException` or silently wrong date calculations. |
|
||||
| 13 | SEC-059 | Batch EntityManager flush/clear | Batch processing loops must call `em.flush()` and `em.clear()` every 100 items. Without this, the JPA persistence context grows unbounded → `OutOfMemoryError` in production. |
|
||||
| 14 | SEC-060 | Dual Flyway migrations | Every new migration must exist in BOTH `db/migration/H2/` AND `db/migration/ORACLE/`. Missing one breaks either dev/test (H2) or production (Oracle). |
|
||||
| 15 | SEC-061 | No hardcoded BBNR/IDs | No hardcoded Betriebsnummern, sprint IDs, Epic keys, or instance names. These must come from configuration or runtime lookup. |
|
||||
| 16 | SEC-064 | DataRake compliance — no secrets in source | No literal passwords/tokens (6–70 chars), no inline credentials in JDBC URLs, no committed keystores/SSH keys, no dangerous credential-exposing commands. H2 test DBs must use random UUID passwords, not default `sa`/empty. |
|
||||
|
||||
### 5. Check PAISY-specific patterns (SEC-055 through SEC-063) with code examples
|
||||
|
||||
For each PAISY-specific rule, verify against the actual code:
|
||||
|
||||
#### SEC-055: src.gen/ protection
|
||||
```bash
|
||||
# Check if any changed files are under src.gen/
|
||||
git diff origin/current --name-only | grep "src\.gen/"
|
||||
# If any match → CRITICAL finding
|
||||
```
|
||||
|
||||
#### SEC-056: JAXB namespace
|
||||
```java
|
||||
// ❌ FAIL — javax namespace (legacy)
|
||||
import javax.xml.bind.annotation.*;
|
||||
|
||||
// ✅ PASS — jakarta namespace
|
||||
import jakarta.xml.bind.annotation.*;
|
||||
```
|
||||
|
||||
#### SEC-057: ServiceCenter F; validation
|
||||
```java
|
||||
// ❌ UNSAFE — no error check
|
||||
String response = ServiceCenter.INSTANCE().getPaisy().pgmReadLine();
|
||||
String[] parts = response.split(";");
|
||||
String bbnr = parts[1]; // ArrayIndexOutOfBoundsException or wrong data if F; response
|
||||
|
||||
// ✅ SAFE — error check first
|
||||
String response = ServiceCenter.INSTANCE().getPaisy().pgmReadLine();
|
||||
if (response.startsWith("F;")) {
|
||||
log.error("PAISY error: {}", response);
|
||||
throw new PaisyRuntimeException("ServiceCenter error: " + response);
|
||||
}
|
||||
String[] parts = response.split(";");
|
||||
```
|
||||
|
||||
#### SEC-058: Date sentinel handling
|
||||
```java
|
||||
// ❌ UNSAFE — no sentinel check
|
||||
LocalDate date = LocalDate.parse(paiDate, formatter);
|
||||
|
||||
// ✅ SAFE — sentinel check first
|
||||
if (paiDate.equals("00.00.0000") || paiDate.equals("0000000") || paiDate.equals("9999999")) {
|
||||
return null; // or LocalDate.MAX / LocalDate.MIN as appropriate
|
||||
}
|
||||
LocalDate date = LocalDate.parse(paiDate, formatter);
|
||||
```
|
||||
|
||||
#### SEC-059: Batch EM flush/clear
|
||||
```java
|
||||
// ❌ UNSAFE — no flush/clear in batch loop
|
||||
for (Record record : records) {
|
||||
em.persist(record);
|
||||
}
|
||||
|
||||
// ✅ SAFE — flush/clear every 100 items
|
||||
for (int i = 0; i < records.size(); i++) {
|
||||
em.persist(records.get(i));
|
||||
if (i % 100 == 0) {
|
||||
em.flush();
|
||||
em.clear();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### SEC-060: Dual Flyway migrations
|
||||
```bash
|
||||
# Check for new migration files
|
||||
git diff origin/current --name-only | grep "db/migration"
|
||||
# For each H2 migration, verify a matching ORACLE migration exists (and vice versa)
|
||||
```
|
||||
|
||||
#### SEC-061: No hardcoded identifiers
|
||||
```java
|
||||
// ❌ FAIL — hardcoded BBNR
|
||||
String bbnr = "12345678";
|
||||
|
||||
// ❌ FAIL — hardcoded sprint ID
|
||||
int sprintId = 1234;
|
||||
|
||||
// ✅ PASS — from configuration
|
||||
@Value("${paisy.bbnr}")
|
||||
private String bbnr;
|
||||
```
|
||||
|
||||
#### SEC-062: CSV encoding
|
||||
```java
|
||||
// ❌ FAIL — wrong encoding
|
||||
new FileReader(csvFile, StandardCharsets.UTF_8);
|
||||
|
||||
// ✅ PASS — correct German government standard
|
||||
new FileReader(csvFile, Charset.forName("ISO-8859-1"));
|
||||
```
|
||||
|
||||
#### SEC-063: Parameterized logging
|
||||
```java
|
||||
// ❌ FAIL — string concatenation
|
||||
log.debug("Processing BBNR: " + bbnr + " with status: " + status);
|
||||
|
||||
// ✅ PASS — parameterized
|
||||
log.debug("Processing BBNR: {} with status: {}", bbnr, status);
|
||||
```
|
||||
|
||||
#### SEC-064: DataRake compliance — H2 test database pattern
|
||||
|
||||
H2 in-memory Test-Datenbanken sind ein häufiger Auslöser für DataRake-Findings. Der **default user `sa` mit leerem Passwort** triggert die JDBC-Rakes nicht zuverlässig (`sa` < 6 Zeichen), aber jeder kurze hartkodierte Wert in `JDBC_PASSWORD` kann als Secret erkannt werden, sobald er die 6-Zeichen-Schwelle überschreitet.
|
||||
|
||||
```java
|
||||
// ✅ SAFE — kein User gesetzt, zufälliges UUID-Passwort (wird nicht als Secret erkannt,
|
||||
// da UUID-Format als Test-Pattern gefiltert wird und kein User → kein JDBC-Rake-Match)
|
||||
props.put(JDBC_DRIVER, "org.h2.Driver");
|
||||
props.put(JDBC_URL, "jdbc:h2:mem:test_db;DB_CLOSE_DELAY=-1;MODE=Oracle");
|
||||
props.put(JDBC_PASSWORD, UUID.randomUUID().toString());
|
||||
|
||||
// ❌ TRIGGERS — default user "sa" + festes kurzes Passwort
|
||||
props.put(JDBC_USER, "sa");
|
||||
props.put(JDBC_PASSWORD, "testpassword123");
|
||||
|
||||
// ❌ TRIGGERS — Inline-Credentials im JDBC-URL
|
||||
props.put(JDBC_URL, "jdbc:oracle:thin:scott/tiger123@//host:1521/SID");
|
||||
|
||||
// ✅ SAFE — Credentials separat, via @Value oder env
|
||||
@Value("${db.user}")
|
||||
private String dbUser;
|
||||
@Value("${db.password}")
|
||||
private String dbPassword;
|
||||
```
|
||||
|
||||
**Generelle Regeln zur Vermeidung von DataRake-Findings:**
|
||||
- Keine literalen Passwörter (6–70 Zeichen) in `.java`, `.yml`, `.properties`, `.xml`, `.sh`
|
||||
- Keine Inline-Credentials in JDBC-URLs (`user=`/`password=` im URL-String)
|
||||
- Keine Java Keystores (`.jks`, `.p12`), SSH Private Keys oder `.netrc`-Dateien im Repository
|
||||
- Template-Variablen verwenden: `${ENV_VAR}`, `{placeholder}`, `((concourse-var))` — DataRake filtert diese als StandardPatterns
|
||||
- Für Tests: `UUID.randomUUID().toString()` oder `ENC[AES256,...]` für verschlüsselte Werte
|
||||
|
||||
Präzedenzfall: `ESIDEPAISY-12154` dokumentiert das Pattern `user=password=<short_value>` als bewusst akzeptierten lokalen Dev-Pattern.
|
||||
|
||||
### 6. Identify false positives
|
||||
|
||||
Before flagging a finding, check against known false positive patterns:
|
||||
|
||||
| Pattern | Tool | Why It's Safe | Action |
|
||||
|---------|------|--------------|--------|
|
||||
| Variable self-assignment | DataRake | Variable assignment, not a password literal | Skip |
|
||||
| Credential parsing from connection string | DataRake | Extracting, not hardcoding | Skip |
|
||||
| Environment variable retrieval | DataRake | Runtime injection, not hardcoded | Skip |
|
||||
| Test data in `src/test/` | Both | Test-only scope, never deployed | Skip (unless test exposes real credentials) |
|
||||
| Application-specific passwords by design | DataRake | Business logic requirement (e.g., PDF encryption) | Document as exception |
|
||||
| Log file matches | DataRake | Build artifacts, not source code | Skip |
|
||||
| Snyk result files | DataRake | Scan output, not source | Skip |
|
||||
| Username=password pattern for local dev | DataRake | Intentional dev-only pattern (ESIDEPAISY-12154 precedent) | Document as accepted risk |
|
||||
|
||||
#### DataRake StandardPatternFilters (built-in false positives)
|
||||
|
||||
DataRake filtert die folgenden Werte automatisch — sie lösen **kein** Finding aus und müssen nicht als False Positive dokumentiert werden:
|
||||
|
||||
| Pattern-Beispiel | Typ | Begründung |
|
||||
|------------------|-----|-----------|
|
||||
| `${variable_name}` | Spring/Shell Template | Wird zur Laufzeit ersetzt |
|
||||
| `{variable}` | Bare Braces | Template-Platzhalter |
|
||||
| `{{variable}}` | Handlebars / Helm Template | Template-Engine-Syntax |
|
||||
| `$(variable)` | Shell Substitution | Wird zur Laufzeit ersetzt |
|
||||
| `$VARIABLE` | Bare Dollar Sign | Shell-/Env-Variable |
|
||||
| `%variable%` | Windows Env Style | Wird zur Laufzeit ersetzt |
|
||||
| `#variable#` | Hash-Delimited | Template-Platzhalter |
|
||||
| `??variable??` | Null-Coalescing Style | Template-Platzhalter |
|
||||
| `((concourse-placeholder))` | Concourse/Pipeline | Pipeline-Variable |
|
||||
| `XXXXXXXXXX` / `xxxxxxxxxx` | Repeated Single Char | Regex `^([0-9A-ZxX+#*-])(\1)+$` |
|
||||
| `test-test`, `foo_foo`, `aaaaaa` | Repeated Word | 3–10 gleiche Zeichen/Wortgruppen |
|
||||
| `ENC[AES256,...]` | AES256-verschlüsselt | Bereits sicher verschlüsselt |
|
||||
| Werte unter 6 Zeichen | Zu kurz | Alle Regexes verlangen `{6,70}` |
|
||||
| `example.com`, `test.de` | Domain/URL | Beispiel-Domains |
|
||||
|
||||
**Konsequenz für den Reviewer:** Tritt einer dieser Patterns im Diff auf, ist es **kein Finding** — auch wenn der Kontext "password" oder "secret" enthält. Nicht in den False-Positive-Report aufnehmen, sondern still überspringen.
|
||||
|
||||
Also search BigMind for known false positive patterns:
|
||||
```python
|
||||
memory_search_facts("false positive security")
|
||||
memory_search_facts("SecBench accepted")
|
||||
```
|
||||
|
||||
### 7. Generate security review document
|
||||
|
||||
Write `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-security-review.md`:
|
||||
|
||||
```markdown
|
||||
# Security Review: <TICKET_KEY> — <Summary>
|
||||
|
||||
**Datum:** <today>
|
||||
**Modul:** <MODULE>
|
||||
**Reviewer:** Roo (Security Reviewer)
|
||||
**Branch:** <branch name>
|
||||
**Verdict:** ✅ PASS / ❌ FAIL
|
||||
|
||||
---
|
||||
|
||||
## Scan-Ergebnisse
|
||||
|
||||
| Tool | Status | Befunde |
|
||||
|------|--------|---------|
|
||||
| SonarQube (SAST) | ✅ Sauber / ⚠️ N Befunde | <details> |
|
||||
| Datarake (Secrets) | ✅ Sauber / ⚠️ N Befunde / ⏭️ Nicht verfügbar | <details> |
|
||||
| Snyk Code | ✅ Sauber / ⚠️ N Befunde / ⏭️ Nicht verfügbar | <details> |
|
||||
|
||||
## Manuelle Sicherheits-Checkliste
|
||||
|
||||
| # | Regel | Prüfpunkt | Ergebnis | Anmerkung |
|
||||
|---|-------|-----------|----------|-----------|
|
||||
| 1 | SEC-001..004 | Keine hartkodierten Credentials | ✅/❌ | |
|
||||
| 2 | SEC-005 | Credentials via @Value/env | ✅/❌ | |
|
||||
| 3 | SEC-011 | Keine SQL-Injection | ✅/❌ | |
|
||||
| 4 | SEC-012 | Kein Path Traversal | ✅/❌ | |
|
||||
| 5 | SEC-016 | Input-Validierung | ✅/❌ | |
|
||||
| 6 | SEC-018 | Keine Info-Disclosure in Fehlern | ✅/❌ | |
|
||||
| 7 | SEC-033 | PII-Verschlüsselung | ✅/N/A | |
|
||||
| 8 | SEC-035 | Kein PII in LLM-Verarbeitung | ✅/N/A | |
|
||||
| 9 | SEC-040 | Keine sensiblen Daten in Logs | ✅/❌ | |
|
||||
| 10 | SEC-055 | Keine src.gen/ Änderungen | ✅/❌ | |
|
||||
| 11 | SEC-057 | F;-Response-Validierung | ✅/N/A | |
|
||||
| 12 | SEC-058 | Datums-Sentinel-Behandlung | ✅/N/A | |
|
||||
| 13 | SEC-059 | Batch-EM-Flush/Clear | ✅/N/A | |
|
||||
| 14 | SEC-060 | Duale Flyway-Migrationen | ✅/N/A | |
|
||||
| 15 | SEC-061 | Keine hartkodierten BBNR/IDs | ✅/❌ | |
|
||||
| 16 | SEC-064 | DataRake-Compliance (keine Secrets im Source) | ✅/❌ | |
|
||||
|
||||
## Befunde
|
||||
|
||||
### ❌ Kritisch / Hoch (muss behoben werden)
|
||||
|
||||
1. **<file>:<line>** — [SEC-XXX] <Beschreibung>
|
||||
- Schweregrad: Critical/High
|
||||
- Empfehlung: <Behebungsvorschlag>
|
||||
|
||||
### ⚠️ Mittel (sollte behoben werden)
|
||||
|
||||
1. **<file>:<line>** — [SEC-XXX] <Beschreibung>
|
||||
- Empfehlung: <Behebungsvorschlag>
|
||||
|
||||
### ℹ️ Niedrig / Info
|
||||
|
||||
1. **<file>:<line>** — [SEC-XXX] <Beschreibung>
|
||||
|
||||
## Identifizierte False Positives
|
||||
|
||||
| Tool | Datei | Befund | Begründung |
|
||||
|------|-------|--------|-----------|
|
||||
| <tool> | <file> | <finding> | <why it's safe> |
|
||||
|
||||
## Verdict
|
||||
|
||||
**✅ PASS** — Keine kritischen oder hohen Sicherheitsbefunde. Weiter zum Code Review.
|
||||
— oder —
|
||||
**❌ FAIL** — N kritische/hohe Befunde müssen vor dem Code Review behoben werden.
|
||||
```
|
||||
|
||||
### 8. Determine verdict
|
||||
|
||||
| Verdict | Criteria | Pipeline Action |
|
||||
|---------|---------|----------------|
|
||||
| ✅ PASS | No Critical or High findings after false positive filtering | Proceed to Phase 6 (Code Review) |
|
||||
| ❌ FAIL | Any Critical or High finding remains | Loop back to Phase 4 (Code mode) for fixes, then re-review |
|
||||
|
||||
### 9. Store findings in BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"{TICKET_KEY}: Security review {verdict}. {total_findings} findings ({critical} Critical, {high} High, {medium} Medium, {low} Low). {false_positives} false positives identified."
|
||||
)
|
||||
|
||||
# For significant findings, store details
|
||||
memory_append_chunk(
|
||||
session_id=SESSION_ID,
|
||||
content=f"Security review for {TICKET_KEY}:\nVerdict: {verdict}\nFindings: {details}\nFalse positives: {fp_details}",
|
||||
flag_reason="security review findings"
|
||||
)
|
||||
```
|
||||
|
||||
## Expected Output
|
||||
|
||||
- Security review document at `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-security-review.md`
|
||||
- SonarQube scan results integrated (where available)
|
||||
- All 16 manual checklist items evaluated (incl. DataRake secrets compliance)
|
||||
- False positives identified and documented with rationale
|
||||
- Clear PASS/FAIL verdict
|
||||
- BigMind fact stored
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| Worktree not found | Check if `/Users/pplate/git/paisy-<TICKET_KEY>` exists, or use main repo with branch checkout |
|
||||
| SonarQube MCP unavailable | Skip automated scan, note in report as "⏭️ Nicht verfügbar", rely on manual checklist |
|
||||
| DataRake not available as MCP | Expected — always perform manual DataRake simulation via Step 3.1 grep commands |
|
||||
| No Java files changed | Skip SonarQube scan and SAST checks, focus on configuration/resource security |
|
||||
| Empty diff | Branch identical to `current` — report "no changes to review" |
|
||||
| Large diff (>50 files) | Focus on high-risk files first: files with `ServiceCenter`, `EntityManager`, `@Value`, SQL, file I/O |
|
||||
|
||||
## Severity Levels
|
||||
|
||||
| Severity | Symbol | Definition | SLA | Pipeline Impact |
|
||||
|----------|--------|-----------|-----|----------------|
|
||||
| Critical | ❌ | Exploitable vulnerability, hardcoded production credentials, data corruption risk | Fix immediately | Blocks pipeline — FAIL |
|
||||
| High | ❌ | Security weakness that could be exploited with effort, missing input validation on external data | Fix before merge | Blocks pipeline — FAIL |
|
||||
| Medium | ⚠️ | Security improvement needed but not immediately exploitable | Fix in sprint | Advisory — PASS with warnings |
|
||||
| Low | ℹ️ | Best practice suggestion, defense-in-depth improvement | Fix when convenient | Advisory — PASS |
|
||||
|
||||
## Language
|
||||
|
||||
- Document content: **German**
|
||||
- Code references (class names, methods, file paths): English as-is
|
||||
- Checklist items: German
|
||||
- BigMind facts: English
|
||||
|
||||
## Conventions
|
||||
|
||||
- One security review per ticket — don't split across multiple documents
|
||||
- Always run SonarQube `analyze_code_snippet` when MCP tool is available
|
||||
- Document ALL false positives with rationale — this builds the knowledge base
|
||||
- Reference SEC-* rule IDs in all findings for traceability
|
||||
- If a finding was previously accepted as risk (check BigMind), note it but don't re-flag
|
||||
@@ -0,0 +1,238 @@
|
||||
# Skill: sprint-report
|
||||
|
||||
Generate sprint status report from Jira data.
|
||||
|
||||
## Invoked by
|
||||
|
||||
🎫 JiraOps mode (or 🪃 Orchestrator delegating to JiraOps)
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `PROJECT_KEY` | Jira project key | `ESIDEPAISY` |
|
||||
| `SPRINT_ID` | Sprint ID (optional — auto-detected if omitted) | `1234` |
|
||||
| `OUTPUT_FORMAT` | Report format (optional) | `markdown`, `confluence`, `teams` |
|
||||
|
||||
## Output
|
||||
|
||||
- Markdown report: `docs/sprint-reports/sprint-<sprint_name>-<date>.md`
|
||||
- Optionally: Confluence page or Teams message
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Get active sprint
|
||||
|
||||
If `SPRINT_ID` is not provided, auto-detect:
|
||||
|
||||
```python
|
||||
# Get the board
|
||||
boards = get_agile_boards(project_key="ESIDEPAISY")
|
||||
board_id = boards[0]["id"]
|
||||
|
||||
# Get active sprint
|
||||
sprints = get_sprints_from_board(board_id=board_id, states="active")
|
||||
sprint = sprints[0]
|
||||
sprint_id = sprint["id"]
|
||||
sprint_name = sprint["name"]
|
||||
```
|
||||
|
||||
### 2. Get sprint tickets
|
||||
|
||||
```python
|
||||
tickets = get_tickets_from_sprint(
|
||||
sprint_id=sprint_id,
|
||||
fields="project,summary,status,issuetype,assignee,customfield_10001,customfield_10106"
|
||||
)
|
||||
```
|
||||
|
||||
Key fields:
|
||||
- `status` — current ticket status
|
||||
- `assignee` — who's working on it
|
||||
- `issuetype` — Story, Bug, Task
|
||||
- `customfield_10106` — Story Points (if configured)
|
||||
- `customfield_10001` — Feature Link (Epic)
|
||||
|
||||
### 3. Categorize tickets by status
|
||||
|
||||
Group tickets into workflow buckets:
|
||||
|
||||
| Category | Statuses |
|
||||
|----------|----------|
|
||||
| To Do | `Open`, `Backlog`, `To Do` |
|
||||
| In Progress | `In Progress`, `In Development` |
|
||||
| In Review | `In Review`, `Code Review` |
|
||||
| Done | `Done`, `Accepted`, `Closed` |
|
||||
| Blocked | Any ticket with `Blocked` flag or label |
|
||||
|
||||
### 4. Calculate metrics
|
||||
|
||||
```python
|
||||
total = len(tickets)
|
||||
done = len([t for t in tickets if t["status"] in DONE_STATUSES])
|
||||
in_progress = len([t for t in tickets if t["status"] in PROGRESS_STATUSES])
|
||||
todo = len([t for t in tickets if t["status"] in TODO_STATUSES])
|
||||
completion_pct = round(done / total * 100) if total > 0 else 0
|
||||
```
|
||||
|
||||
### 5. Group by assignee
|
||||
|
||||
```python
|
||||
by_assignee = {}
|
||||
for ticket in tickets:
|
||||
assignee = ticket.get("assignee", "Unassigned")
|
||||
by_assignee.setdefault(assignee, []).append(ticket)
|
||||
```
|
||||
|
||||
### 6. Group by Epic/Feature
|
||||
|
||||
```python
|
||||
by_epic = {}
|
||||
for ticket in tickets:
|
||||
epic = ticket.get("customfield_10001", "Kein Epic")
|
||||
by_epic.setdefault(epic, []).append(ticket)
|
||||
```
|
||||
|
||||
### 7. Generate report
|
||||
|
||||
Write `docs/sprint-reports/sprint-<sprint_name>-<date>.md`:
|
||||
|
||||
```markdown
|
||||
# Sprint Report: <sprint_name>
|
||||
|
||||
**Datum:** <today>
|
||||
**Sprint:** <sprint_name>
|
||||
**Zeitraum:** <start_date> — <end_date>
|
||||
**Projekt:** ESIDEPAISY
|
||||
|
||||
---
|
||||
|
||||
## Übersicht
|
||||
|
||||
| Metrik | Wert |
|
||||
|--------|------|
|
||||
| Tickets gesamt | <total> |
|
||||
| Erledigt | <done> (<completion_pct>%) |
|
||||
| In Bearbeitung | <in_progress> |
|
||||
| Offen | <todo> |
|
||||
| In Review | <in_review> |
|
||||
|
||||
## Fortschritt
|
||||
|
||||
```
|
||||
[████████████░░░░░░░░] 60% (<done>/<total>)
|
||||
```
|
||||
|
||||
## Nach Status
|
||||
|
||||
### ✅ Erledigt (<done>)
|
||||
|
||||
| Ticket | Typ | Zusammenfassung | Bearbeiter |
|
||||
|--------|-----|----------------|------------|
|
||||
| <key> | Story | <summary> | <assignee> |
|
||||
|
||||
### 🔄 In Bearbeitung (<in_progress>)
|
||||
|
||||
| Ticket | Typ | Zusammenfassung | Bearbeiter |
|
||||
|--------|-----|----------------|------------|
|
||||
| <key> | Bug | <summary> | <assignee> |
|
||||
|
||||
### ⏳ Offen (<todo>)
|
||||
|
||||
| Ticket | Typ | Zusammenfassung | Bearbeiter |
|
||||
|--------|-----|----------------|------------|
|
||||
| <key> | Task | <summary> | <assignee> |
|
||||
|
||||
## Nach Bearbeiter
|
||||
|
||||
| Bearbeiter | Gesamt | Erledigt | In Bearbeitung | Offen |
|
||||
|-----------|--------|----------|---------------|-------|
|
||||
| <name> | <n> | <done> | <wip> | <todo> |
|
||||
|
||||
## Nach Feature/Epic
|
||||
|
||||
| Epic | Tickets | Erledigt | Fortschritt |
|
||||
|------|---------|----------|-------------|
|
||||
| <epic_name> | <n> | <done> | <pct>% |
|
||||
|
||||
## Blocker / Risiken
|
||||
|
||||
| Ticket | Beschreibung | Seit | Auswirkung |
|
||||
|--------|-------------|------|-----------|
|
||||
| <key> | <blocker description> | <date> | <impact> |
|
||||
|
||||
<If no blockers: "Keine Blocker im aktuellen Sprint.">
|
||||
```
|
||||
|
||||
### 8. Publish to Confluence (optional)
|
||||
|
||||
If `OUTPUT_FORMAT` includes `confluence`:
|
||||
|
||||
```python
|
||||
create_page(
|
||||
space_key="ESIDEPAISY",
|
||||
title=f"Sprint Report: {sprint_name} — {date}",
|
||||
content=<html_converted_content>,
|
||||
parent_id="<sprint-reports-parent-page-id>"
|
||||
)
|
||||
```
|
||||
|
||||
### 9. Send Teams summary (optional)
|
||||
|
||||
If `OUTPUT_FORMAT` includes `teams`:
|
||||
|
||||
```python
|
||||
teams_send_channel_message(
|
||||
team_id="<team_id>",
|
||||
channel_id="<channel_id>",
|
||||
content=f"📊 *Sprint Report: {sprint_name}*\n\n"
|
||||
f"Fortschritt: {done}/{total} ({completion_pct}%)\n"
|
||||
f"In Bearbeitung: {in_progress}\n"
|
||||
f"Offen: {todo}\n"
|
||||
f"Blocker: {blocked}\n\n"
|
||||
f"Vollständiger Bericht: <confluence_link or file path>"
|
||||
)
|
||||
```
|
||||
|
||||
### 10. Store in BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"Sprint report for {sprint_name}: {done}/{total} done ({completion_pct}%), {in_progress} in progress, {blocked} blocked."
|
||||
)
|
||||
```
|
||||
|
||||
## Expected Output
|
||||
|
||||
- Markdown sprint report with ticket breakdown
|
||||
- Metrics: completion %, by-status, by-assignee, by-epic
|
||||
- Blocker/risk section
|
||||
- Optionally published to Confluence and/or Teams
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| No active sprint found | Check `states="active"` — may need `states="active,future"` |
|
||||
| No tickets in sprint | Sprint may be empty or newly created — report "0 tickets" |
|
||||
| Board not found | Verify project key, try `get_agile_boards` with different key |
|
||||
| Story points not configured | Skip story point metrics, use ticket count only |
|
||||
| Confluence publish fails | Save markdown locally, report Confluence error |
|
||||
|
||||
## Report Variants
|
||||
|
||||
| Variant | When | Content |
|
||||
|---------|------|---------|
|
||||
| Daily standup | Mid-sprint | Focus on in-progress + blockers only |
|
||||
| Sprint review | End of sprint | Full report with all sections |
|
||||
| Management summary | On request | Metrics + epic progress only, no ticket details |
|
||||
|
||||
Adjust the template based on the variant requested.
|
||||
|
||||
## Language
|
||||
|
||||
- Report content: **German**
|
||||
- Ticket keys, branch names: English as-is
|
||||
- Teams messages: **German**
|
||||
- Confluence page: **German**
|
||||
@@ -0,0 +1,154 @@
|
||||
# Skill: ssh-test-deploy
|
||||
|
||||
Deploy and test a module JAR on a PAISY SSH test instance.
|
||||
|
||||
## Invoked by
|
||||
|
||||
💻 Code mode (or 🪃 Orchestrator delegating to Code)
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TICKET_KEY` | Jira issue key | `ESIDEPAISY-12081` |
|
||||
| `MODULE` | PAISY module name | `eau`, `eubp`, `svmeldungen`, `dabpv` |
|
||||
| `PROGRAM` | PAI program to run | `PAI022`, `PAIBATCH`, `PAI030` |
|
||||
| `PROGRAM_ARGS` | Program arguments (optional) | `"-eau"`, `"-svmeldungen DSAK"` |
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. List available test instances
|
||||
|
||||
```python
|
||||
list-instances()
|
||||
```
|
||||
|
||||
Pick an appropriate instance based on module and availability. If the user has a preferred instance, use that.
|
||||
|
||||
### 2. Select the instance
|
||||
|
||||
```python
|
||||
set-instance(instance="<chosen instance>")
|
||||
```
|
||||
|
||||
### 3. Build the module JAR locally
|
||||
|
||||
```bash
|
||||
cd /Users/pplate/git/paisy-<TICKET_KEY>
|
||||
mvn package -pl java/modules/cs-modules/<MODULE> -am -DskipTests -f java/pom.xml
|
||||
```
|
||||
|
||||
Locate the built JAR:
|
||||
```bash
|
||||
find java/modules/cs-modules/<MODULE>/target -name "*.jar" -not -name "*-sources.jar" | head -1
|
||||
```
|
||||
|
||||
### 4. Upload JAR to instance
|
||||
|
||||
```python
|
||||
upload-file(
|
||||
localPath="/Users/pplate/git/paisy-<TICKET_KEY>/java/modules/cs-modules/<MODULE>/target/<MODULE>-<version>.jar",
|
||||
remoteFilename="<MODULE>-<version>.jar"
|
||||
)
|
||||
```
|
||||
|
||||
### 5. Run the program
|
||||
|
||||
```python
|
||||
run-program(
|
||||
program="<PROGRAM>",
|
||||
args="<PROGRAM_ARGS>"
|
||||
)
|
||||
```
|
||||
|
||||
For common programs:
|
||||
|
||||
| Program | Purpose | Typical args |
|
||||
|---------|---------|-------------|
|
||||
| `PAI022` | SV-Meldeverfahren batch | `"-svmeldungen DSAK"`, `"-svmeldungen DSBD"` |
|
||||
| `PAIBATCH` | General batch runner | module-specific |
|
||||
| `PAI030` | Lohnsteuer | `"-lstb"` |
|
||||
| `PAI028` | SVD import | (no args, reads SVD.XML) |
|
||||
|
||||
### 6. Parse output
|
||||
|
||||
Check the program output for errors:
|
||||
|
||||
```python
|
||||
# PAISY error responses start with "F;"
|
||||
# Success responses typically start with "0;" or contain "RC=0"
|
||||
```
|
||||
|
||||
| Pattern | Meaning | Action |
|
||||
|---------|---------|--------|
|
||||
| `F;` prefix | PAISY error | Log error, report to user |
|
||||
| `RC=0` | Success | Continue |
|
||||
| `RC=4` | Warning | Log warning, review output |
|
||||
| `RC=8` or higher | Error | Log error, investigate |
|
||||
|
||||
### 7. Verify with shell command (optional)
|
||||
|
||||
```python
|
||||
exec-command(command="ls -la /path/to/output/")
|
||||
exec-command(command="cat /path/to/logfile.log | tail -50")
|
||||
```
|
||||
|
||||
### 8. Log results to BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"{TICKET_KEY}: SSH test on <instance> — {PROGRAM} {PROGRAM_ARGS} → RC={rc}. <summary>"
|
||||
)
|
||||
memory_append_chunk(
|
||||
session_id=SESSION_ID,
|
||||
content=f"SSH test deploy for {TICKET_KEY}:\nInstance: <instance>\nProgram: {PROGRAM}\nResult: <output summary>",
|
||||
flag_reason="SSH test result"
|
||||
)
|
||||
```
|
||||
|
||||
## Expected Output
|
||||
|
||||
- Module JAR built and uploaded to test instance
|
||||
- Program executed with output captured
|
||||
- Results logged to BigMind
|
||||
- Error/success status reported to user
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| No instances available | `list-instances()` returns empty — ask user to check VPN/SSH access |
|
||||
| Build failure | Check Maven output for compilation errors, fix before retrying |
|
||||
| Upload failure | Verify instance is reachable, check disk space with `exec-command("df -h")` |
|
||||
| `F;` response | Parse error code, check ADP Docs Wiki for error meaning |
|
||||
| `RC=15` | Often means SVD.XML is outdated — run PAI028 first to import fresh SVD data |
|
||||
| Connection timeout | Instance may be down — try another instance from `list-instances()` |
|
||||
|
||||
## Common Workflows
|
||||
|
||||
### EAU test
|
||||
```python
|
||||
set-instance(instance="Nadine.123")
|
||||
run-program(program="PAI022", args="-eau")
|
||||
```
|
||||
|
||||
### SVMeldungen DSAK test
|
||||
```python
|
||||
set-instance(instance="Tanja.122")
|
||||
run-program(program="PAI022", args="-svmeldungen DSAK")
|
||||
```
|
||||
|
||||
### Full batch test
|
||||
```python
|
||||
# First update SVD data
|
||||
run-program(program="PAI028")
|
||||
# Then run the batch
|
||||
run-program(program="PAIBATCH", args="<module-specific>")
|
||||
```
|
||||
|
||||
## Language
|
||||
|
||||
- Log entries and BigMind facts: English
|
||||
- Error descriptions from PAISY: German (preserve as-is)
|
||||
- User-facing summaries: match user's language
|
||||
Reference in New Issue
Block a user