Repository navigation
refactor(cli): reporting, feeds, drift and rescan worklist on traust-core (XWING-2440) - #285
Merged
smith-xyz merged 2 commits intoOct 27, 2026
Conversation
…core (XWING-2440)
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: smith-xyz The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
9 of 11 tasks
smith-xyz
added a commit
to smith-xyz/traust
that referenced
this pull request
Oct 27, 2026
smith-xyz
added a commit
to smith-xyz/traust
that referenced
this pull request
Oct 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Plan:
plans/traust-standardization/0-continuous-ops/in-progress/17-shaun-traust-core-only.md(part)Wave 2, lane (d). Stacked on traust#279 (lane a,
refactor/traust-core-loader@9189e08): until #279 merges this diff includes its commit; review only the top commit446caa1. Pins traust-core to traust-core#222 @15db382(stacked on core developmentbeb96f1, the pin lane (a) uses).Chain: traust#279 (lane a) → traust-core#222 → this PR.
What
RenderFormatmoves tomodels/artifacts.py(the consumer ratchet allows onlycontext/models/errors), and a newContext.reportingcached property builds the ReportingService without the record store.services().reportinghands out that same instance. Without it, the four file-only commands below would have created or opened the record store on every run.cli/groups/reporting.py→ctx.reporting. No engine import left.validate→validate_reports(path, strict=, schema=).--schemakeeps its file-name form:triage.schema.json,contracts/triage.schema.jsonandtriageall map to the contract schematriage. Output (PASS/FAIL lines, totals, exit codes, the "No .json files found" / "Path not found" lines) is unchanged.lint→lint_threat_models(paths, strict=).traust.context.load()already registers the pinned ATT&CK catalog, so ids are checked against the table, as the engine's linter did when it could importattack_refs.render→render(ThreatModelArtifact | ReportArtifact, RenderFormat.MARKDOWN), chosen by the-threat-model.jsonname as before. The section-loss guard uses core'slost_sections, and traust's local copy (_section_bodies,lost_sections) is deleted.sarif→sarif_reports(root)for the sweep, andsarif(CloudConfigAuditArtifact | ReportArtifact)per report. The cloud-config arm is still picked by content (metadata.assessment_mode == "declared"orfacts_ref), as the engine exporter did, so a cloud-config-findings-current.jsonstill exports through the declared arm.cli/fetch_feeds.py→ coreLocations:locations(load(home)).product_definitionsreplacestraust_engine.locations.product_definitions_url(configured_locations()).cli/check_drift.py:traust_engine/data/compliance/: NIST 800-53 rev5 spine, 800-53B profiles, PCI/SOC2/GDPR id catalogs,compliance-mapping.yaml,provenance.json, README) moves intopacks/security/compliance/as pack content, read by path. The files are byte-identical to traust-engine7c6aa58. The engine keeps its copy until wave 3 deletes it.traust_core.v1.providers.tools.{yara,opengrep}), since core runs those tools now. The pins are identical to the engine's. The refresh text namespacks/security/compliance/README.md.cli/build_rescan_worklist.py: core's strictHttpsRepoUrlwould break shadow-run parity (it's https-only, the whole string must be the URL, and the host must be inforge_hosts). So the engine'snormalize_repo_urlmoves in verbatim as the private_normalize_repo_url, marked# retires with this script at cutover (plan 18, Live runs). This is a deliberate, scoped exception to "no engine code in traust" (supervisor-approved): the script is legacy, kept only so the shadow run can diff against it. It has a new table-driven test.sweep collect/draft/sweep/emit/benchmark/rule-lane→PENDING(decision: sweep stages — retire or port). Core has no door for them; the engine's sweep package is file-store based.portfolio build/freshness/interfaces/symbols/artifacts/stats/query→PENDING(decision: portfolio graph layers — retire or port). These are the engine's SQLite graph layers L0–L4; the portfolio-graph port replaced only blast radius (dependents/dependencies).sweep verify-draft→NEED(core: an opengrep door that scans with one given rule file). Core's registered opengrep tool scans with the registered pack only.DEFAULT_SWEEP_LIMIT/SWEEPS_RELstay with the engine ops that use them: separating them would only copy engine constants.build_rescan_worklist.py1→0,check_drift.py1→0,fetch_feeds.py1→0,groups/reporting.py4→0.tests/test_engine_imports.pyshrinks the same four entries. Nothing grew.Behaviour changes
reporting renderrefuses a document its contract schema refuses (exit 2,render: ERROR: <schema>: N issue(s); first: …, nothing written). Before, the engine rendered any JSON.reporting sarifrefuses a schema-invalid report (ERROR: <path>: …, rc 1, the run continues). Exported SARIF uses core's naming (core refactor(ops): emit registered reason codes and retain diagnostic logs #213): drivertraust(wastraust-engine), run propertiestraust/*(wereharness/*), rule text "Finding category" (was "Harness finding category").reporting validate --schemanames contract schemas only. A schema file outside traust-contracts can no longer be loaded by path: its file name maps to the contract schema of that name, or the run exits 2 with core'sConfigError(before: a traceback for an unknown name).reporting validate|lint|render|sarifread the deployment config through core (traust.context.load). An invalidcore.yamlexits 2.sarifnow resolveslocations.sarif_tool_urifrom--config-home(before:$TRAUST_CONFIG_HOMEonly).feeds fetch-productsreadslocations.product_definitionsfrom--config-home(before:$TRAUST_CONFIG_HOMEonly). It always loads the config, even with--cache-dir.check driftpin rows read core's provider modules. Their refresh hint names the core module to bump.Ops still on the engine (exact scope for the pending decisions)
sweep collectsrc/traust/cli/groups/sweep.py:100harnessing/mine-ledger/SKILL.md:160sweep draftsweep.py:128mine-ledger/SKILL.md:165sweep sweepsweep.py:168mine-ledger/SKILL.md:169sweep emitsweep.py:200mine-ledger/SKILL.md:171sweep benchmarksweep.py:250harnessing/5-validate/validate-findings/SKILL.md:139;docs/tooling-and-structure-files.md:67;docs/continuous-operations.md:145sweep rule-lanesweep.py:294mine-ledger/SKILL.md:13,73,194,236,260,286;docs/error-model.md:158-159;docs/tooling-and-structure-files.md:79;docs/continuous-operations.md:112,139;harnessing/drift-watch/SKILL.md:63sweep verify-draft(NEED)sweep.py:508portfolio buildsrc/traust/cli/groups/portfolio.py:110harnessing/portfolio-graph/SKILL.md:124,164;.claude/commands/portfolio-graph.md:5;docs/continuous-operations.md:151portfolio freshnessportfolio.py:203portfolio-graph/SKILL.md:103portfolio interfacesportfolio.py:229portfolio-graph/SKILL.md:154portfolio symbolsportfolio.py:257portfolio artifactsportfolio.py:298portfolio statsportfolio.py:326portfolio-graph/SKILL.md:169portfolio queryportfolio.py:360portfolio-graph/SKILL.md:194,197,201Reviewer checks
ReportingServiceviactx.reporting, coreLocations, core provider pins); no engine code copied into traust except the approved_normalize_repo_url(retires with the script)Quality checklist
lost_sections,sarif_reports,validate_reports,lint_threat_models; traust's copies deleted.git, trailing dot, http, no URL,ext::)traust_test_w2_d)Changed tests
tests/test_render_section_guard.pyreporting.load_enginewith a fake facade rendering throughtraust_engine.reporting.render→ callscall_renderfor real (core render);test_lost_sections_names_what_would_gousesload().reporting.lost_sectionsand core's render instead of traust's deletedlost_sectionsand the engine renderer. Assertions unchangedrenderandlost_sectionsare core's now; traust's copies were deletedtests/test_fetch_feeds.pyff.locations.configured_locations(engine) with a contractsLocations→ writes alocations.yamlwithproduct_definitionsinto a tmp config home (TRAUST_CONFIG_HOME); the "absent" test deletes that file instead of patching. Assertions unchangedLocationsviaload()tests/routing_reference.py(helper, not an assertion)normalize_repo_url→_normalize_repo_urlbuild_rescan_worklist.pytests/test_engine_imports.pybuild_rescan_worklist.py,check_drift.py,fetch_feeds.py,groups/reporting.pyNew:
tests/test_reporting_group.py(13 tests);test_normalize_repo_url_takes_the_first_url_out_of_report_prose(10 cases) intests/test_build_rescan_worklist.py.Validation
make lint-fix && make test: 2718 passed, 2 skipped (Postgrestraust_test_w2_d)uv run traust check docs-consistency: consistente0b2ddd, referenceupstream/development): cleanLeft for later lanes
reporting rate-threatsstill importstraust_contracts.v1.risk_rating(contracts 1 in.ratchet.json). No lane names it, and core hascontracts.risk_ratingbut no consumer-reachable door.harnessing/threat-register/SKILL.md:18,3-audit/cloud-config-audit/SKILL.md:19,3-audit/secure-container-audit/SKILL.md:31(allowed-toolsnamingtraust_engine.reporting.*);3-audit/compliance-check/SKILL.md:31(compliance data "shipped with traust-engine");docs/risk-rating-methodology.md:112;config/README.md:40,50.tests/test_check_drift.py::test_argus_pack_is_not_the_default_rules_sourcestill reads the engine adapter's source, andtest_rule_pack_pins_parse_from_the_engine_adapterskeeps its name though it now parses core's modules (unchanged tests).