Skip to content

feat: submodule support in IDD config — let parent config route submodule operations #162

Description

@kiki830621

Problem

Original suggestion (verbatim):
「我在想 idd 要能夠支持 submodule 的設定,可能最上層的 idd 設定可以用來調整 submodule 吧?」

When working inside a git submodule, IDD's walked-up config resolution (Step 0.5.B) finds the parent repo's .claude/issue-driven-dev.local.json and uses its github_repo field — which targets the parent repo, not the submodule. The submodule's own GitHub remote is silently ignored.

The user is asking for: the topmost (parent) IDD config could declare per-submodule routing, so a single parent config drives both parent-repo issues and submodule-repo issues without the user having to maintain a separate config file inside each submodule.

Type

feature / enhancement (config-protocol)

Concrete pain point (encountered 2026-05-26)

Setup:

  • Parent repo: PsychQuant/IRT_variacne_bootstrapping_estimtor (code + sims)
  • Submodule at manuscript/parametric_bootstrapping_se/ → remote kiki830621/PB-of-IRT-ability (manuscript)
  • Parent config: article2_standard_error/.claude/issue-driven-dev.local.json → "github_repo": "PsychQuant/IRT_variacne_bootstrapping_estimtor"

Sequence:

  1. cd manuscript/parametric_bootstrapping_se/05xx-2026/ (inside submodule)
  2. /idd-issue ... for a manuscript-content change
  3. Step 0.5.B walks up, hits parent config → GITHUB_REPO = PsychQuant/IRT_variacne_bootstrapping_estimtor (WRONG — should be kiki830621/PB-of-IRT-ability)
  4. The submodule's own git remote get-url origin (which would derive the correct target) is ignored because Step 0.5.B's walked-up config wins over derivation
  5. Workaround: manually create manuscript/parametric_bootstrapping_se/.claude/issue-driven-dev.local.json with "github_repo": "kiki830621/PB-of-IRT-ability"

Same friction applies to idd-diagnose / idd-implement / idd-verify / idd-close — every IDD skill walking-up from submodule cwd hits the wrong parent config.

Expected

A parent IDD config should be able to declare per-submodule routing in one of these forms (proposing two designs, not mutually exclusive):

Option A — Reuse existing candidates + path predicates (documentation pattern)

The candidates mechanism + path_contains predicate already handles this case; it's a discoverability gap, not a missing feature. Document the pattern explicitly:

{
  "github_repo": "PsychQuant/IRT_variacne_bootstrapping_estimtor",
  "candidates": [
    {
      "label": "Manuscript submodule",
      "github_repo": "kiki830621/PB-of-IRT-ability",
      "when": { "path_contains": "manuscript/parametric_bootstrapping_se" }
    }
  ]
}

Step 0.5.C predicate pre-resolve already picks the candidate when cwd matches the path. The friction is that users (incl. me today) don't know this pattern handles submodules — README and CLAUDE.md call candidates "monorepo sub-package" routing, not "submodule" routing. Fix could be docs-only.

Option B — Native submodule awareness (submodules field in config schema)

Add a first-class field that consumes the parent repo's .gitmodules and auto-routes:

{
  "github_repo": "PsychQuant/IRT_variacne_bootstrapping_estimtor",
  "submodules": {
    "manuscript/parametric_bootstrapping_se": {
      "github_repo": "kiki830621/PB-of-IRT-ability",
      "attachments_release": "attachments"
    }
  }
}

Or with auto-derive (parse .gitmodules, use submodule's git remote get-url origin):

{
  "github_repo": "PsychQuant/IRT_variacne_bootstrapping_estimtor",
  "submodules": "auto"
}

Resolution algorithm: Step 0.5 checks if cwd is inside a registered submodule path → use submodule's mapped github_repo; otherwise fall through to parent's github_repo. The submodule's .claude/ directory does NOT need its own config.

Actual (current behaviour)

The fallback chain in Step 0.5 (config-protocol six mechanisms):

  1. --target flag (per-invocation override) — works but heavyweight
  2. ask_each_time menu — only fires if config has candidates / groups
  3. Predicate pre-resolve — works if candidates are set up (user has to know)
  4. Cascading config (walk up) — finds parent config, uses parent's github_repo (silent wrong target)
  5. git remote fallback — never reached because step 4 already resolved
  6. Groups — orthogonal, doesn't help

Submodule users currently must either (a) pass --target ... every invocation, (b) set up candidates manually, or (c) duplicate config inside the submodule. None is discoverable from the failure mode (silent wrong-target).

Impact

  • Affects any user with git subtree/git submodule workflow (e.g. manuscript + code projects, Overleaf-synced manuscripts, multi-repo monorepos)
  • Particularly painful when the submodule's GitHub remote differs from parent's owner (cross-org submodules)
  • Silent failure mode: target goes to wrong repo, user only notices after issue is filed in wrong place

Proposed scope (please confirm)

  • Docs (Option A): README + CLAUDE.md section "Submodule support" showing candidates + path_contains pattern. Probably 1 commit, zero code changes.
  • Native (Option B): submodules field in config schema + Step 0.5 resolution algorithm update + tests + docs. Larger; depends on whether maintainer prefers extending schema vs steering users to candidates.
  • Fallback safety net: if Step 0.5.B's walked-up config exists but cwd is inside an UNregistered submodule (not in candidates, not in submodules), emit a warning citing the parent target + suggesting the candidates/submodules pattern — instead of silent wrong-target.

Related

  • config-protocol.md Step 0.5 six-mechanism resolution (this issue proposes extension to mechanism 4)
  • candidates + path_contains (existing, under-documented for submodule case)
  • Pain point context: today's session converted manuscript/parametric_bootstrapping_se/ from git subtree → git submodule (per parent repo CLAUDE.md update 2026-05-26). The mode switch surfaced this gap.

Current Status

Phase: closed
Last updated: 2026-07-06 by /idd-verify (via /idd-all batch drain)

Key Decisions

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions