diff --git a/cmd/specsync/main.go b/cmd/specsync/main.go
index 6315e7e..4f12561 100644
--- a/cmd/specsync/main.go
+++ b/cmd/specsync/main.go
@@ -33,7 +33,7 @@ var knownSubcommands = map[string]bool{
"sync": true, "audit": true, "audit-tasks": true, "validate": true,
"spinoff": true, "pr-body": true, "verify": true,
"agent-help": true, "doctor": true, "idea": true, "ideas": true, "archive": true,
- "epic": true, "adopt": true,
+ "epic": true, "adopt": true, "topology": true,
}
// knownConfusions maps a word someone might reach for by habit (e.g. git's
@@ -94,7 +94,7 @@ func deprecatedSlugFlag(args []string) error {
func main() {
cmd, rest, err := resolveSubcommand(os.Args[1:])
if err != nil {
- fmt.Fprintf(os.Stderr, "specsync: %v\n\nRun with no subcommand (optionally with flags) to sync, or use one of: pull, adopt, link, scan, trace, release-plan, changelog, install-skill, changes, set-stage, set-priority, note, audit, audit-tasks, validate, spinoff, pr-body, verify, idea, ideas, archive, epic\n", err)
+ fmt.Fprintf(os.Stderr, "specsync: %v\n\nRun with no subcommand (optionally with flags) to sync, or use one of: pull, adopt, link, scan, trace, release-plan, changelog, install-skill, changes, set-stage, set-priority, note, audit, audit-tasks, validate, spinoff, pr-body, verify, idea, ideas, archive, epic, topology\n", err)
os.Exit(2)
}
@@ -151,6 +151,8 @@ func main() {
runArchive(rest)
case "epic":
runEpic(rest)
+ case "topology":
+ runTopology(rest)
default:
runSync(rest)
}
diff --git a/openspec/changes/restore-topology-dispatch/proposal.md b/openspec/changes/restore-topology-dispatch/proposal.md
new file mode 100644
index 0000000..44ea6e3
--- /dev/null
+++ b/openspec/changes/restore-topology-dispatch/proposal.md
@@ -0,0 +1,26 @@
+# Restore the topology command and fix stale "soon" badges on the site
+
+## Why
+PR #174 (store support) was rebased from a branch that predated two pieces of
+already-shipped work: the `topology` subcommand's dispatch wiring in
+`cmd/specsync/main.go`, and the "See who's already working what" feature card
+on specsync.se. The flat-diff reapplication silently dropped the `topology`
+case from `knownSubcommands` and the `main()` switch, so `specsync topology`
+now fails with "unknown subcommand" even though `runTopology` and all its
+tests are still present and working.
+
+Separately, while reviewing the site after that merge: three feature cards
+(design notes overflow #139, topology #168, adopt #160) still carry a "soon"
+badge even though all three shipped weeks ago.
+
+## What Changes
+- Restore `"topology": true` in `knownSubcommands`, the `case "topology":
+ runTopology(rest)` dispatch arm, and `topology` in the subcommand list
+ printed on an unknown-subcommand error.
+- Drop the stale `"status": "soon"` / `"issue"` fields from the three
+ already-shipped feature cards in `site/features.json`.
+
+## Impact
+- Affected code: `cmd/specsync/main.go`, `site/features.json`
+- No spec delta: restores previously-specified, previously-tested behavior
+ that regressed in a merge; doesn't change any contract.
diff --git a/openspec/changes/restore-topology-dispatch/tasks.md b/openspec/changes/restore-topology-dispatch/tasks.md
new file mode 100644
index 0000000..fa5feec
--- /dev/null
+++ b/openspec/changes/restore-topology-dispatch/tasks.md
@@ -0,0 +1,2 @@
+- [x] Restore topology to knownSubcommands and the dispatch switch
+- [x] Drop stale soon/issue fields from the three shipped feature cards
diff --git a/openspec/changes/trim-feature-card-sprawl/proposal.md b/openspec/changes/trim-feature-card-sprawl/proposal.md
new file mode 100644
index 0000000..54ec624
--- /dev/null
+++ b/openspec/changes/trim-feature-card-sprawl/proposal.md
@@ -0,0 +1,25 @@
+# Trim low-value feature cards from the landing page
+
+## Why
+site/features.json has grown to one card per shipped PR rather than curated
+visitor-facing messaging. Several entries describe internal implementation
+details or flag-behavior nuances that read as changelog entries rather than
+reasons to try the tool:
+
+- "Explicit repo resolution" and "Per-repository board" — resolution
+ precedence order (`-repo` flag → `gh repo set-default` → `origin`, etc.):
+ reference-doc material, and "Per-repository board" duplicated "Projects
+ board sync" right above it.
+- "No label noise by default" — a specific PR's behavior change (labels
+ opt-in via `-labels`), not a feature a new visitor evaluates on.
+
+## What Changes
+- Remove "Explicit repo resolution", "Per-repository board", and "No label
+ noise by default".
+- Retitle "Collapsed by default" → "A clean issue, not a wall of text" to
+ lead with the visible benefit instead of the implementation mechanism.
+- Already-shipped features keep full documentation in README.md; this only
+ trims the landing page's card list.
+
+## Impact
+- Affected: site/features.json only. No code or behavior change.
diff --git a/openspec/changes/trim-feature-card-sprawl/tasks.md b/openspec/changes/trim-feature-card-sprawl/tasks.md
new file mode 100644
index 0000000..4b00c4b
--- /dev/null
+++ b/openspec/changes/trim-feature-card-sprawl/tasks.md
@@ -0,0 +1 @@
+- [x] Remove the three low-value cards, retitle one for benefit-first framing
diff --git a/site/features.json b/site/features.json
index 2e03a9a..b7df384 100644
--- a/site/features.json
+++ b/site/features.json
@@ -9,9 +9,7 @@
"group": "plan",
"icon": "flow",
"title": "Design notes survive the worktree",
- "body": "A design.md renders as ## Design notes in the synced issue, so decisions made while planning aren't lost if the local worktree is force-removed. Oversized notes overflow to a linked issue comment instead of getting truncated.",
- "status": "soon",
- "issue": 139
+ "body": "A design.md renders as ## Design notes in the synced issue, so decisions made while planning aren't lost if the local worktree is force-removed. Oversized notes overflow to a linked issue comment instead of getting truncated."
},
{
"group": "plan",
@@ -23,9 +21,7 @@
"group": "plan",
"icon": "flow",
"title": "See who's already working what",
- "body": "specsync topology joins every change with its tracker issue, git branch, and worktree across coordinated stores — a read-only check before an agent starts, so it doesn't duplicate work already in flight.",
- "status": "soon",
- "issue": 168
+ "body": "specsync topology joins every change with its tracker issue, git branch, and worktree across coordinated stores — a read-only check before an agent starts, so it doesn't duplicate work already in flight."
},
{
"group": "plan",
@@ -49,9 +45,7 @@
"group": "collaborate",
"icon": "idempotent",
"title": "Adopt an existing issue",
- "body": "specsync adopt -issue 3691 -change my-change binds a change and an issue that already exist independently, writing the ref cache before touching the issue body so the link holds immediately instead of racing search indexing.",
- "status": "soon",
- "issue": 160
+ "body": "specsync adopt -issue 3691 -change my-change binds a change and an issue that already exist independently, writing the ref cache before touching the issue body so the link holds immediately instead of racing search indexing."
},
{
"group": "collaborate",
@@ -89,18 +83,6 @@
"title": "Archive audit",
"body": "specsync audit cross-references archived changes against GitHub PRs to find archived-but-unmerged work. Add -mark-shipped to record the final lifecycle step."
},
- {
- "group": "collaborate",
- "icon": "idempotent",
- "title": "Explicit repo resolution",
- "body": "specsync resolves the target repository deterministically: -repo flag → gh repo set-default → origin. Fork-parent writes are refused by default; use -repo to override."
- },
- {
- "group": "collaborate",
- "icon": "board",
- "title": "Per-repository board",
- "body": "Board resolution per-repository: -project flag → openspec/specsync.yml → no board. No global default; each repo syncs only to its own declared board."
- },
{
"group": "collaborate",
"icon": "idempotent",
@@ -134,13 +116,7 @@
{
"group": "collaborate",
"icon": "state",
- "title": "Collapsed by default",
+ "title": "A clean issue, not a wall of text",
"body": "A synced issue shows title and task checklist first — Proposal, Original ask, and Discoveries render inside collapsed <details> blocks, one click away, nothing removed."
- },
- {
- "group": "collaborate",
- "icon": "idempotent",
- "title": "No label noise by default",
- "body": "specsync and stage:<stage> labels are opt-in via -labels — neither is read back by specsync itself, so they aren't added unless you actually want native-label filtering."
}
]