Skip to content

feat: surface Gemara bundle metadata in list and get commands Body:#711

Open
yvonnedevlinrh wants to merge 2 commits into
complytime:mainfrom
yvonnedevlinrh:opsx/bundle-metadata-cli
Open

feat: surface Gemara bundle metadata in list and get commands Body:#711
yvonnedevlinrh wants to merge 2 commits into
complytime:mainfrom
yvonnedevlinrh:opsx/bundle-metadata-cli

Conversation

@yvonnedevlinrh

Copy link
Copy Markdown
Contributor

Summary

Implements #506 (Options B + C) -- surface Gemara bundle metadata via CLI for informed configuration.

Changes

  • complyctl list gains EVALUATOR and CONTROLS columns showing the evaluator type and control count for each cached policy
  • complyctl get prints a post-sync summary to stderr after fetching a policy, showing title, evaluator, control count, and assessment count
  • PolicyState in state.json gains policy_title, policy_evaluator, control_count, and assessment_count fields (backward compatible via omitempty)
  • policy.Resolver.ExtractPolicyMetadata() provides lightweight metadata extraction without building a full DependencyGraph
  • Upgrade backfill automatically populates metadata for pre-existing caches on the next complyctl get run
  • formatPolicySummary() helper for testable stderr output

Files Changed

Area Files
CLI commands cmd/complyctl/cli/get.go, cmd/complyctl/cli/list.go
Cache state internal/cache/state.go
Policy resolver internal/policy/resolver.go
Tests cli_test.go, get_verify_test.go, state_test.go, resolver_test.go
Docs CHANGELOG.md, AGENTS.md
OpenSpec openspec/changes/bundle-metadata-cli/ (proposal, design, spec, tasks)

Option A (deferred)

complyctl inspect <url> for pre-pull discovery was evaluated and deferred -- the gap is minimal now that get prints a summary and list shows metadata.

Closes #506

@yvonnedevlinrh yvonnedevlinrh self-assigned this Jul 10, 2026
@yvonnedevlinrh yvonnedevlinrh requested a review from a team as a code owner July 10, 2026 12:13
@yvonnedevlinrh yvonnedevlinrh force-pushed the opsx/bundle-metadata-cli branch 3 times, most recently from d01a665 to 4cad011 Compare July 10, 2026 12:51
Comment thread cmd/complyctl/cli/cli_test.go Outdated
Comment thread cmd/complyctl/cli/get.go Outdated
Comment thread cmd/complyctl/cli/get.go Outdated
Comment thread cmd/complyctl/cli/get.go Outdated
Comment thread cmd/complyctl/cli/cli_test.go
yvonnedevlinrh added a commit to yvonnedevlinrh/complyctl that referenced this pull request Jul 13, 2026
…te flush

Address PR complytime#711 review feedback from @trevor-vaughan:

- Use ps.Version (concrete persisted version) instead of the config tag
  for ExtractPolicyMetadata. A ":latest" pin is stored under the resolved
  version, so extracting by "latest" would fail store.Resolve() and
  silently drop all metadata.
- Move cache.SaveState() from per-policy (syncSinglePolicy) to after the
  loop (syncAllPolicies) for batch flush instead of repeated disk writes.
- Remove redundant cacheDir parameter from syncAllPolicies and
  syncSinglePolicy; use cacheMgr.Dir() instead.

Assisted-by: OpenCode (claude-opus-4-6)
Signed-off-by: Yvonne Devlin <ydevlin@redhat.com>
yvonnedevlinrh added a commit to yvonnedevlinrh/complyctl that referenced this pull request Jul 13, 2026
…rtion

Address PR complytime#711 review feedback from @trevor-vaughan:

- Replace truncated SHA-256 digests (16 hex chars) with valid-length
  hashes (64 hex chars) in test fixtures for realistic test data.
- Add missing dash assertion in TestListOptions_Run_MultiEvaluatorShowsDash
  to verify the evaluator column actually shows "-" for multi-evaluator
  policies.

Assisted-by: OpenCode (claude-opus-4-6)
Signed-off-by: Yvonne Devlin <ydevlin@redhat.com>
yvonnedevlinrh added a commit to yvonnedevlinrh/complyctl that referenced this pull request Jul 13, 2026
- Use ps.Version (concrete persisted version) instead of the config tag
  for ExtractPolicyMetadata. A ":latest" pin is stored under the resolved
  version, so extracting by "latest" would fail store.Resolve() and
  silently drop all metadata.
- Move cache.SaveState() from per-policy (syncSinglePolicy) to after the
  loop (syncAllPolicies) for a single batch flush.
- Remove redundant cacheDir parameter from syncAllPolicies and
  syncSinglePolicy; use cacheMgr.Dir() instead.
- Replace truncated SHA-256 digests with valid-length 64 hex char hashes
  in test fixtures.
- Add missing dash assertion in TestListOptions_Run_MultiEvaluatorShowsDash.

Assisted-by: OpenCode (claude-opus-4-6)
Signed-off-by: Yvonne Devlin <ydevlin@redhat.com>
@yvonnedevlinrh yvonnedevlinrh force-pushed the opsx/bundle-metadata-cli branch from c6e58f3 to b889433 Compare July 13, 2026 09:51
yvonnedevlinrh added a commit to yvonnedevlinrh/complyctl that referenced this pull request Jul 13, 2026
- Use ps.Version (concrete persisted version) instead of the config tag
  for ExtractPolicyMetadata. A ":latest" pin is stored under the resolved
  version, so extracting by "latest" would fail store.Resolve() and
  silently drop all metadata.
- Move cache.SaveState() from per-policy (syncSinglePolicy) to after the
  loop (syncAllPolicies) for a single batch flush.
- Remove redundant cacheDir parameter from syncAllPolicies and
  syncSinglePolicy; use cacheMgr.Dir() instead.
- Remove omitempty from ControlCount and AssessmentCount JSON tags so
  zero values survive round-trips and "metadata extracted with 0
  controls" is distinguishable from "metadata never extracted".
- Replace truncated SHA-256 digests with valid-length 64 hex char hashes
  in test fixtures.
- Add missing dash assertion in TestListOptions_Run_MultiEvaluatorShowsDash.

Assisted-by: OpenCode (claude-opus-4-6)
Signed-off-by: Yvonne Devlin <ydevlin@redhat.com>
@yvonnedevlinrh yvonnedevlinrh force-pushed the opsx/bundle-metadata-cli branch from b889433 to b6cdfcb Compare July 13, 2026 11:06
@yvonnedevlinrh

Copy link
Copy Markdown
Contributor Author

@trevor-vaughan Thanks for the thorough review. All five items addressed in b6cdfcb:

  1. Invalid test digests — replaced truncated SHA-256 hashes with valid-length 64 hex char digests across test fixtures.
  2. :latest version bug — applied your suggestion: extractMetadata uses fetched || !hasMetadata(ps) and passes ps.Version (concrete persisted version) to ExtractPolicyMetadata.
  3. Batch SaveState — moved cache.SaveState() from per-policy in syncSinglePolicy to a single flush after the loop in syncAllPolicies.
  4. Redundant cacheDir param — removed from syncAllPolicies/syncSinglePolicy; using cacheMgr.Dir() instead.
  5. Missing dash assertion — TestListOptions_Run_MultiEvaluatorShowsDash now asserts the evaluator column contains "-".
    Also removed omitempty from ControlCount/AssessmentCount JSON tags so zero values survive round-trips — no impact on existing caches since json.Unmarshal produces 0 for missing int fields either way. Branch rebased onto current main to resolve the merge conflict.

- Add EVALUATOR and CONTROLS columns to `complyctl list` sourced
  from PolicyState metadata cached in state.json
- Print post-sync summary to stderr after `complyctl get` showing
  policy title, evaluator, control count, and assessment count
- Add PolicyTitle, PolicyEvaluator, ControlCount, AssessmentCount
  fields to PolicyState with omitempty tags for backward compat
- Add ExtractPolicyMetadata() to policy.Resolver for lightweight
  metadata extraction without building full DependencyGraph
- Add upgrade backfill for pre-existing caches without metadata
- Add formatPolicySummary() helper for testable stderr output
- Include OpenSpec artifacts (proposal, design, spec, tasks)

Closes complytime#506

Assisted-by: OpenCode (claude-opus-4-6)
Signed-off-by: Yvonne Devlin <ydevlin@redhat.com>
- Use ps.Version (concrete persisted version) instead of the config tag
  for ExtractPolicyMetadata. A ":latest" pin is stored under the resolved
  version, so extracting by "latest" would fail store.Resolve() and
  silently drop all metadata.
- Move cache.SaveState() from per-policy (syncSinglePolicy) to after the
  loop (syncAllPolicies) for a single batch flush.
- Remove redundant cacheDir parameter from syncAllPolicies and
  syncSinglePolicy; use cacheMgr.Dir() instead.
- Remove omitempty from ControlCount and AssessmentCount JSON tags so
  zero values survive round-trips and "metadata extracted with 0
  controls" is distinguishable from "metadata never extracted".
- Replace truncated SHA-256 digests with valid-length 64 hex char hashes
  in test fixtures.
- Add missing dash assertion in TestListOptions_Run_MultiEvaluatorShowsDash.

Assisted-by: OpenCode (claude-opus-4-6)
Signed-off-by: Yvonne Devlin <ydevlin@redhat.com>
@yvonnedevlinrh yvonnedevlinrh force-pushed the opsx/bundle-metadata-cli branch from b6cdfcb to cc36c06 Compare July 13, 2026 13:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: surface Gemara bundle metadata via CLI for informed configuration

2 participants