@opengsd/gsd-core 1.7.0-rc.3 → 1.7.0-rc.5
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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.opencode/plugins/gsd-core.js +20 -0
- package/README.ja-JP.md +4 -3
- package/README.ko-KR.md +4 -3
- package/README.md +4 -3
- package/README.pt-BR.md +4 -3
- package/README.zh-CN.md +4 -3
- package/agents/gsd-doc-classifier.md +105 -0
- package/agents/gsd-doc-synthesizer.md +61 -0
- package/agents/gsd-ui-checker.md +28 -0
- package/bin/install.js +652 -466
- package/commands/gsd/map-codebase.md +4 -4
- package/commands/gsd/ns-project.md +2 -1
- package/commands/gsd/onboard.md +46 -0
- package/gsd-core/bin/gsd-tools.cjs +87 -3
- package/gsd-core/bin/lib/api-coverage.cjs +466 -0
- package/gsd-core/bin/lib/audit.cjs +6 -3
- package/gsd-core/bin/lib/capability-loader.cjs +11 -9
- package/gsd-core/bin/lib/capability-registry.cjs +741 -62
- package/gsd-core/bin/lib/capability-state.cjs +117 -18
- package/gsd-core/bin/lib/capability-validator.cjs +1 -1
- package/gsd-core/bin/lib/capability-writer.cjs +21 -2
- package/gsd-core/bin/lib/check-command-router.cjs +242 -3
- package/gsd-core/bin/lib/claude-orchestration-command-router.cjs +136 -0
- package/gsd-core/bin/lib/claude-orchestration.cjs +404 -0
- package/gsd-core/bin/lib/clusters.cjs +1 -0
- package/gsd-core/bin/lib/command-aliases.cjs +8 -0
- package/gsd-core/bin/lib/commands.cjs +7 -5
- package/gsd-core/bin/lib/config-loader.cjs +1 -0
- package/gsd-core/bin/lib/config.cjs +96 -0
- package/gsd-core/bin/lib/core-utils.cjs +4 -1
- package/gsd-core/bin/lib/host-integration-adapters/cline-sdk-binding.cjs +234 -0
- package/gsd-core/bin/lib/host-integration-adapters/imperative-hook-bus.cjs +145 -0
- package/gsd-core/bin/lib/host-integration.cjs +16 -0
- package/gsd-core/bin/lib/init-command-router.cjs +4 -0
- package/gsd-core/bin/lib/init.cjs +99 -99
- package/gsd-core/bin/lib/install-effort-resolver.cjs +213 -0
- package/gsd-core/bin/lib/install-engine.cjs +159 -16
- package/gsd-core/bin/lib/install-profiles.cjs +2 -0
- package/gsd-core/bin/lib/installer-migration-report.cjs +4 -0
- package/gsd-core/bin/lib/loop-resolver.cjs +75 -18
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +50 -11
- package/gsd-core/bin/lib/milestone.cjs +3 -3
- package/gsd-core/bin/lib/model-resolver.cjs +69 -4
- package/gsd-core/bin/lib/normalize-test-command.cjs +187 -0
- package/gsd-core/bin/lib/onboard-projection.cjs +309 -0
- package/gsd-core/bin/lib/phase-id.cjs +132 -3
- package/gsd-core/bin/lib/phase.cjs +78 -16
- package/gsd-core/bin/lib/planning-workspace.cjs +17 -0
- package/gsd-core/bin/lib/roadmap-command-router.cjs +5 -4
- package/gsd-core/bin/lib/roadmap-parser.cjs +21 -30
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +9 -9
- package/gsd-core/bin/lib/roadmap.cjs +42 -56
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +13 -6
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +2 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +17 -10
- package/gsd-core/bin/lib/runtime-homes.cjs +8 -0
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +33 -25
- package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
- package/gsd-core/bin/lib/spec-section.cjs +111 -0
- package/gsd-core/bin/lib/state-transition.cjs +1 -1
- package/gsd-core/bin/lib/state.cjs +24 -24
- package/gsd-core/bin/lib/surface.cjs +81 -30
- package/gsd-core/bin/lib/uat.cjs +4 -1
- package/gsd-core/bin/lib/validate.cjs +15 -6
- package/gsd-core/bin/lib/verify.cjs +33 -37
- package/gsd-core/bin/shared/config-schema.manifest.json +2 -0
- package/gsd-core/bin/shared/model-catalog.json +11 -6
- package/gsd-core/references/api-coverage.md +104 -0
- package/gsd-core/references/gsd-run-resolver.md +8 -0
- package/gsd-core/references/model-profiles.md +2 -2
- package/gsd-core/references/planning-config.md +2 -0
- package/gsd-core/references/specless-probe-fallback.md +172 -0
- package/gsd-core/templates/config.json +2 -1
- package/gsd-core/templates/project.md +1 -1
- package/gsd-core/workflows/audit-fix.md +9 -1
- package/gsd-core/workflows/code-review-fix.md +7 -3
- package/gsd-core/workflows/code-review.md +4 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +4 -1
- package/gsd-core/workflows/do.md +4 -3
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +8 -4
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +42 -0
- package/gsd-core/workflows/execute-phase.md +1 -25
- package/gsd-core/workflows/help/modes/brief.md +2 -1
- package/gsd-core/workflows/help/modes/default.md +2 -1
- package/gsd-core/workflows/help/modes/full.md +11 -1
- package/gsd-core/workflows/help/modes/topic.md +1 -1
- package/gsd-core/workflows/onboard.md +277 -0
- package/gsd-core/workflows/plan-phase.md +31 -2
- package/gsd-core/workflows/quick.md +22 -2
- package/gsd-core/workflows/review.md +59 -13
- package/gsd-core/workflows/settings-advanced.md +5 -5
- package/gsd-core/workflows/settings.md +2 -2
- package/gsd-core/workflows/verify-phase.md +3 -2
- package/gsd-core/workflows/verify-work.md +38 -0
- package/hooks/dist/gsd-cursor-pre-tool.js +76 -0
- package/hooks/dist/gsd-cursor-stop.js +48 -0
- package/hooks/dist/gsd-cursor-subagent-start.js +50 -0
- package/hooks/dist/gsd-cursor-subagent-stop.js +40 -0
- package/hooks/dist/managed-hooks-registry.cjs +4 -0
- package/hooks/gsd-cursor-pre-tool.js +76 -0
- package/hooks/gsd-cursor-stop.js +48 -0
- package/hooks/gsd-cursor-subagent-start.js +50 -0
- package/hooks/gsd-cursor-subagent-stop.js +40 -0
- package/hooks/managed-hooks-registry.cjs +4 -0
- package/package.json +2 -1
- package/scripts/build-hooks.js +5 -1
- package/scripts/gen-golden-install-parity-zcode.cjs +77 -0
- package/scripts/lint-phase-id-drift.cjs +150 -0
- package/scripts/run-tests.cjs +26 -4
- package/scripts/sync-runtime-launcher.cjs +20 -2
- package/skills/gsd-map-codebase/SKILL.md +3 -3
- package/skills/gsd-ns-project/SKILL.md +1 -0
- package/skills/gsd-onboard/SKILL.md +46 -0
|
@@ -9,7 +9,7 @@ allowed-tools:
|
|
|
9
9
|
- Grep
|
|
10
10
|
- Write
|
|
11
11
|
- Agent
|
|
12
|
-
requires: [config, new-project, plan-phase]
|
|
12
|
+
requires: [config, new-project, plan-phase, onboard]
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
<objective>
|
|
@@ -42,7 +42,7 @@ Parse the first token of $ARGUMENTS:
|
|
|
42
42
|
Check for .planning/STATE.md - loads context if project already initialized
|
|
43
43
|
|
|
44
44
|
**This command can run:**
|
|
45
|
-
-
|
|
45
|
+
- Via /gsd:onboard for first-time brownfield setup - creates codebase map first
|
|
46
46
|
- After /gsd:new-project (greenfield codebases) - updates codebase map as code evolves
|
|
47
47
|
- Anytime to refresh codebase understanding
|
|
48
48
|
</context>
|
|
@@ -51,7 +51,7 @@ Check for .planning/STATE.md - loads context if project already initialized
|
|
|
51
51
|
**Use map-codebase for:**
|
|
52
52
|
- Brownfield projects before initialization (understand existing code first)
|
|
53
53
|
- Refreshing codebase map after significant changes
|
|
54
|
-
-
|
|
54
|
+
- Refreshing or deepening an onboarded codebase map
|
|
55
55
|
- Before major refactoring (understand current state)
|
|
56
56
|
- When STATE.md references outdated codebase info
|
|
57
57
|
|
|
@@ -71,7 +71,7 @@ Check for .planning/STATE.md - loads context if project already initialized
|
|
|
71
71
|
4. Wait for agents to complete, collect confirmations (NOT document contents)
|
|
72
72
|
5. Verify all 7 documents exist with line counts
|
|
73
73
|
6. Commit codebase map
|
|
74
|
-
7. Offer next steps (typically: /gsd:new-project or /gsd:plan-phase)
|
|
74
|
+
7. Offer next steps (typically: /gsd:onboard, /gsd:new-project, or /gsd:plan-phase)
|
|
75
75
|
</process>
|
|
76
76
|
|
|
77
77
|
<success_criteria>
|
|
@@ -5,7 +5,7 @@ argument-hint: ""
|
|
|
5
5
|
allowed-tools:
|
|
6
6
|
- Read
|
|
7
7
|
- Skill
|
|
8
|
-
requires: [new-project, new-milestone, complete-milestone, audit-milestone, milestone-summary, import, ingest-docs, profile-user, review-backlog]
|
|
8
|
+
requires: [new-project, onboard, new-milestone, complete-milestone, audit-milestone, milestone-summary, import, ingest-docs, profile-user, review-backlog]
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
Route to the appropriate project / milestone skill based on the user's intent.
|
|
@@ -15,6 +15,7 @@ inline as part of `gsd-audit-milestone`'s output.
|
|
|
15
15
|
| User wants | Invoke |
|
|
16
16
|
|---|---|
|
|
17
17
|
| Start a new project | gsd-new-project |
|
|
18
|
+
| Onboard an existing codebase | gsd-onboard |
|
|
18
19
|
| Create a new milestone | gsd-new-milestone |
|
|
19
20
|
| Complete the current milestone | gsd-complete-milestone |
|
|
20
21
|
| Audit a milestone for issues | gsd-audit-milestone |
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gsd:onboard
|
|
3
|
+
description: Guide existing codebase onboarding through mapping, doc ingest, and planning setup
|
|
4
|
+
argument-hint: "[--fast] [--text]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Bash
|
|
8
|
+
- Write
|
|
9
|
+
- Glob
|
|
10
|
+
- Grep
|
|
11
|
+
- Agent
|
|
12
|
+
- AskUserQuestion
|
|
13
|
+
requires: [config, new-project, map-codebase, ingest-docs, manager]
|
|
14
|
+
---
|
|
15
|
+
<runtime_note>
|
|
16
|
+
**Copilot (VS Code):** Use `vscode_askquestions` wherever this workflow calls `AskUserQuestion`. They are equivalent — `vscode_askquestions` is the VS Code Copilot implementation of the same interactive question API.
|
|
17
|
+
</runtime_note>
|
|
18
|
+
|
|
19
|
+
<objective>
|
|
20
|
+
Guide brownfield onboarding for an existing codebase by routing through the existing GSD primitives in the safe order: codebase map → docs ingest → project initialization → onboarding summary.
|
|
21
|
+
|
|
22
|
+
**Creates or confirms:**
|
|
23
|
+
- `.planning/codebase/` — evidence-backed codebase map from `/gsd:map-codebase`
|
|
24
|
+
- `.planning/PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, `STATE.md` — project setup from `/gsd:new-project` or `/gsd:ingest-docs`
|
|
25
|
+
- `.planning/onboarding/SUMMARY.md` — lightweight index of what was learned and the next command
|
|
26
|
+
|
|
27
|
+
**Non-goals:** This command does not execute phases, ship work, or overwrite existing planning artifacts without an explicit gate.
|
|
28
|
+
</objective>
|
|
29
|
+
|
|
30
|
+
<execution_context>
|
|
31
|
+
@~/.claude/gsd-core/workflows/onboard.md
|
|
32
|
+
@~/.claude/gsd-core/references/ui-brand.md
|
|
33
|
+
@~/.claude/gsd-core/references/gate-prompts.md
|
|
34
|
+
</execution_context>
|
|
35
|
+
|
|
36
|
+
<context>
|
|
37
|
+
Arguments: $ARGUMENTS
|
|
38
|
+
|
|
39
|
+
Flags:
|
|
40
|
+
- `--fast` — prefer `/gsd:map-codebase --fast` for the mapping handoff; the complete map is still required before `/gsd:new-project`.
|
|
41
|
+
- `--text` — use plain-text numbered lists instead of TUI menus.
|
|
42
|
+
</context>
|
|
43
|
+
|
|
44
|
+
<process>
|
|
45
|
+
Execute the onboard workflow end-to-end. Preserve all safety gates, text-mode fallbacks, idempotency checks, and top-level handoff rules for nested interactive commands.
|
|
46
|
+
</process>
|
|
@@ -179,14 +179,23 @@
|
|
|
179
179
|
*
|
|
180
180
|
* Loop Extension Point Queries (ADR-857 phase 3c):
|
|
181
181
|
* loop render-hooks <point> Resolve + render active Capability hooks at a loop point
|
|
182
|
+
* [--config-dir <path>] [--runtime <r>] [--active-cap <capId>]
|
|
182
183
|
* Returns JSON envelope { point, activeHooks, rendered }
|
|
183
184
|
* Valid points: discuss:pre/post, plan:pre/post,
|
|
184
185
|
* execute:pre/wave:pre/wave:post/post, verify:pre/post, ship:pre/post
|
|
186
|
+
* --runtime: override the auto-detected runtime (#2003) so the config
|
|
187
|
+
* dir resolves to that runtime's home even when
|
|
188
|
+
* .planning/config.json persists a different runtime.
|
|
185
189
|
*
|
|
186
190
|
* Capability State (ADR-857 phase 4b):
|
|
187
|
-
* capability state [--config-dir <path>] Resolve per-capability install/surface/hook-activation state
|
|
191
|
+
* capability state [--config-dir <path>] [--runtime <r>] Resolve per-capability install/surface/hook-activation state
|
|
188
192
|
* Returns JSON envelope { runtimeConfigDir, capabilities[] }
|
|
189
193
|
* --config-dir: runtime config dir (default: auto-detect current runtime)
|
|
194
|
+
* --runtime: override the auto-detected runtime (#2003); bypasses the
|
|
195
|
+
* GSD_RUNTIME → config.runtime → 'claude' precedence so a
|
|
196
|
+
* repo with a persisted runtime can still resolve another
|
|
197
|
+
* runtime's config dir (e.g. driving Claude Code from a
|
|
198
|
+
* repo that persists runtime:"codex").
|
|
190
199
|
*
|
|
191
200
|
* GSD-2 Migration:
|
|
192
201
|
* from-gsd2 [--path <dir>] [--force] [--dry-run]
|
|
@@ -679,7 +688,7 @@ async function main() {
|
|
|
679
688
|
// phase / roadmap / milestone / progress / etc.
|
|
680
689
|
const TOP_LEVEL_USAGE = 'Usage: gsd-tools <command> [args] [--raw] [--pick <field>] [--cwd <path>] [--ws <name>] [--json-errors]\n' +
|
|
681
690
|
'Commands: agent, agent-skills, assumption-delta, audit-open, audit-uat, check, check-commit, commit, commit-to-subrepo, pr-subrepo, ' +
|
|
682
|
-
'config-ensure-section, config-get, config-new-project, config-path, config-set, migrate-config, ' +
|
|
691
|
+
'config-ensure-section, config-get, config-new-project, config-path, config-set, migrate-config, normalize-test-command, ' +
|
|
683
692
|
'current-timestamp, detect-custom-files, docs-init, drift-guard, effort, extract-messages, find-phase, ' +
|
|
684
693
|
'from-gsd2, frontmatter, gap-analysis, generate-claude-md, generate-claude-profile, ' +
|
|
685
694
|
'generate-dev-preferences, generate-slug, graphify, history-digest, init, intel, ' +
|
|
@@ -1282,6 +1291,16 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
|
|
|
1282
1291
|
break;
|
|
1283
1292
|
}
|
|
1284
1293
|
|
|
1294
|
+
case 'normalize-test-command': {
|
|
1295
|
+
// #1857: rewrite a resolved test command to a one-shot form so a
|
|
1296
|
+
// watch-mode runner (vitest/jest) cannot hang a verification gate. Shared
|
|
1297
|
+
// by the regression gate and the post-merge gate. args[1] is the raw
|
|
1298
|
+
// resolved command; --cwd (already parsed into `cwd`) locates package.json.
|
|
1299
|
+
const testCommandNormalizer = require('./lib/normalize-test-command.cjs');
|
|
1300
|
+
testCommandNormalizer.cmdNormalizeTestCommand(cwd, args[1]);
|
|
1301
|
+
break;
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1285
1304
|
case 'dispatch-should-flatten': {
|
|
1286
1305
|
// #1708 / #853: typed query replacing the `RUNTIME === 'codex'` prose rule.
|
|
1287
1306
|
//
|
|
@@ -1598,9 +1617,28 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
|
|
|
1598
1617
|
}
|
|
1599
1618
|
loopActiveCap = value;
|
|
1600
1619
|
}
|
|
1620
|
+
// --runtime <r> (#2003): explicit runtime override so the config-dir
|
|
1621
|
+
// resolution bypasses the persisted-runtime fallback (GSD_RUNTIME →
|
|
1622
|
+
// config.runtime). Mirrors the --config-dir dual-form (--runtime X /
|
|
1623
|
+
// --runtime=X) and the capability-set --runtime precedent.
|
|
1624
|
+
let loopRuntime = undefined;
|
|
1625
|
+
const runtimeEqArg = args.find(arg => arg.startsWith('--runtime='));
|
|
1626
|
+
const runtimeIdx = args.indexOf('--runtime');
|
|
1627
|
+
if (runtimeEqArg) {
|
|
1628
|
+
const value = runtimeEqArg.slice('--runtime='.length).trim();
|
|
1629
|
+
if (!value) error('Missing value for --runtime', ERROR_REASON ? ERROR_REASON.USAGE : undefined);
|
|
1630
|
+
loopRuntime = value;
|
|
1631
|
+
} else if (runtimeIdx !== -1) {
|
|
1632
|
+
const value = args[runtimeIdx + 1];
|
|
1633
|
+
if (!value || value.startsWith('--')) {
|
|
1634
|
+
error('Missing value for --runtime', ERROR_REASON ? ERROR_REASON.USAGE : undefined);
|
|
1635
|
+
}
|
|
1636
|
+
loopRuntime = value;
|
|
1637
|
+
}
|
|
1601
1638
|
loopResolver.cmdLoopRenderHooks(cwd, args[2], raw, {
|
|
1602
1639
|
configDir: loopConfigDir ? path.resolve(loopConfigDir) : undefined,
|
|
1603
1640
|
activeCap: loopActiveCap,
|
|
1641
|
+
runtime: loopRuntime,
|
|
1604
1642
|
});
|
|
1605
1643
|
} else {
|
|
1606
1644
|
error(
|
|
@@ -1752,7 +1790,24 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
|
|
|
1752
1790
|
configDir = configDirVal;
|
|
1753
1791
|
}
|
|
1754
1792
|
const resolvedConfigDir = configDir ? path.resolve(configDir) : null;
|
|
1755
|
-
|
|
1793
|
+
// --runtime <r> (#2003): explicit runtime override so the config-dir
|
|
1794
|
+
// resolution bypasses the persisted-runtime fallback. Dual-form like
|
|
1795
|
+
// --config-dir (--runtime X / --runtime=X).
|
|
1796
|
+
let stateRuntime = undefined;
|
|
1797
|
+
const stateRuntimeEqArg = args.find(arg => arg.startsWith('--runtime='));
|
|
1798
|
+
const stateRuntimeIdx = args.indexOf('--runtime');
|
|
1799
|
+
if (stateRuntimeEqArg) {
|
|
1800
|
+
const value = stateRuntimeEqArg.slice('--runtime='.length).trim();
|
|
1801
|
+
if (!value) error('Missing value for --runtime', ERROR_REASON ? ERROR_REASON.USAGE : undefined);
|
|
1802
|
+
stateRuntime = value;
|
|
1803
|
+
} else if (stateRuntimeIdx !== -1) {
|
|
1804
|
+
const value = args[stateRuntimeIdx + 1];
|
|
1805
|
+
if (!value || value.startsWith('--')) {
|
|
1806
|
+
error('Missing value for --runtime', ERROR_REASON ? ERROR_REASON.USAGE : undefined);
|
|
1807
|
+
}
|
|
1808
|
+
stateRuntime = value;
|
|
1809
|
+
}
|
|
1810
|
+
capabilityState.cmdCapabilityState(cwd, resolvedConfigDir, raw, { runtime: stateRuntime });
|
|
1756
1811
|
} else if (capSubcommand === 'set') {
|
|
1757
1812
|
// capability set <id> [--on|--off|--enable|--disable] [--gate <key>=<bool>]... [--config-dir <dir>] [--runtime <r>] [--scope <s>]
|
|
1758
1813
|
const capId = args[2];
|
|
@@ -2095,6 +2150,28 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
|
|
|
2095
2150
|
}
|
|
2096
2151
|
}
|
|
2097
2152
|
} catch { /* best-effort — list still works without the inactive annotation */ }
|
|
2153
|
+
// Issue #2045 (DEFECT 3): derive each capability's SURFACED state from the
|
|
2154
|
+
// SAME resolver `capability state` uses (resolveCapabilityRuntimeState), so
|
|
2155
|
+
// `list` and `state` stop disagreeing. `list` previously derived `status`
|
|
2156
|
+
// purely from ledger-entry existence — an installed-but-not-surfaced cap
|
|
2157
|
+
// reported active in `list` and absent in `state`. Surfaced is evaluated at
|
|
2158
|
+
// the default runtime config dir (the resolver resolves it when undefined),
|
|
2159
|
+
// matching `capability state <id>` with no --config-dir. Best-effort: a
|
|
2160
|
+
// resolver failure leaves surfacedById empty (rows report surfaced:null).
|
|
2161
|
+
const surfacedById = {};
|
|
2162
|
+
// surfacedById is keyed by capId only (NOT `${scope} ${capId}`): surface
|
|
2163
|
+
// state is single-source — one runtime config dir → one .gsd-surface.json
|
|
2164
|
+
// → one surfaced truth per capId — and the loader dedupes overlay caps to
|
|
2165
|
+
// one registry entry per id (first-party-wins). So a cap installed in both
|
|
2166
|
+
// scopes correctly shares one surfaced value across its list rows.
|
|
2167
|
+
try {
|
|
2168
|
+
const surfaceState = capabilityState.resolveCapabilityRuntimeState(cwd, undefined);
|
|
2169
|
+
for (const cap of (surfaceState && surfaceState.capabilities) || []) {
|
|
2170
|
+
if (cap && typeof cap.id === 'string') {
|
|
2171
|
+
surfacedById[cap.id] = cap.surfaced === true;
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
} catch { /* best-effort — list still works without the surfaced annotation */ }
|
|
2098
2175
|
for (const capId of Object.keys(fp)) {
|
|
2099
2176
|
const cap = fp[capId] || {};
|
|
2100
2177
|
rows.push({
|
|
@@ -2105,6 +2182,7 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
|
|
|
2105
2182
|
source: 'first-party',
|
|
2106
2183
|
scope: 'first-party',
|
|
2107
2184
|
status: 'active',
|
|
2185
|
+
surfaced: Object.prototype.hasOwnProperty.call(surfacedById, capId) ? surfacedById[capId] === true : null,
|
|
2108
2186
|
title: cap.title || null,
|
|
2109
2187
|
});
|
|
2110
2188
|
}
|
|
@@ -2154,6 +2232,12 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
|
|
|
2154
2232
|
scope: sc,
|
|
2155
2233
|
status,
|
|
2156
2234
|
reason,
|
|
2235
|
+
// Issue #2045 (DEFECT 3): surfaced reflects surface composition, so
|
|
2236
|
+
// list and state agree. An inactive (unconsented/incompatible) cap is
|
|
2237
|
+
// surfaced:false by definition; otherwise defer to the resolver.
|
|
2238
|
+
surfaced: status === 'active'
|
|
2239
|
+
? (Object.prototype.hasOwnProperty.call(surfacedById, capId) ? surfacedById[capId] === true : null)
|
|
2240
|
+
: false,
|
|
2157
2241
|
title: manifest.title || null,
|
|
2158
2242
|
});
|
|
2159
2243
|
}
|