Skip to content

Commit dea9465

Browse files
Merge remote-tracking branch 'origin/main' into worktree-20260322-120216
# Conflicts: # .tickets/.index.json
2 parents 030b1b2 + cc25a16 commit dea9465

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2890
-123
lines changed

.test-index

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ plugins/dso/skills/plan-review/SKILL.md:plugins/dso/tests/test-sprint-skill-step
6767
plugins/dso/skills/playwright-debug/SKILL.md:plugins/dso/tests/test-sprint-skill-step10-no-merge-to-main.sh,tests/plugin/test-audit-skill-resolution.sh,tests/hooks/test-fix-bug-skill.sh,tests/hooks/test-generate-claude-md-skill.sh,tests/hooks/test-init-skill.sh,tests/scripts/test-qualify-skill-refs.sh,tests/scripts/test-skill-path-refs.sh,tests/scripts/test-check-skill-refs.sh,tests/skills/test_end_skill_final_verification_step.py,tests/skills/test_implementation_plan_skill_tdd_enforcement.py,tests/skills/test-quick-ref-skill.sh,tests/skills/test_project_setup_skill_conditional_prompts.py,tests/skills/test_fix_bug_skill.py,tests/skills/test_end_skill_summary_displays_stored_learnings.py,tests/skills/test_end_skill_learnings_step_before_commit.py,tests/skills/test-design-skills-cross-stack.sh,tests/skills/test_end_skill_dirty_worktree_resolution.py,tests/skills/test_fix_bug_skill_escalated_section.py,tests/skills/test_end_skill_bug_tickets_before_commit.py
6868
plugins/dso/skills/preplanning/docs/reviewers/performance.md:tests/hooks/test-performance-validation.sh
6969
plugins/dso/skills/preplanning/SKILL.md:plugins/dso/tests/test-sprint-skill-step10-no-merge-to-main.sh,tests/plugin/test-audit-skill-resolution.sh,tests/hooks/test-fix-bug-skill.sh,tests/hooks/test-generate-claude-md-skill.sh,tests/hooks/test-init-skill.sh,tests/scripts/test-qualify-skill-refs.sh,tests/scripts/test-skill-path-refs.sh,tests/scripts/test-check-skill-refs.sh,tests/skills/test_end_skill_final_verification_step.py,tests/skills/test_implementation_plan_skill_tdd_enforcement.py,tests/skills/test-quick-ref-skill.sh,tests/skills/test_project_setup_skill_conditional_prompts.py,tests/skills/test_fix_bug_skill.py,tests/skills/test_end_skill_summary_displays_stored_learnings.py,tests/skills/test_end_skill_learnings_step_before_commit.py,tests/skills/test-design-skills-cross-stack.sh,tests/skills/test_end_skill_dirty_worktree_resolution.py,tests/skills/test_fix_bug_skill_escalated_section.py,tests/skills/test_end_skill_bug_tickets_before_commit.py
70-
plugins/dso/skills/project-setup/SKILL.md:plugins/dso/tests/test-sprint-skill-step10-no-merge-to-main.sh,tests/plugin/test-audit-skill-resolution.sh,tests/hooks/test-fix-bug-skill.sh,tests/hooks/test-generate-claude-md-skill.sh,tests/hooks/test-init-skill.sh,tests/scripts/test-qualify-skill-refs.sh,tests/scripts/test-skill-path-refs.sh,tests/scripts/test-check-skill-refs.sh,tests/skills/test_end_skill_final_verification_step.py,tests/skills/test_implementation_plan_skill_tdd_enforcement.py,tests/skills/test-quick-ref-skill.sh,tests/skills/test_project_setup_skill_conditional_prompts.py,tests/skills/test_fix_bug_skill.py,tests/skills/test_end_skill_summary_displays_stored_learnings.py,tests/skills/test_end_skill_learnings_step_before_commit.py,tests/skills/test-design-skills-cross-stack.sh,tests/skills/test_end_skill_dirty_worktree_resolution.py,tests/skills/test_fix_bug_skill_escalated_section.py,tests/skills/test_end_skill_bug_tickets_before_commit.py
70+
plugins/dso/skills/project-setup/SKILL.md:plugins/dso/tests/test-sprint-skill-step10-no-merge-to-main.sh,tests/plugin/test-audit-skill-resolution.sh,tests/hooks/test-fix-bug-skill.sh,tests/hooks/test-generate-claude-md-skill.sh,tests/hooks/test-init-skill.sh,tests/scripts/test-qualify-skill-refs.sh,tests/scripts/test-skill-path-refs.sh,tests/scripts/test-check-skill-refs.sh,tests/skills/test_end_skill_final_verification_step.py,tests/skills/test_implementation_plan_skill_tdd_enforcement.py,tests/skills/test-quick-ref-skill.sh,tests/skills/test_project_setup_skill_conditional_prompts.py,tests/skills/test_fix_bug_skill.py,tests/skills/test_end_skill_summary_displays_stored_learnings.py,tests/skills/test_end_skill_learnings_step_before_commit.py,tests/skills/test-design-skills-cross-stack.sh,tests/skills/test_end_skill_dirty_worktree_resolution.py,tests/skills/test_fix_bug_skill_escalated_section.py,tests/skills/test_end_skill_bug_tickets_before_commit.py,tests/skills/test_project_setup_suite_placement.py,tests/skills/test-project-setup-ci-generation.sh
7171
plugins/dso/skills/quick-ref/SKILL.md:plugins/dso/tests/test-sprint-skill-step10-no-merge-to-main.sh,tests/plugin/test-audit-skill-resolution.sh,tests/hooks/test-fix-bug-skill.sh,tests/hooks/test-generate-claude-md-skill.sh,tests/hooks/test-init-skill.sh,tests/scripts/test-qualify-skill-refs.sh,tests/scripts/test-skill-path-refs.sh,tests/scripts/test-check-skill-refs.sh,tests/skills/test_end_skill_final_verification_step.py,tests/skills/test_implementation_plan_skill_tdd_enforcement.py,tests/skills/test-quick-ref-skill.sh,tests/skills/test_project_setup_skill_conditional_prompts.py,tests/skills/test_fix_bug_skill.py,tests/skills/test_end_skill_summary_displays_stored_learnings.py,tests/skills/test_end_skill_learnings_step_before_commit.py,tests/skills/test-design-skills-cross-stack.sh,tests/skills/test_end_skill_dirty_worktree_resolution.py,tests/skills/test_fix_bug_skill_escalated_section.py,tests/skills/test_end_skill_bug_tickets_before_commit.py
7272
plugins/dso/skills/resolve-conflicts/SKILL.md:plugins/dso/tests/test-sprint-skill-step10-no-merge-to-main.sh,tests/plugin/test-audit-skill-resolution.sh,tests/hooks/test-fix-bug-skill.sh,tests/hooks/test-generate-claude-md-skill.sh,tests/hooks/test-init-skill.sh,tests/scripts/test-qualify-skill-refs.sh,tests/scripts/test-skill-path-refs.sh,tests/scripts/test-check-skill-refs.sh,tests/skills/test_end_skill_final_verification_step.py,tests/skills/test_implementation_plan_skill_tdd_enforcement.py,tests/skills/test-quick-ref-skill.sh,tests/skills/test_project_setup_skill_conditional_prompts.py,tests/skills/test_fix_bug_skill.py,tests/skills/test_end_skill_summary_displays_stored_learnings.py,tests/skills/test_end_skill_learnings_step_before_commit.py,tests/skills/test-design-skills-cross-stack.sh,tests/skills/test_end_skill_dirty_worktree_resolution.py,tests/skills/test_fix_bug_skill_escalated_section.py,tests/skills/test_end_skill_bug_tickets_before_commit.py
7373
plugins/dso/skills/retro/SKILL.md:plugins/dso/tests/test-sprint-skill-step10-no-merge-to-main.sh,tests/plugin/test-audit-skill-resolution.sh,tests/hooks/test-fix-bug-skill.sh,tests/hooks/test-generate-claude-md-skill.sh,tests/hooks/test-init-skill.sh,tests/scripts/test-qualify-skill-refs.sh,tests/scripts/test-skill-path-refs.sh,tests/scripts/test-check-skill-refs.sh,tests/skills/test_end_skill_final_verification_step.py,tests/skills/test_implementation_plan_skill_tdd_enforcement.py,tests/skills/test-quick-ref-skill.sh,tests/skills/test_project_setup_skill_conditional_prompts.py,tests/skills/test_fix_bug_skill.py,tests/skills/test_end_skill_summary_displays_stored_learnings.py,tests/skills/test_end_skill_learnings_step_before_commit.py,tests/skills/test-design-skills-cross-stack.sh,tests/skills/test_end_skill_dirty_worktree_resolution.py,tests/skills/test_fix_bug_skill_escalated_section.py,tests/skills/test_end_skill_bug_tickets_before_commit.py
@@ -91,3 +91,5 @@ plugins/dso/scripts/ticket-bridge-status.sh:tests/scripts/test_bridge_status.py
9191
plugins/dso/scripts/ticket-show.sh:tests/scripts/test-ticket-show.sh,tests/scripts/test_bridge_alert_display.py
9292
plugins/dso/scripts/ticket-list.sh:tests/scripts/test-ticket-list.sh,tests/scripts/test_bridge_alert_display.py
9393
plugins/dso/scripts/ticket-lib.sh:tests/scripts/test_revert_event.py,tests/scripts/test-ticket-lib.sh
94+
plugins/dso/scripts/ci-generator.sh:tests/scripts/test-ci-generator.sh,tests/scripts/test-ci-generator-integration.sh
95+
plugins/dso/scripts/project-detect.sh:tests/scripts/test-ci-generator-integration.sh

.tickets/.index.json

Lines changed: 11 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,6 @@
8787
"title": "Display BRIDGE_ALERT health warning in ticket-show.sh and ticket-list.sh output",
8888
"type": "task"
8989
},
90-
"dso-2bmc": {
91-
"deps": [],
92-
"priority": 1,
93-
"status": "open",
94-
"title": "Add descriptive agent name guidance to /dso:debug-everything dispatch points",
95-
"type": "task"
96-
},
9790
"dso-2dxt": {
9891
"deps": [],
9992
"parent": "w22-ns6l",
@@ -189,22 +182,6 @@
189182
"title": "Conditional Security & Performance Review Overlays",
190183
"type": "epic"
191184
},
192-
"dso-5rya": {
193-
"deps": [],
194-
"priority": 1,
195-
"status": "open",
196-
"title": "Add descriptive agent name guidance to /dso:sprint dispatch points",
197-
"type": "task"
198-
},
199-
"dso-6026": {
200-
"deps": [
201-
"dso-917w"
202-
],
203-
"priority": 2,
204-
"status": "open",
205-
"title": "As a DSO practitioner, deprecated sub-agent templates have consistent anti-cover-up guidance",
206-
"type": "story"
207-
},
208185
"dso-60uy": {
209186
"deps": [
210187
"dso-ed01",
@@ -216,18 +193,11 @@
216193
"title": "Add REVERT to ticket-lib.sh allowed event_type enum and create ticket-revert.sh",
217194
"type": "task"
218195
},
219-
"dso-6r3o": {
220-
"deps": [],
221-
"priority": 1,
222-
"status": "closed",
223-
"title": "As a developer, the CI auto-ticket-creation pattern is fully removed",
224-
"type": "story"
225-
},
226196
"dso-6x8o": {
227197
"deps": [],
228198
"priority": 1,
229199
"status": "closed",
230-
"title": "Bug: record-test-status.sh allows re-recording with stale test results hash updated without re-running tests",
200+
"title": "Bug: record-test-status.sh allows re-recording with stale test results \u2014 hash updated without re-running tests",
231201
"type": "bug"
232202
},
233203
"dso-7n6c": {
@@ -265,13 +235,6 @@
265235
"title": "Extract review and evaluation sub-agents into dedicated plugin agents",
266236
"type": "epic"
267237
},
268-
"dso-917w": {
269-
"deps": [],
270-
"priority": 1,
271-
"status": "open",
272-
"title": "As a DSO practitioner, sub-agents receive comprehensive anti-cover-up guidance in active prompt templates",
273-
"type": "story"
274-
},
275238
"dso-94ya": {
276239
"deps": [],
277240
"priority": 2,
@@ -514,15 +477,6 @@
514477
"title": "Implement bridge-inbound.py: inbound Jira comment pull with dual-key dedup",
515478
"type": "task"
516479
},
517-
"dso-fqye": {
518-
"deps": [
519-
"dso-6r3o"
520-
],
521-
"priority": 2,
522-
"status": "closed",
523-
"title": "Update project docs to reflect CI ticket removal",
524-
"type": "story"
525-
},
526480
"dso-fucm": {
527481
"deps": [],
528482
"priority": 4,
@@ -668,13 +622,6 @@
668622
"title": "GREEN: Add abbreviated clarification loop to HOOK-INJECTION.md",
669623
"type": "task"
670624
},
671-
"dso-jjli": {
672-
"deps": [],
673-
"priority": 2,
674-
"status": "open",
675-
"title": "merge-to-main.sh 'merge' phase name misleads agents into thinking code is on main",
676-
"type": "bug"
677-
},
678625
"dso-khl2": {
679626
"deps": [],
680627
"priority": 2,
@@ -697,7 +644,7 @@
697644
],
698645
"priority": 2,
699646
"status": "open",
700-
"title": "Optimize /dso:sprint skill prune bloat, merge phases, remove Task tracking",
647+
"title": "Optimize /dso:sprint skill \u2014 prune bloat, merge phases, remove Task tracking",
701648
"type": "epic"
702649
},
703650
"dso-lm92": {
@@ -802,13 +749,6 @@
802749
"title": "Fix: add test for source-file-is-test-file edge case in fuzzy-match tests",
803750
"type": "bug"
804751
},
805-
"dso-pcgh": {
806-
"deps": [],
807-
"priority": 1,
808-
"status": "open",
809-
"title": "Sub-agents create tickets with type 'task' instead of 'bug' when tracking discovered bugs",
810-
"type": "bug"
811-
},
812752
"dso-psan": {
813753
"deps": [
814754
"w22-45i1",
@@ -823,14 +763,7 @@
823763
"deps": [],
824764
"priority": 1,
825765
"status": "closed",
826-
"title": "Bug: stat -f || stat -c fallback pattern broken on Linux — stat -f succeeds with wrong semantics",
827-
"type": "bug"
828-
},
829-
"dso-ptzz": {
830-
"deps": [],
831-
"priority": 2,
832-
"status": "open",
833-
"title": "sprint-next-batch.sh treats tk dep blockers as file conflicts, preventing non-overlapping tasks from batching",
766+
"title": "Bug: stat -f || stat -c fallback pattern broken on Linux \u2014 stat -f succeeds with wrong semantics",
834767
"type": "bug"
835768
},
836769
"dso-pwt7": {
@@ -840,7 +773,7 @@
840773
],
841774
"priority": 2,
842775
"status": "open",
843-
"title": "Integration test: full discover generate validate write workflow for new project",
776+
"title": "Integration test: full discover \u2192 generate \u2192 validate \u2192 write workflow for new project",
844777
"type": "task"
845778
},
846779
"dso-pxos": {
@@ -1138,7 +1071,7 @@
11381071
"deps": [],
11391072
"priority": 1,
11401073
"status": "closed",
1141-
"title": "test-batched.sh state file not isolated by repo/worktree causes cross-session interference",
1074+
"title": "test-batched.sh state file not isolated by repo/worktree \u2014 causes cross-session interference",
11421075
"type": "bug"
11431076
},
11441077
"w20-fxpu": {
@@ -1153,7 +1086,7 @@
11531086
"parent": "w22-ku13",
11541087
"priority": 3,
11551088
"status": "open",
1156-
"title": "generate-test-index.sh broader scan is O(n*m) extremely slow on repos with many files",
1089+
"title": "generate-test-index.sh broader scan is O(n*m) \u2014 extremely slow on repos with many files",
11571090
"type": "task"
11581091
},
11591092
"w20-keta": {
@@ -1167,7 +1100,7 @@
11671100
"deps": [],
11681101
"priority": 2,
11691102
"status": "open",
1170-
"title": "Multiple [LOCK] tickets for debug-everything no cleanup after session ends",
1103+
"title": "Multiple [LOCK] tickets for debug-everything \u2014 no cleanup after session ends",
11711104
"type": "bug"
11721105
},
11731106
"w20-w7pm": {
@@ -1208,7 +1141,7 @@
12081141
"deps": [],
12091142
"priority": 1,
12101143
"status": "open",
1211-
"title": "Ticket system v3 migration from tk and cutover",
1144+
"title": "Ticket system v3 \u2014 migration from tk and cutover",
12121145
"type": "epic"
12131146
},
12141147
"w21-25mq": {
@@ -1307,7 +1240,7 @@
13071240
],
13081241
"priority": 1,
13091242
"status": "closed",
1310-
"title": "Ticket system v3 dependency management, cross-worktree sync, and conflict resolution",
1243+
"title": "Ticket system v3 \u2014 dependency management, cross-worktree sync, and conflict resolution",
13111244
"type": "epic"
13121245
},
13131246
"w21-5mr1": {
@@ -1410,7 +1343,7 @@
14101343
],
14111344
"priority": 1,
14121345
"status": "closed",
1413-
"title": "Ticket system v3 Jira bridge and LLM-optimized output",
1346+
"title": "Ticket system v3 \u2014 Jira bridge and LLM-optimized output",
14141347
"type": "epic"
14151348
},
14161349
"w21-chse": {
@@ -1485,7 +1418,7 @@
14851418
"parent": "dso-9xnr",
14861419
"priority": 3,
14871420
"status": "open",
1488-
"title": "dso-setup.sh supplement_template_file uses cat for append not in _make_tool_path fake PATH",
1421+
"title": "dso-setup.sh supplement_template_file uses cat for append \u2014 not in _make_tool_path fake PATH",
14891422
"type": "bug"
14901423
},
14911424
"w21-epz2": {

.tickets/archive/dso-0ey5.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
---
2+
id: dso-0ey5
3+
status: closed
4+
deps: [dso-9mvn, dso-1dws]
5+
links: []
6+
created: 2026-03-22T15:44:28Z
7+
type: task
8+
priority: 2
9+
assignee: Joe Oakhart
10+
parent: w22-ond9
11+
---
12+
# Add YAML validation, command sanitization, and edge-case handling to ci-generator.sh
13+
14+
15+
## Description
16+
17+
Extend plugins/dso/scripts/ci-generator.sh with YAML validation, command sanitization, and edge-case robustness.
18+
19+
Implementation steps:
20+
1. Command sanitization: apply allowlist filter (alphanumeric, space, '-', '_', '/', '.', ':', '=') to suite command strings before embedding in YAML. Reject/strip anything else.
21+
2. YAML validation: after generating YAML to a temp path:
22+
a. If actionlint is on PATH: run actionlint <temp_file>; non-zero = exit 2, do not write
23+
b. Else: python3 -c "import yaml; yaml.safe_load(open('<temp_file>').read())" ; exception = exit 2
24+
c. On validation success: move temp file to final destination
25+
3. Edge cases:
26+
- Empty suite list: write no files, exit 0
27+
- Special characters in suite name: normalize to valid job ID (lowercase, replace non-alphanumeric with '-', collapse repeated '-')
28+
- All-unknown suites in --non-interactive: write all to ci-slow.yml
29+
4. Interactive speed_class prompting:
30+
- For each unknown suite: prompt "Is [name] a fast test (<30s) or slow test? [fast/slow/skip] (default: slow): "
31+
- On Enter with no input: treat as slow
32+
- 'skip': omit this suite from generated workflows
33+
34+
TDD REQUIREMENT: Depends on dso-9mvn RED tests. All tests added in dso-9mvn must pass GREEN after this task. Also depends on dso-1dws (base generator).
35+
36+
Security note: [Security] tag from story — suite commands come from user project config and could contain injection attempts. The allowlist sanitization prevents shell injection in generated YAML.
37+
38+
## ACCEPTANCE CRITERIA
39+
40+
- [ ] bash tests/run-all.sh passes (exit 0)
41+
Verify: cd $(git rev-parse --show-toplevel) && bash tests/run-all.sh
42+
- [ ] ruff check passes (exit 0)
43+
Verify: ruff check plugins/dso/scripts/*.py tests/**/*.py
44+
- [ ] ruff format --check passes (exit 0)
45+
Verify: ruff format --check plugins/dso/scripts/*.py tests/**/*.py
46+
- [ ] test_command_sanitization_strips_metacharacters passes
47+
Verify: cd $(git rev-parse --show-toplevel) && bash tests/scripts/test-ci-generator.sh 2>&1 | grep -q 'PASS.*test_command_sanitization'
48+
- [ ] test_yaml_validation_blocks_invalid_yaml passes
49+
Verify: cd $(git rev-parse --show-toplevel) && bash tests/scripts/test-ci-generator.sh 2>&1 | grep -q 'PASS.*test_yaml_validation_blocks_invalid_yaml'
50+
- [ ] test_temp_then_move_pattern passes
51+
Verify: cd $(git rev-parse --show-toplevel) && bash tests/scripts/test-ci-generator.sh 2>&1 | grep -q 'PASS.*test_temp_then_move'
52+
- [ ] All test-ci-generator.sh tests pass
53+
Verify: cd $(git rev-parse --show-toplevel) && bash tests/scripts/test-ci-generator.sh; test $? -eq 0
54+
55+
## Notes
56+
57+
**2026-03-22T17:04:53Z**
58+
59+
CHECKPOINT 1/6: Task context loaded ✓
60+
61+
**2026-03-22T17:05:26Z**
62+
63+
CHECKPOINT 2/6: Code patterns understood ✓
64+
65+
**2026-03-22T17:05:36Z**
66+
67+
CHECKPOINT 3/6: Tests written (RED tests pre-exist) ✓
68+
69+
**2026-03-22T17:06:50Z**
70+
71+
CHECKPOINT 4/6: Implementation complete ✓
72+
73+
**2026-03-22T17:07:00Z**
74+
75+
CHECKPOINT 5/6: Validation passed ✓
76+
77+
**2026-03-22T17:07:38Z**
78+
79+
CHECKPOINT 6/6: Done ✓ — Note: AC grep patterns use 'PASS.*test_name' but output format is 'test_name ... PASS'; underlying tests all pass (28 PASSED, 0 FAILED, exit 0)
80+
81+
**2026-03-22T17:09:56Z**
82+
83+
CHECKPOINT 6/6: Done ✓ — Files: plugins/dso/scripts/ci-generator.sh. Tests: 28 GREEN.

0 commit comments

Comments
 (0)