list-ids --source <slug> returns 0 IDs for a registered source AND for a registered system
Summary
cpt --json list-ids --source <name> returns count = 0 and
artifacts_scanned = 0 regardless of whether the user passes:
- a system slug (e.g.
utea) — expected: list of IDs from artifacts
belonging to that system, OR a clear error that --source does not
accept system slugs
- a workspace source name (e.g.
utea-api) — expected: list of IDs
from artifacts attached to that source
Both invocations exit 0 with an empty result, while a project-wide
cpt --json list-ids --pattern "cpt-upilot-utea-api" resolves 421
IDs in the same workspace. The workspace registry is healthy (per
cpt --json info).
The "vacuous PASS with empty result" is the same anti-pattern as the
sibling spec-coverage --system bug (filed separately). A CI gate
that wraps cpt --json list-ids --source <name> will never see new IDs
appear and will silently regress.
Affected version
cpt 3.7.0b0 (cypilot-proxy 3.7.0b0, skill kit v3.7.0-beta).
Reproduction
Workspace shape: see the sibling spec-coverage --system issue draft;
it uses the same cypilot/config/artifacts.toml snippet. Same machine
(macOS 25.4, Python 3.13).
# Case A — user passes a system slug ("utea")
$ cpt --json list-ids --source utea --include-code
{
"count": 0,
"artifacts_scanned": 0,
"ids": []
}
# Case B — user passes a workspace source name ("utea-api")
$ cpt --json list-ids --source utea-api --include-code
{
"count": 0,
"artifacts_scanned": 0,
"ids": []
}
# Project-wide (works) — proves the IDs exist
$ cpt --json list-ids --pattern "cpt-upilot-utea-api" \
| jq '.count'
421
cpt --json info shows that utea is a system slug under upilot,
and that utea-api and utea-web are workspace source names attached
to that system's codebase blocks. Neither lookup path resolves any
artifact through --source.
Expected vs actual
| Invocation |
Expected |
Actual |
--source <system-slug> |
Either count > 0 (if --source accepts system slugs) or a clear error like "'utea' is a system slug, not a source — did you mean --system utea?" |
count = 0, no warning |
--source <workspace-source> |
count > 0 for IDs in the artifacts associated with that source |
count = 0, no warning |
| Empty result with no matches |
Exit > 0 OR a "matched 0 sources" warning |
Exit 0, message field omitted |
The silent-empty-result is a CI hazard. A team that wraps the command
to drive coverage / drift gates will see a vacuous PASS that never
fires.
Workaround we used
Substitute --source <name> with --pattern "<system-slug-prefix>"
(e.g. --pattern "cpt-upilot-utea-api") in every place we wanted a
per-source view. This works because the IDs are namespace-prefixed by
system, so a pattern filter recovers the same intent.
Proposed fix paths (for triage discussion)
- Document explicitly which slug type
--source accepts. The
--source flag's name suggests "workspace source", but operators
reach for it intuitively when they have a system slug — and getting
a vacuous empty result with no warning is the worst possible
feedback shape.
- If
--source is intentionally workspace-source-only, accept system
slugs as an alias OR fail loudly with a "did you mean --system?"
diagnostic.
- If the workspace-source path is also broken (Case B above), trace
through the artifact-to-source attachment logic — our info output
shows utea-api and utea-web as registered sources, but
--source utea-api resolves zero artifacts.
- Empty-result responses from
list-ids should never silently
succeed — surface a warning in the JSON envelope (e.g.
warnings: ["No artifacts matched filter --source=utea"]) so
wrappers can detect misconfiguration without parsing string
messages.
Cross-reference
- Cypilot remediation plan that surfaced the issue:
architecture/utea/remediation-DELTA.md § Validate gate (gate 8,
DEFERRED tooling caveat) and § Residual debt (third bullet)
- Sibling issue:
01-spec-coverage-system-empty-result.md
- ADR documenting the FULL traceability scope and pointing here:
architecture/utea/ADR/0012-code-traceability-scope.md
list-ids --source
<slug>returns 0 IDs for a registered source AND for a registered systemSummary
cpt --json list-ids --source <name>returnscount = 0andartifacts_scanned = 0regardless of whether the user passes:utea) — expected: list of IDs from artifactsbelonging to that system, OR a clear error that
--sourcedoes notaccept system slugs
utea-api) — expected: list of IDsfrom artifacts attached to that source
Both invocations exit
0with an empty result, while a project-widecpt --json list-ids --pattern "cpt-upilot-utea-api"resolves 421IDs in the same workspace. The workspace registry is healthy (per
cpt --json info).The "vacuous PASS with empty result" is the same anti-pattern as the
sibling
spec-coverage --systembug (filed separately). A CI gatethat wraps
cpt --json list-ids --source <name>will never see new IDsappear and will silently regress.
Affected version
cpt 3.7.0b0(cypilot-proxy 3.7.0b0, skill kitv3.7.0-beta).Reproduction
Workspace shape: see the sibling
spec-coverage --systemissue draft;it uses the same
cypilot/config/artifacts.tomlsnippet. Same machine(macOS 25.4, Python 3.13).
cpt --json infoshows thatuteais a system slug underupilot,and that
utea-apiandutea-webare workspace source names attachedto that system's codebase blocks. Neither lookup path resolves any
artifact through
--source.Expected vs actual
--source <system-slug>count > 0(if--sourceaccepts system slugs) or a clear error like"'utea' is a system slug, not a source — did you mean --system utea?"count = 0, no warning--source <workspace-source>count > 0for IDs in the artifacts associated with that sourcecount = 0, no warning"matched 0 sources"warningThe silent-empty-result is a CI hazard. A team that wraps the command
to drive coverage / drift gates will see a vacuous PASS that never
fires.
Workaround we used
Substitute
--source <name>with--pattern "<system-slug-prefix>"(e.g.
--pattern "cpt-upilot-utea-api") in every place we wanted aper-source view. This works because the IDs are namespace-prefixed by
system, so a pattern filter recovers the same intent.
Proposed fix paths (for triage discussion)
--sourceaccepts. The--sourceflag's name suggests "workspace source", but operatorsreach for it intuitively when they have a system slug — and getting
a vacuous empty result with no warning is the worst possible
feedback shape.
--sourceis intentionally workspace-source-only, accept systemslugs as an alias OR fail loudly with a "did you mean
--system?"diagnostic.
through the artifact-to-source attachment logic — our
infooutputshows
utea-apiandutea-webas registered sources, but--source utea-apiresolves zero artifacts.list-idsshould never silentlysucceed — surface a warning in the JSON envelope (e.g.
warnings: ["No artifacts matched filter --source=utea"]) sowrappers can detect misconfiguration without parsing string
messages.
Cross-reference
architecture/utea/remediation-DELTA.md§ Validate gate (gate 8,DEFERRED tooling caveat) and § Residual debt (third bullet)
01-spec-coverage-system-empty-result.mdarchitecture/utea/ADR/0012-code-traceability-scope.md