claude-autopm 3.22.2 → 3.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -321,66 +321,84 @@ Creating task 002 (Database schema):
321
321
  ✓ Created
322
322
  ```
323
323
 
324
- ### 4. Task File Format with Frontmatter
324
+ ### 4. MANDATORY: Read Issue Template Before Creating Tasks
325
+
326
+ **CRITICAL**: Before creating ANY task, read the issue template:
327
+ ```
328
+ Read .claude/templates/issue.xml
329
+ Read .claude/rules/issue-structure.xml
330
+ ```
331
+
332
+ Every task file MUST include ALL required sections from `issue.xml`. Missing sections = auto-reject.
333
+
334
+ ### 5. Task File Format with Frontmatter
325
335
  For each task, create a file with this exact structure:
326
336
 
327
337
  ```markdown
328
338
  ---
329
339
  name: [Task Title]
330
340
  status: open
341
+ priority: [critical/high/medium/low]
342
+ effort: [S/M/L/XL]
331
343
  created: [Current ISO date/time]
332
344
  updated: [Current ISO date/time]
333
- assigned_agent: .claude/agents/{category}/{agent-name}.md # Specialized agent for this task
334
- agent_context: # Optional: Agent-specific configuration
345
+ assigned_agent: .claude/agents/{category}/{agent-name}.md
346
+ agent_context:
335
347
  framework: [framework_name]
336
348
  language: [language_name]
337
- approach: [implementation_approach]
338
349
  github: [Will be updated when synced to GitHub]
339
- depends_on: [] # List of task numbers this depends on, e.g., [001, 002]
340
- parallel: true # Can this run in parallel with other tasks?
341
- conflicts_with: [] # Tasks that modify same files, e.g., [003, 004]
350
+ depends_on: []
351
+ parallel: true
352
+ conflicts_with: []
342
353
  ---
343
354
 
344
355
  # Task: [Task Title]
345
356
 
346
- ## Description
347
- Clear, concise description of what needs to be done
348
-
349
- ## ⚠️ TDD Requirements
350
- **This project uses Test-Driven Development. You MUST:**
351
- 1. 🔴 RED: Write failing test first
352
- 2. 🟢 GREEN: Write minimal code to make test pass
353
- 3. 🔵 REFACTOR: Clean up code while keeping tests green
357
+ ## Goal
358
+ [One sentence: WHAT this task delivers and WHY it matters]
354
359
 
355
- See `.claude/rules/tdd.enforcement.md` for complete requirements.
360
+ ## Context
361
+ [WHY this task exists — what triggered it, what currently works/doesn't,
362
+ what must be in place first. Include specific file paths, URLs, services.]
356
363
 
357
364
  ## Acceptance Criteria
358
- - [ ] Specific criterion 1
359
- - [ ] Specific criterion 2
360
- - [ ] Specific criterion 3
365
+ - [ ] Specific, measurable criterion 1
366
+ - [ ] Specific, measurable criterion 2
367
+ - [ ] Specific, measurable criterion 3
361
368
 
362
- ## Technical Details
363
- - Implementation approach
364
- - Key considerations
365
- - Code locations/files affected
369
+ ## Affected Files
370
+ - `path/to/file.ts` — [what changes]
371
+ - `path/to/test.ts` — [new test file]
366
372
 
367
- ## Dependencies
368
- - [ ] Task/Issue dependencies
369
- - [ ] External dependencies
373
+ ## Related Issues
374
+ - depends on #NNN — [why]
375
+ - blocks #NNN [why]
376
+ - (or "None" if standalone)
370
377
 
371
- ## Effort Estimate
372
- - Size: XS/S/M/L/XL
373
- - Hours: estimated hours
374
- - Parallel: true/false (can run in parallel with other tasks)
378
+ ## Verification Steps
379
+ [Concrete commands to verify this task is done:]
380
+ - `npm test -- --filter=feature` → all pass
381
+ - `curl http://localhost:3000/api/endpoint` 200
382
+ - `kubectl get pods -n app` → Running
375
383
 
376
384
  ## Definition of Done
377
385
  - [ ] Tests written FIRST (RED phase)
378
386
  - [ ] Code implemented (GREEN phase)
379
387
  - [ ] Code refactored (REFACTOR phase)
380
388
  - [ ] All tests passing
381
- - [ ] Documentation updated
382
- - [ ] Code reviewed
383
- - [ ] Deployed to staging
389
+ - [ ] Verification steps confirmed
390
+ - [ ] PR approved and merged
391
+
392
+ ## ⚠️ TDD Requirements
393
+ 1. 🔴 RED: Write failing test first
394
+ 2. 🟢 GREEN: Write minimal code to make test pass
395
+ 3. 🔵 REFACTOR: Clean up code while keeping tests green
396
+
397
+ ## Technical Constraints
398
+ [Stack, patterns, prohibitions — optional but recommended]
399
+
400
+ ## Out of Scope
401
+ [What NOT to touch — prevents AI from "improving" neighbors]
384
402
  ```
385
403
 
386
404
  ### 3. Task Naming Convention
@@ -356,18 +356,50 @@ Parse the arguments to detect the mode:
356
356
  - [Internal systems or components]
357
357
  - [Third-party libraries or tools]
358
358
 
359
- ## Implementation Plan
360
- ### Phase 1: Foundation
361
- - [ ] [Initial tasks]
359
+ ## Architecture Design
360
+ ### Component Tree
361
+ [Map out the key new files/modules/components that will be created:]
362
+ ```
363
+ src/
364
+ ├── feature/
365
+ │ ├── Component.tsx
366
+ │ ├── hooks/useFeature.ts
367
+ │ └── utils/helpers.ts
368
+ ```
362
369
 
363
- ### Phase 2: Core Features
364
- - [ ] [Main development]
370
+ ### Data Flow
371
+ [How data moves through the system for this feature:]
372
+ - User action → API endpoint → Service → Database → Response
365
373
 
366
- ### Phase 3: Enhancement
367
- - [ ] [Additional features]
374
+ ### State Management
375
+ [New state needed — stores, context, caching strategy]
368
376
 
369
- ### Phase 4: Release
370
- - [ ] [Final testing and deployment]
377
+ ## Implementation Plan
378
+ ### Phase 1: Analyze (before writing code)
379
+ - [ ] Read existing codebase patterns
380
+ - [ ] Identify integration points
381
+ - [ ] Confirm architecture with stakeholder
382
+
383
+ ### Phase 2: Foundation
384
+ - [ ] Database migrations / models
385
+ - [ ] Core API endpoints (backend)
386
+ - [ ] Base component scaffolding (frontend)
387
+
388
+ ### Phase 3: Core Features
389
+ - [ ] [Main feature implementation]
390
+ - [ ] [Integration with existing systems]
391
+
392
+ ### Phase 4: Polish & Release
393
+ - [ ] [Testing — unit, integration, e2e]
394
+ - [ ] [Documentation]
395
+ - [ ] [Deployment]
396
+
397
+ ### Quick Win Path
398
+ [Minimum viable subset that works end-to-end in 1-3 days:]
399
+ - Day 1: [smallest vertical slice]
400
+ - Day 2: [connect to real data]
401
+ - Day 3: [basic UI showing results]
402
+ [This path gives a working demo before full implementation]
371
403
 
372
404
  ## Risks and Mitigation
373
405
  ### Technical Risks
@@ -6,13 +6,18 @@
6
6
 
7
7
  <template>
8
8
  <section name="goal" required="true">One sentence: WHAT and WHY</section>
9
- <section name="context" required="true">Architecture location, files, dependencies</section>
9
+ <section name="context" required="true">
10
+ WHY this issue exists — problem background, current state, dependencies, environment.
11
+ Must answer: what triggered this, what works/doesn't, what must exist first.
12
+ </section>
10
13
  <section name="acceptance-criteria" required="true">Measurable checkboxes, not prose</section>
11
- <section name="technical-constraints" required="false">Stack, patterns, prohibitions</section>
12
14
  <section name="affected-files" required="true">Exact file paths with change description</section>
15
+ <section name="related-issues" required="true">depends on / blocks / related to #NNN, or "None"</section>
16
+ <section name="verification" required="true">Concrete commands to verify (curl, kubectl, npm test, etc.)</section>
17
+ <section name="definition-of-done" required="true">Quality gate checkboxes — tests, deploy, PR merged</section>
18
+ <section name="constraints" required="false">Stack, patterns, prohibitions</section>
13
19
  <section name="out-of-scope" required="false">What NOT to touch</section>
14
20
  <section name="suggested-approach" required="false">Brief implementation strategy</section>
15
- <section name="definition-of-done" required="false">Quality gates (tests, lint, coverage)</section>
16
21
  </template>
17
22
 
18
23
  <title-convention>
@@ -40,8 +45,12 @@
40
45
  </key-principles>
41
46
 
42
47
  <violations enforcement="auto-reject">
48
+ <violation>Creating issues without Context section (why it exists, current state)</violation>
43
49
  <violation>Creating issues without Acceptance Criteria</violation>
44
50
  <violation>Creating issues without Affected Files section</violation>
51
+ <violation>Creating issues without Verification Steps</violation>
52
+ <violation>Creating issues without Definition of Done</violation>
45
53
  <violation>Vague goal without concrete deliverable</violation>
54
+ <violation>Missing Related Issues (must list links or "None")</violation>
46
55
  </violations>
47
56
  </rule>
@@ -400,7 +400,7 @@ function renderHTML() {
400
400
  border: 1px solid #30363d; border-radius: 8px; overflow: hidden;
401
401
  }
402
402
  .diagram-split .code-pane {
403
- flex: 1; display: flex; flex-direction: column; border-right: 1px solid #30363d; min-width: 0;
403
+ width: 30%; display: flex; flex-direction: column; min-width: 150px; flex-shrink: 0;
404
404
  }
405
405
  .diagram-split .code-pane .pane-header {
406
406
  background: #161b22; padding: 6px 12px; font-size: 11px; color: #8b949e;
@@ -411,8 +411,13 @@ function renderHTML() {
411
411
  font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace; font-size: 13px;
412
412
  line-height: 1.5; resize: none; outline: none; tab-size: 2;
413
413
  }
414
+ .diagram-split .split-handle {
415
+ width: 5px; cursor: col-resize; background: #30363d; flex-shrink: 0;
416
+ transition: background 0.15s;
417
+ }
418
+ .diagram-split .split-handle:hover, .diagram-split .split-handle.dragging { background: #58a6ff; }
414
419
  .diagram-split .preview-pane {
415
- flex: 1; display: flex; flex-direction: column; background: #161b22; min-width: 0;
420
+ flex: 1; display: flex; flex-direction: column; background: #161b22; min-width: 200px;
416
421
  }
417
422
  .diagram-split .preview-pane .pane-header {
418
423
  background: #161b22; padding: 6px 12px; font-size: 11px; color: #8b949e;
@@ -429,6 +434,23 @@ function renderHTML() {
429
434
  .panzoom-hint {
430
435
  position: absolute; bottom: 8px; right: 12px; color: #484f58; font-size: 10px; pointer-events: none; z-index: 1;
431
436
  }
437
+ /* Diagram card actions */
438
+ .diagram-grid-item .card-actions {
439
+ display: flex; gap: 6px; margin-top: 8px; border-top: 1px solid #21262d; padding-top: 8px;
440
+ }
441
+ .diagram-grid-item .card-actions button {
442
+ background: #21262d; color: #8b949e; border: 1px solid #30363d;
443
+ padding: 3px 10px; border-radius: 4px; cursor: pointer; font-size: 11px;
444
+ }
445
+ .diagram-grid-item .card-actions button:hover { background: #30363d; color: #c9d1d9; }
446
+ .diagram-grid-item .card-actions .btn-remove { color: #f85149; }
447
+ .diagram-grid-item .card-actions .btn-remove:hover { background: #3d1116; border-color: #f85149; }
448
+ /* Fullscreen editor */
449
+ .diagram-editor.fullscreen {
450
+ position: fixed; inset: 0; z-index: 998; background: #0d1117;
451
+ padding: 12px; display: flex; flex-direction: column;
452
+ }
453
+ .diagram-editor.fullscreen .diagram-split { min-height: 0; flex: 1; }
432
454
  </style>
433
455
  </head>
434
456
  <body>
@@ -562,7 +584,27 @@ function renderHTML() {
562
584
  <!-- Diagram list view -->
563
585
  <div id="diagram-list-view">
564
586
  <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;">
565
- <p class="desc" style="margin:0;">Click a diagram to view and edit. Create new: <code>/pm:diagram-new &lt;name&gt;</code></p>
587
+ <p class="desc" style="margin:0;">Project diagrams stored in <code>.claude/pm/diagrams/</code></p>
588
+ <button class="btn" onclick="showNewDiagramForm()">+ New Diagram</button>
589
+ </div>
590
+ <!-- New diagram form (hidden by default) -->
591
+ <div id="new-diagram-form" class="card" style="display:none;margin-bottom:16px;">
592
+ <div class="row">
593
+ <div><label>Name (slug)</label><input type="text" id="new-diagram-name" placeholder="e.g. frontend, backend, database"></div>
594
+ <div><label>Type</label><select id="new-diagram-type">
595
+ <option value="architecture">architecture</option>
596
+ <option value="modules">modules</option>
597
+ <option value="data-flow">data-flow</option>
598
+ <option value="dependencies">dependencies</option>
599
+ <option value="custom">custom</option>
600
+ </select></div>
601
+ </div>
602
+ <label>Description</label>
603
+ <input type="text" id="new-diagram-desc" placeholder="e.g. Frontend React component tree">
604
+ <div style="margin-top:12px;">
605
+ <button class="btn" onclick="createNewDiagram()">Create</button>
606
+ <button class="btn" style="background:#21262d;margin-left:6px;" onclick="hideNewDiagramForm()">Cancel</button>
607
+ </div>
566
608
  </div>
567
609
  <div id="diagram-grid" class="diagram-grid"></div>
568
610
  </div>
@@ -572,19 +614,20 @@ function renderHTML() {
572
614
  <div class="left">
573
615
  <button class="btn-back" onclick="closeDiagramEditor()">← Back</button>
574
616
  <strong id="editor-diagram-name" style="color:#c9d1d9;font-size:14px;"></strong>
575
- <span id="editor-diagram-meta" style="color:#8b949e;font-size:11px;"></span>
576
617
  <span id="editor-unsaved" style="color:#d29922;font-size:11px;display:none;">● unsaved</span>
577
618
  </div>
578
619
  <div class="right">
579
620
  <button onclick="downloadCurrentDiagram()">↓ .mmd</button>
621
+ <button onclick="toggleEditorFullscreen()">⤢ Fullscreen</button>
580
622
  <button class="btn-save" onclick="saveDiagram()">Save</button>
581
623
  </div>
582
624
  </div>
583
- <div class="diagram-split">
584
- <div class="code-pane">
625
+ <div class="diagram-split" id="diagram-split">
626
+ <div class="code-pane" id="code-pane">
585
627
  <div class="pane-header"><span>Mermaid Source</span></div>
586
628
  <textarea id="diagram-code" spellcheck="false"></textarea>
587
629
  </div>
630
+ <div class="split-handle" id="split-handle"></div>
588
631
  <div class="preview-pane">
589
632
  <div class="pane-header">
590
633
  <span>Preview</span>
@@ -654,16 +697,10 @@ function renderDiagramsTab() {
654
697
  fetch('/api/diagrams', { headers: { 'Authorization': 'Bearer ' + TOKEN } })
655
698
  .then(r => r.json())
656
699
  .then(data => {
657
- // Merge system-generated + project diagrams into one list
658
700
  allDiagrams = [];
659
- if (data.epicFlowHasData) {
660
- allDiagrams.push({ name: 'epic-flow', content: data.epicFlow, type: 'system', meta: 'PRD → Epic → Tasks' });
661
- }
662
- allDiagrams.push({ name: 'plugins', content: data.pluginGraph, type: 'system', meta: 'Plugin dependencies' });
663
- allDiagrams.push({ name: 'agents', content: data.agentTree, type: 'system', meta: 'Agent selection tree' });
664
701
  if (data.projectDiagrams) {
665
702
  data.projectDiagrams.forEach(d => {
666
- allDiagrams.push({ name: d.name, content: d.content, type: 'project', meta: d.type || 'custom' });
703
+ allDiagrams.push({ name: d.name, content: d.content, type: d.type || 'custom' });
667
704
  });
668
705
  }
669
706
  renderDiagramGrid();
@@ -675,49 +712,112 @@ function renderDiagramGrid() {
675
712
  const grid = document.getElementById('diagram-grid');
676
713
  grid.textContent = '';
677
714
  if (allDiagrams.length === 0) {
678
- grid.innerHTML = '<p class="desc">No diagrams yet. Run <code>/pm:diagram-new &lt;name&gt;</code> to create one.</p>';
715
+ const msg = document.createElement('p');
716
+ msg.className = 'desc';
717
+ msg.textContent = 'No diagrams yet. Click "+ New Diagram" or run /pm:diagram-new <name>.';
718
+ grid.appendChild(msg);
679
719
  return;
680
720
  }
681
721
  allDiagrams.forEach(d => {
682
722
  const item = document.createElement('div');
683
723
  item.className = 'diagram-grid-item';
684
- item.setAttribute('role', 'button');
685
724
  item.setAttribute('tabindex', '0');
686
- item.onclick = function() { openDiagramEditor(d.name); };
687
- item.onkeydown = function(e) { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); openDiagramEditor(d.name); } };
688
725
  const h4 = document.createElement('h4');
689
726
  h4.textContent = d.name;
690
727
  const meta = document.createElement('div');
691
728
  meta.className = 'diagram-meta';
692
- meta.textContent = d.type === 'system' ? '⚙ ' + d.meta : '📄 ' + d.meta;
729
+ meta.textContent = d.type;
693
730
  const preview = document.createElement('div');
694
731
  preview.className = 'diagram-preview';
695
732
  const pre = document.createElement('pre');
696
733
  pre.className = 'mermaid';
697
734
  pre.textContent = d.content;
698
735
  preview.appendChild(pre);
736
+ // Action buttons
737
+ const actions = document.createElement('div');
738
+ actions.className = 'card-actions';
739
+ const editBtn = document.createElement('button');
740
+ editBtn.textContent = 'Edit';
741
+ editBtn.onclick = function(e) { e.stopPropagation(); openDiagramEditor(d.name); };
742
+ const dlBtn = document.createElement('button');
743
+ dlBtn.textContent = '↓ .mmd';
744
+ dlBtn.onclick = function(e) { e.stopPropagation(); downloadDiagram(d.name, d.content); };
745
+ const rmBtn = document.createElement('button');
746
+ rmBtn.textContent = 'Remove';
747
+ rmBtn.className = 'btn-remove';
748
+ rmBtn.onclick = function(e) { e.stopPropagation(); removeDiagram(d.name); };
749
+ actions.appendChild(editBtn);
750
+ actions.appendChild(dlBtn);
751
+ actions.appendChild(rmBtn);
699
752
  item.appendChild(h4);
700
753
  item.appendChild(meta);
701
754
  item.appendChild(preview);
755
+ item.appendChild(actions);
756
+ // Click card body (not actions) opens editor
757
+ item.onclick = function(e) { if (!e.target.closest('.card-actions')) openDiagramEditor(d.name); };
758
+ item.onkeydown = function(e) {
759
+ if (e.target && e.target.closest('.card-actions')) return;
760
+ if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); openDiagramEditor(d.name); }
761
+ };
702
762
  grid.appendChild(item);
703
763
  });
704
- // Render mini previews
705
764
  if (typeof mermaid !== 'undefined' && mermaid.run) {
706
765
  mermaid.run({ nodes: grid.querySelectorAll('.mermaid') });
707
766
  }
708
767
  }
709
768
 
769
+ // New diagram form
770
+ function showNewDiagramForm() { document.getElementById('new-diagram-form').style.display = ''; }
771
+ function hideNewDiagramForm() { document.getElementById('new-diagram-form').style.display = 'none'; }
772
+
773
+ async function createNewDiagram() {
774
+ const name = document.getElementById('new-diagram-name').value.trim().replace(/[^a-zA-Z0-9_-]/g, '-');
775
+ if (!name) { toast('Name is required', false); return; }
776
+ if (allDiagrams.find(d => d.name === name)) { toast('Diagram "' + name + '" already exists', false); return; }
777
+ const type = document.getElementById('new-diagram-type').value;
778
+ const desc = document.getElementById('new-diagram-desc').value.trim();
779
+ const template = 'graph TD\\n A[' + esc(desc || name) + ']';
780
+ try {
781
+ await api('POST', '/api/diagrams/' + encodeURIComponent(name), { content: template, type: type, description: desc });
782
+ hideNewDiagramForm();
783
+ document.getElementById('new-diagram-name').value = '';
784
+ document.getElementById('new-diagram-desc').value = '';
785
+ diagramsLoaded = false;
786
+ renderDiagramsTab();
787
+ toast('Diagram "' + name + '" created', true);
788
+ } catch (e) { /* api() already shows toast */ }
789
+ }
790
+
791
+ async function removeDiagram(name) {
792
+ if (!confirm('Remove diagram "' + name + '"?')) return;
793
+ try {
794
+ await api('DELETE', '/api/diagrams/' + encodeURIComponent(name));
795
+ allDiagrams = allDiagrams.filter(d => d.name !== name);
796
+ renderDiagramGrid();
797
+ toast('Diagram removed', true);
798
+ } catch (e) { /* api() already shows toast */ }
799
+ }
800
+
801
+ function downloadDiagram(name, content) {
802
+ const safeName = name.replace(/[^a-zA-Z0-9_-]/g, '_') + '.mmd';
803
+ const blob = new Blob([content], { type: 'text/plain' });
804
+ const a = document.createElement('a');
805
+ const url = URL.createObjectURL(blob);
806
+ a.href = url; a.download = safeName; a.style.display = 'none';
807
+ document.body.appendChild(a);
808
+ try { a.click(); } finally { document.body.removeChild(a); setTimeout(function() { URL.revokeObjectURL(url); }, 100); }
809
+ }
810
+
710
811
  function openDiagramEditor(name) {
711
812
  const d = allDiagrams.find(x => x.name === name);
712
813
  if (!d) return;
713
814
  currentDiagramName = name;
714
815
  currentDiagramSaved = d.content;
715
816
  document.getElementById('editor-diagram-name').textContent = name;
716
- document.getElementById('editor-diagram-meta').textContent = d.type === 'system' ? '(system — read-only)' : '';
717
817
  document.getElementById('editor-unsaved').style.display = 'none';
718
818
  const codeEl = document.getElementById('diagram-code');
719
819
  codeEl.value = d.content;
720
- codeEl.readOnly = d.type === 'system';
820
+ codeEl.readOnly = false;
721
821
  document.getElementById('diagram-list-view').style.display = 'none';
722
822
  document.getElementById('diagram-editor-view').classList.add('active');
723
823
  renderPreview(d.content);
@@ -726,11 +826,19 @@ function openDiagramEditor(name) {
726
826
  function closeDiagramEditor() {
727
827
  clearTimeout(previewDebounce); previewDebounce = null;
728
828
  if (panzoomInstance) { panzoomInstance.dispose(); panzoomInstance = null; }
729
- document.getElementById('diagram-editor-view').classList.remove('active');
829
+ const editor = document.getElementById('diagram-editor-view');
830
+ editor.classList.remove('active', 'fullscreen');
730
831
  document.getElementById('diagram-list-view').style.display = '';
731
832
  currentDiagramName = null;
732
833
  }
733
834
 
835
+ function toggleEditorFullscreen() {
836
+ document.getElementById('diagram-editor-view').classList.toggle('fullscreen');
837
+ // Re-render preview to fit new size
838
+ if (panzoomInstance) { panzoomInstance.dispose(); panzoomInstance = null; }
839
+ setTimeout(function() { renderPreview(document.getElementById('diagram-code').value); }, 100);
840
+ }
841
+
734
842
  function renderPreview(source) {
735
843
  const container = document.getElementById('diagram-preview-render');
736
844
  container.textContent = '';
@@ -761,6 +869,35 @@ function resetPanZoom() {
761
869
  }
762
870
  }
763
871
 
872
+ // Resizable split handle
873
+ (function() {
874
+ const handle = document.getElementById('split-handle');
875
+ const codePane = document.getElementById('code-pane');
876
+ const split = document.getElementById('diagram-split');
877
+ if (!handle || !codePane || !split) return;
878
+ let dragging = false;
879
+ handle.addEventListener('mousedown', function(e) {
880
+ e.preventDefault();
881
+ dragging = true;
882
+ handle.classList.add('dragging');
883
+ document.body.style.cursor = 'col-resize';
884
+ document.body.style.userSelect = 'none';
885
+ });
886
+ document.addEventListener('mousemove', function(e) {
887
+ if (!dragging) return;
888
+ const rect = split.getBoundingClientRect();
889
+ const pct = Math.min(70, Math.max(10, ((e.clientX - rect.left) / rect.width) * 100));
890
+ codePane.style.width = pct + '%';
891
+ });
892
+ document.addEventListener('mouseup', function() {
893
+ if (!dragging) return;
894
+ dragging = false;
895
+ handle.classList.remove('dragging');
896
+ document.body.style.cursor = '';
897
+ document.body.style.userSelect = '';
898
+ });
899
+ })();
900
+
764
901
  // Live preview on code change
765
902
  document.addEventListener('DOMContentLoaded', function() {
766
903
  const codeEl = document.getElementById('diagram-code');
@@ -776,7 +913,6 @@ document.addEventListener('DOMContentLoaded', function() {
776
913
  async function saveDiagram() {
777
914
  if (!currentDiagramName) return;
778
915
  const d = allDiagrams.find(x => x.name === currentDiagramName);
779
- if (d && d.type === 'system') { toast('System diagrams are read-only', false); return; }
780
916
  const content = document.getElementById('diagram-code').value;
781
917
  try {
782
918
  await api('POST', '/api/diagrams/' + encodeURIComponent(currentDiagramName), { content: content });
@@ -787,7 +923,7 @@ async function saveDiagram() {
787
923
  diagramsLoaded = false;
788
924
  toast('Diagram saved', true);
789
925
  } catch (e) {
790
- toast('Save failed: ' + e.message, false);
926
+ /* api() already shows toast */
791
927
  }
792
928
  }
793
929
 
@@ -1273,6 +1409,8 @@ const server = http.createServer(async (req, res) => {
1273
1409
  let meta = {};
1274
1410
  try { meta = JSON.parse(fs.readFileSync(metaPath, 'utf8')); } catch {}
1275
1411
  meta.name = meta.name || name;
1412
+ if (typeof body.type === 'string') meta.type = body.type.slice(0, 50);
1413
+ if (typeof body.description === 'string') meta.description = body.description.slice(0, 500);
1276
1414
  meta.updated = new Date().toISOString().replace(/\\.\\d{3}Z$/, 'Z');
1277
1415
  if (!meta.created) meta.created = meta.updated;
1278
1416
  fs.writeFileSync(metaPath, JSON.stringify(meta, null, 2), 'utf8');
@@ -7,14 +7,42 @@
7
7
  <field name="assignee" type="string" default=""/>
8
8
  <field name="created" type="datetime" auto="true"/>
9
9
  <field name="updated" type="datetime" auto="true"/>
10
+ <field name="priority" type="enum" values="critical,high,medium,low" default="medium"/>
11
+ <field name="effort" type="enum" values="S,M,L,XL" default="M"/>
10
12
  <field name="started" type="datetime"/>
11
13
  <field name="completed" type="datetime"/>
12
14
  </frontmatter>
13
15
 
14
16
  <sections>
15
17
  <section name="goal" heading="Goal" required="true">One sentence: WHAT and WHY</section>
18
+ <section name="context" heading="Context" required="true">
19
+ Why this issue exists. Include:
20
+ - Problem background — what triggered this (bug report, user request, architectural gap)
21
+ - Current state — what works now, what doesn't, relevant infrastructure/config
22
+ - Dependencies — what must exist first (images, services, DNS, other issues)
23
+ - Access/environment — how to reproduce, where to verify (cluster, URL, CI)
24
+ </section>
16
25
  <section name="acceptance-criteria" heading="Acceptance Criteria" required="true">Measurable checkboxes</section>
17
26
  <section name="affected-files" heading="Affected Files" required="true">Exact file paths with change description</section>
27
+ <section name="related-issues" heading="Related Issues" required="true">
28
+ Links to blocking/blocked/related issues:
29
+ - depends on #NNN — must be done first
30
+ - blocks #NNN — this unblocks other work
31
+ - related to #NNN — shares context
32
+ - Write "None" if truly standalone
33
+ </section>
34
+ <section name="verification" heading="Verification Steps" required="true">
35
+ Concrete commands to verify the work is done. Examples:
36
+ - curl https://app.example.com → 200
37
+ - kubectl get pods -n app → Running
38
+ - npm test -- --filter=feature → pass
39
+ </section>
40
+ <section name="definition-of-done" heading="Definition of Done" required="true">
41
+ Checklist of quality gates that MUST pass before closing:
42
+ - [ ] Tests pass (unit, integration)
43
+ - [ ] Deployed to staging/verified
44
+ - [ ] PR approved and merged
45
+ </section>
18
46
  <section name="constraints" heading="Technical Constraints" required="false">Stack, patterns, prohibitions</section>
19
47
  <section name="out-of-scope" heading="Out of Scope" required="false">What NOT to touch</section>
20
48
  <section name="approach" heading="Suggested Approach" required="false">Brief implementation strategy</section>
@@ -22,6 +50,11 @@
22
50
 
23
51
  <validation>
24
52
  <rule>goal must be non-empty</rule>
53
+ <rule>context must be non-empty</rule>
54
+ <rule>acceptance-criteria must be non-empty</rule>
55
+ <rule>related-issues must be non-empty</rule>
56
+ <rule>verification must be non-empty</rule>
57
+ <rule>definition-of-done must be non-empty</rule>
25
58
  <rule>at least 1 acceptance criterion checkbox (- [ ])</rule>
26
59
  </validation>
27
60
  </template>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-autopm",
3
- "version": "3.22.2",
3
+ "version": "3.23.1",
4
4
  "description": "Autonomous Project Management Framework for Claude Code - Advanced AI-powered development automation",
5
5
  "main": "bin/autopm.js",
6
6
  "workspaces": [
@@ -844,6 +844,15 @@
844
844
  "description": "Provider-agnostic PM workflows"
845
845
  }
846
846
  },
847
+ "rules": [
848
+ {
849
+ "name": "issue-structure",
850
+ "file": "rules/issue-structure.xml",
851
+ "description": "Enforces standard issue structure with required sections",
852
+ "priority": "high",
853
+ "appliesTo": ["issue-create", "epic-decompose"]
854
+ }
855
+ ],
847
856
  "dependencies": [],
848
857
  "peerPlugins": [
849
858
  "@claudeautopm/plugin-core"
@@ -0,0 +1,56 @@
1
+ <rule id="issue-structure" priority="high" enforcement="required">
2
+ <description>
3
+ Every GitHub issue created by ClaudeAutoPM MUST follow the standard structure.
4
+ Issues without proper structure waste AI tokens and lead to scope creep.
5
+ </description>
6
+
7
+ <template>
8
+ <section name="goal" required="true">One sentence: WHAT and WHY</section>
9
+ <section name="context" required="true">
10
+ WHY this issue exists — problem background, current state, dependencies, environment.
11
+ Must answer: what triggered this, what works/doesn't, what must exist first.
12
+ </section>
13
+ <section name="acceptance-criteria" required="true">Measurable checkboxes, not prose</section>
14
+ <section name="affected-files" required="true">Exact file paths with change description</section>
15
+ <section name="related-issues" required="true">depends on / blocks / related to #NNN, or "None"</section>
16
+ <section name="verification" required="true">Concrete commands to verify (curl, kubectl, npm test, etc.)</section>
17
+ <section name="definition-of-done" required="true">Quality gate checkboxes — tests, deploy, PR merged</section>
18
+ <section name="constraints" required="false">Stack, patterns, prohibitions</section>
19
+ <section name="out-of-scope" required="false">What NOT to touch</section>
20
+ <section name="suggested-approach" required="false">Brief implementation strategy</section>
21
+ </template>
22
+
23
+ <title-convention>
24
+ <format>[type][scope] Imperative description</format>
25
+ <types>feat, fix, refactor, chore, test, docs, ci</types>
26
+ <examples>
27
+ <example>[feat][agent] Add retry logic to ResearcherAgent</example>
28
+ <example>[fix][api] Handle timeout in /ingest endpoint</example>
29
+ <example>[refactor][db] Extract VectorStore interface</example>
30
+ <example>[test][plugin] Add PluginManager install scenario tests</example>
31
+ </examples>
32
+ </title-convention>
33
+
34
+ <labels>
35
+ <label-group name="type">feature, bug, refactor, chore</label-group>
36
+ <label-group name="effort">S, M, L, XL</label-group>
37
+ <label-group name="ai-ready">true — issue is well-structured for AI execution</label-group>
38
+ </labels>
39
+
40
+ <key-principles>
41
+ <principle>Acceptance Criteria over narrative — AI understands checkboxes better than prose</principle>
42
+ <principle>Explicit scope always — say what NOT to touch or AI will "improve" neighbors</principle>
43
+ <principle>Name files, classes, functions — AI should not guess project structure</principle>
44
+ <principle>Link related issues — dependencies and blockers must be visible</principle>
45
+ </key-principles>
46
+
47
+ <violations enforcement="auto-reject">
48
+ <violation>Creating issues without Context section (why it exists, current state)</violation>
49
+ <violation>Creating issues without Acceptance Criteria</violation>
50
+ <violation>Creating issues without Affected Files section</violation>
51
+ <violation>Creating issues without Verification Steps</violation>
52
+ <violation>Creating issues without Definition of Done</violation>
53
+ <violation>Vague goal without concrete deliverable</violation>
54
+ <violation>Missing Related Issues (must list links or "None")</violation>
55
+ </violations>
56
+ </rule>