3 Commits

  • fix: address second round of code-review findings
    actions.js:
    - Add assertValidRepo/assertValidIssueNumber guards at the top of all
      action handlers (applyClaim, applySync, applyValidate, applyPublish,
      applyReview, applyDecompose, applyUnblock) for fast-fail validation
    - applyValidate: fix status transition — set 'validated' unconditionally
      when ok=true instead of preserving 'blocked' (was inconsistent with
      projectState becoming 'ready')
    
    gh-api.js:
    - runGh: preserve GITHUB_TOKEN by default; only delete when caller
      explicitly sets options.stripGithubToken=true (was deleting by
      default, breaking CI)
    
    parsing.js:
    - extractCoordinationState: throw SyntaxError on malformed JSON instead
      of silently returning null — lets callers distinguish bad JSON from
      absent marker
    - normalizeBodyForComparison: fix regex to match JSON-quoted form
      "lastSyncAt": ... instead of bare lastSyncAt: ...
    
    policy.js:
    - loadPolicy: validate that parsed JSON is a plain object before
      spreading; coerce nested fields (labels, review, validation,
      branchModel, project, fieldNames) to objects before merging
    
    state.js:
    - assertIssueClaimable: block re-claim on status alone (not status AND
      owner) to prevent {status:'claimed', owner:null} bypass; use
      state.owner || 'unknown' in error message
    - getCoordinationState: catch SyntaxError from extractCoordinationState,
      log warning to stderr, fall back to default state
    
    tests/lib:
    - Update malformed-JSON test to expect SyntaxError throw instead of null
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
  • refactor: apply code-review findings to github-native coordination
    scripts/github-coordination.js:
    - parseArgs: replace 13-entry if/else chain with BOOL_FLAGS/VALUE_FLAGS
      lookup maps; shrinks from 119 to ~45 lines
    - Extract dispatchCommand(options, ctx) and formatOutput(payload, options)
      from main(); main() shrinks to ~20 lines
    
    scripts/lib/github-coordination.js:
    - Split 1041-line monolith into 6 focused sub-modules under
      scripts/lib/github-coordination/ (policy, parsing, gh-api, state,
      actions, store); index becomes a thin re-export (~55 lines)
    - Document ECC_GH_SHIM trust boundary in runGh() (gh-api.js)
    - Document applyClaim() read→check→write race condition (actions.js)
    
    tests/lib/github-coordination.test.js:
    - Refactor runTests() to data-driven DESCRIPTORS array + runGroup()
      helper; runTests() shrinks to ~10 lines
    - Add 5 new edge-case tests: normalizeRepo('') and normalizeRepo('   ')
      throw, desiredLabelsForState for blocked/ready statuses, and
      buildIssueStateFromAction for validate action (15 → 20 tests)
    
    tests/scripts/github-coordination.test.js:
    - Replace console.log in test runner with process.stdout.write
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
  • feat: add github-native coordination (epic-* commands + scripts + tests)
    Adds a GitHub-native coordination layer on top of ECC:
    
    Commands (7 new slash commands):
    - epic-claim, epic-sync, epic-validate, epic-publish
    - epic-review, epic-unblock, epic-decompose
    
    Scripts:
    - scripts/github-coordination.js  — CLI entry point
    - scripts/lib/github-coordination.js  — core library (state machine, gh API wrappers)
    - scripts/status.js  — coordination status reporter
    
    Config:
    - config/github-native-coordination.json  — labels, review policy, validation gates
    
    Tests:
    - tests/lib/github-coordination.test.js  — 15 unit tests for pure functions
    - tests/scripts/github-coordination.test.js  — integration/CLI test suite
    
    Registry:
    - docs/COMMAND-REGISTRY.json  — adds 7 epic-* entries, totalCommands 84 → 91
    
    No encoding changes, no prp-* modifications, no Windows shims.
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>