Scoreboard: Does the implementation fully represent the spec layer it claims to align to?
This document tracks every component defined in Sirius Context Engine Spec v3.0 against its build state, assigns it to a sprint, and surfaces what work remains. Update this file as sprints close.
| Symbol | Meaning |
|---|---|
| β | Built, tested, merged |
| π‘ | Built, not yet tested |
| π² | Specified, not yet built |
| β³ | Blocked on external dependency |
| ποΈ | Scheduled for removal (replaced by upstream) |
| Component | File | Status | Sprint | Notes |
|---|---|---|---|---|
ContextEngine::current() |
src/core/ContextEngine.php |
β | S-01 | Throws ContextBootException, never null/partial |
| CLI system context | src/core/ContextEngine.php |
β | S-01 | SYSTEM/GLOBAL/CLI path |
SirusContext DTO |
src/core/SirusContext.php |
β | S-01 | Includes trust_score; trust_level typed as TrustLevelPrimitive enum |
ContextCache |
src/core/ContextCache.php |
β | S-01 | Cache + TTL eviction |
ContextBootException |
packages/sparxstar-ouroboros-integrity/src/Exceptions/ContextBootException.php |
β | S-04 | Migrated to Ouroboros CO-001 β Starisian\Sparxstar\Infrastructure\Exceptions |
ContextPulse DTO |
packages/sparxstar-ouroboros-integrity/src/DTOs/ContextPulse.php |
β | S-04 | Migrated to Ouroboros CO-001 β Starisian\Sparxstar\Infrastructure\DTOs |
SirusDatabase schema boot |
src/core/SirusDatabase.php, src/SirusPlugin.php |
β | S-08 (fixed 2026-08-01) | Platform-breaking bug fixed: as a must-use plugin, Sirus never fires register_activation_hook(), so ensure_schema() was never called in a real deployment (only wired to SirusPlugin::onActivation()). Replaced with SirusDatabase::maybe_upgrade_schema() (public SCHEMA_VERSION int constant, one cheap get_option() read, ensure_schema() only on mismatch) called from SirusPlugin::bootSchemaAndCron() on an early init hook. Cron scheduling moved the same way, reusing the existing wp_next_scheduled()-guarded schedule_cron() pattern. onActivation()/onDeactivation() and the lifecycle hook registrations in sparxstar-sirus-context.php are removed. No table/column/index definitions changed β only when schema creation runs. Multisite: no explicit per-site loop needed (mirrors SparxstarUECInstaller::activate_site()'s "never loop over sites" rule) β each request already executes in its own site's $wpdb/option context. |
| Component | File | Status | Sprint | Notes |
|---|---|---|---|---|
TrustEngine |
src/core/TrustEngine.php |
β | S-01/S-02 | Frozen algorithm; 18 unit tests in TrustEngineTest |
TrustResolver |
src/core/TrustResolver.php |
β | S-01/S-02 | Credential-level base + drift/session deductions; 19 unit tests in TrustResolverTest; CREDENTIAL_BASE fixed 2026-08-01 β removed dead elder entry (not a CredentialTier case), added missing authority entry (0.95, above user 0.85); added exhaustive-coverage and monotonic-ordering tests |
StepUpPolicy |
src/core/StepUpPolicy.php |
β | S-01/S-02 | Frozen policy; requiresStepUp() + TRUST_LEVEL_STEP_UP_REQUIRED pre-flag check; fails closed on LOCKED (checked before STEP_UP_REQUIRED, added 2026-08-01); 21 unit tests |
PulseGenerator |
src/core/PulseGenerator.php |
β | S-01/S-02 | HMAC-SHA256 only; consumes enum-backed SirusContext::trust_level; PAM-002-P2 fields wired (behavior_flags, geo_zone, network_effective_type, session_duration); 36 unit tests in PulseGeneratorTest; $now/$ttlSeconds explicit params; signing key constant renamed from its old SIRUS_-prefixed name to SPARXSTAR_PULSE_SIGNING_KEY (2026-08-01, matches Helios); resolveTtl(ResourceSensitivity) implements the sensitivity/connectivity TTL strategy (2026-08-01) |
| Component | File | Status | Sprint | Notes |
|---|---|---|---|---|
DeviceContinuity |
src/core/DeviceContinuity.php |
β | S-01 | Two-stage pipeline: resolveDevice() + evaluateContinuity() |
DeviceMatcher |
src/core/DeviceMatcher.php |
β | S-01 | spec Β§14.3: STRONG_MATCH_THRESHOLD=0.8 / WEAK_MATCH_THRESHOLD=0.6; MatchResult enum; classify(); 22 unit tests |
DeviceRecord DTO |
src/core/DeviceRecord.php |
β | S-01 | |
DeviceRepository |
src/core/DeviceRepository.php |
β | S-01 | |
IdentityResolver |
src/core/IdentityResolver.php |
β | S-01 | Five-tier resolution via Helios |
AuthorityResolver |
src/core/AuthorityResolver.php |
β | S-01 | Multi-authority aggregation |
| Component | File | Status | Sprint | Notes |
|---|---|---|---|---|
EnvironmentResolver |
src/services/EnvironmentResolver.php |
β | S-07 | Client-first EnvironmentRecord builder with UA fallback only; compatibility accessors retained |
EnvironmentRecord DTO |
src/core/EnvironmentRecord.php |
β | S-07 | Built with IP anonymization, region-level location, network filtering, and capture metadata |
NetworkContextBroker |
src/core/NetworkContextBroker.php |
β | S-01 | issueToken(context, secret) / verifyToken(token, secret) β explicit secret; portable |
| Component | File | Status | Sprint | Notes |
|---|---|---|---|---|
ConsentManager |
src/core/ConsentManager.php |
β | S-01 | Three-level cascade (userβsiteβdeny); purpose consent; append-only history; 16 tests β |
| Component | File | Status | Sprint | Notes |
|---|---|---|---|---|
StarUserEnv facade |
src/StarUserEnv.php |
β | S-00 | FROZEN β UEC backward compat; signatures must never change |
UECCompatibilityShim |
src/integrations/UECCompatibilityShim.php |
β | S-00 | Namespace alias bridge |
Ownership ruling: Sirus generates pulses; Helios verifies them (
.github/instructions/copilot-instructions.md: "Do not put verification logic here"). The canonical six-check contract andVerificationResultenum are shared types owned by Ouroboros β Sirus must not implement runtime verification. Sirus's only obligation is to prove its generated pulses round-trip against the canonical Ouroboros signing material.
| Component | Owner | Status | Sprint | Notes |
|---|---|---|---|---|
PulseGenerator (signing side) |
Sirus | β | S-01/S-02 | Signs via Ouroboros ContextPulseSigningMaterial::build() |
VerificationResult enum |
Ouroboros | β³ | S-07 | Shared type β import from Ouroboros, never redefine in Sirus |
PulseVerifier six-check |
Helios / Ouroboros | β³ | S-07 | Not built in Sirus by design. S-07 adds a generateβverify round-trip test only |
| Component | File | Status | Sprint | Notes |
|---|---|---|---|---|
REST /device |
src/api/SirusRESTController.php |
β | S-01 | Registered |
REST /context |
src/api/SirusRESTController.php |
β | S-01 | Registered; optional device_id must match the current or token-derived context |
REST /pulse |
src/api/SirusRESTController.php |
π‘ | S-07 | Registered with HttpOnly/SameSite=Strict pulse cookie + metadata body; full validation pending dependency install |
REST /identity |
src/api/SirusRESTController.php |
π‘ | S-07 | Registered; delegates to IdentityResolver; full validation pending dependency install |
REST /session |
src/api/SirusRESTController.php |
π‘ | S-07 | Registered; exposes current session status; full validation pending dependency install |
REST /client-report |
src/api/SirusRESTController.php |
π‘ | S-07 | Registered; delegates to ClientTelemetry; full validation pending dependency install |
| API contract + seed | docs/contracts/sirus-api-contract.v1.json, docs/contracts/sirus-api-seed.v1.json |
β | S-07 | Machine-readable OpenAPI contract and seed payloads for downstream repos; smoke-tested without WordPress |
CapabilityEngine |
src/core/CapabilityEngine.php |
π‘ | S-01 | resolve(SirusContext): array; no unit test |
AuthorityResolver |
src/core/AuthorityResolver.php |
π‘ | S-01 | Built; no unit test |
ClientTelemetry |
src/core/ClientTelemetry.php |
π‘ | S-01 | Built; no unit test |
The runtime signal-evaluation and mitigation pipeline that backs the trust signals
TrustEngineconsumes. Built earlier; comprehensive unit coverage landed via PRs #80/#81 ("12 previously uncovered classes"). Tracked here so the subsystem is visible against the S-06 observability theme.
| Component | File | Status | Sprint | Notes |
|---|---|---|---|---|
SirusSignalEvaluator |
src/helpers/SirusSignalEvaluator.php |
β | S-06 | SirusSignalEvaluatorTest |
SirusMitigationCoordinator |
src/services/SirusMitigationCoordinator.php |
β | S-06 | SirusMitigationCoordinatorTest |
SirusMitigationRuleEngine |
src/helpers/SirusMitigationRuleEngine.php |
β | S-06 | SirusMitigationRuleEngineTest |
SirusRuleConfig |
src/helpers/SirusRuleConfig.php |
β | S-06 | SirusRuleConfigTest |
SirusImpactScorer |
src/helpers/SirusImpactScorer.php |
β | S-06 | SirusImpactScorerTest |
SirusPriorityScorer |
src/helpers/SirusPriorityScorer.php |
β | S-06 | SirusPriorityScorerTest |
SirusRateLimit |
src/helpers/SirusRateLimit.php |
β | S-06 | SirusRateLimitTest; REMOTE_ADDR validated before rate-limit keying |
SirusEventAggregator |
src/core/SirusEventAggregator.php |
β | S-06 | SirusEventAggregatorTest |
SirusEventRepository |
src/core/SirusEventRepository.php |
β | S-06 | SirusEventRepositoryTest |
SirusRuleHitRepository |
src/core/SirusRuleHitRepository.php |
β | S-06 | SirusRuleHitRepositoryTest |
SirusMitigationActionRepository |
src/core/SirusMitigationActionRepository.php |
β | S-06 | SirusMitigationActionRepositoryTest |
SirusEventController (REST) |
src/api/SirusEventController.php |
β | S-06 | SirusEventControllerTest |
SirusDirectiveController (REST) |
src/api/SirusDirectiveController.php |
β | S-06 | SirusDirectiveControllerTest |
SirusDeviceParser |
src/services/SirusDeviceParser.php |
β | S-06 | SirusDeviceParserTest; Matomo wrapper, empty output without optional dep |
HeliosClient |
src/integrations/HeliosClient.php |
β | S-06 | HeliosClientTest |
SirusNetworkSettingsPage |
src/admin/SirusNetworkSettingsPage.php |
β | S-06 | SirusNetworkSettingsTest |
| Test File | Component | Status | Sprint | Tests |
|---|---|---|---|---|
ContextEngineTest.php |
ContextEngine |
β | S-01 | 6 |
ContextCacheTest.php |
ContextCache |
β | S-01 | β |
SirusContextTest.php |
SirusContext |
β | S-01 | β |
NetworkContextBrokerTest.php |
NetworkContextBroker |
β | S-01 | 10 tests: issue/verify round-trip, tamper detection, wrong secret, expired |
IdentityResolverTest.php |
IdentityResolver |
β | S-01 | β |
DeviceContinuityTest.php |
DeviceContinuity |
β | S-01 | +2 STEP_UP_REQUIRED tests |
DeviceRecordTest.php |
DeviceRecord |
β | S-01 | β |
TrustEngineTest.php |
TrustEngine |
β | S-02 | 18 |
PulseGeneratorTest.php |
PulseGenerator |
β | S-02 | 20 |
TrustResolverTest.php |
TrustResolver |
β | S-02 | 15 |
EnvironmentResolverTest.php |
EnvironmentResolver |
β | S-07 | Client signals take precedence; UA/Matomo is fallback only; network filter; EnvironmentRecord output |
DeviceMatcherTest.php |
DeviceMatcher |
β | S-02 | 22 |
ConsentManagerTest.php |
ConsentManager |
β | S-02 | 16 tests β cascade order, privacy-first hard default, anonymous user, invalid meta, multisite isolation, history, purpose consent |
StepUpPolicyTest.php |
StepUpPolicy |
β | S-02 | 17 |
AuthorityResolverTest.php |
AuthorityResolver |
β | S-07 | Authority trust paths and precedence coverage |
CapabilityEngineTest.php |
CapabilityEngine |
β | S-07 | Named capability issuance + filter coverage |
ClientTelemetryTest.php |
ClientTelemetry |
β | S-07 | Report/aggregation/pruning, no post-meta storage assertions |
PulseRoundTripTest.php |
PulseGenerator β Ouroboros |
β | S-07 | Generateβverify against canonical Ouroboros signing material |
EnvironmentRecordTest.php |
EnvironmentRecord |
β | S-07 | Privacy invariants at construction |
RestApiTest.php (integration) |
SirusRESTController |
β | S-07 | Covers all six REST endpoints (Β§18β19) |
ContextBootExceptionTest.php |
ContextBootException |
ποΈ | β | Removed from Sirus scope β type owned by Ouroboros since S-04 |
ContextPulseTest.php |
ContextPulse |
ποΈ | β | Removed from Sirus scope β type owned by Ouroboros since S-04 |
Static spec-conformance audit against Sirus Context Engine Spec v3.0 found and fixed six defects (B-1 through B-6) plus a stub-drift CI gap (D-4). Full detail per-component is recorded in the Scoreboard rows above; this note records the cross-cutting decisions.
- B-1 (π΄ platform-breaking): the old
SIRUS_-prefixed signing-key constant renamed toSPARXSTAR_PULSE_SIGNING_KEYeverywhere (code, tests,PUBLIC_API.md,README.md) to match Helios's already-renamed side. Every pulse was failing Helios's signature verification until this landed. - B-2 (π΄ platform-breaking): see the
SirusDatabaseschema boot row above. Sirus tables were never created in a real deployment because must-use plugins never fire activation hooks. - B-3 (π ) β table-name reconciliation:
sparxstar-user-environment-check.phpandsparxstar-sirus-context.phpdefinedSPX_ENV_CHECK_DB_TABLE_NAMEto two different values (sparxstar_uec_snapshotsvssparxstar_env_snapshots) with behavior depending on mu-plugin load order. Decision: keepsparxstar_env_snapshotsβ the value already defined (guarded, "define if not already defined") bysparxstar-sirus-context.php, which is the live/active orchestrator entry point. Reasoning: WordPress loads mu-plugins in filename-alphabetical order;sparxstar-sirus-context.phpsorts beforesparxstar-user-environment-check.php('s' < 'u'), so it always defines the constant first in practice even without the new guard. The new guard added insparxstar-user-environment-check.php(if (defined('SIRUS_VERSION')) { return; }) makes this outcome unconditional rather than order-dependent: the legacy file's own conflicting definition ofSPX_ENV_CHECK_DB_TABLE_NAME(sparxstar_uec_snapshots) is now unreachable whenever Sirus is loaded. In practice this also means the legacySparxstarUECDatabase/SparxstarUECSnapshotRepositorycode path (the only consumer of that constant) no longer runs at all when Sirus is active β it was already superseded bySirusDatabase/SirusEventRepositoryper the UEC Legacy Scoreboard below.sparxstar-user-environment-check.phpwas also added to.distignore. Neither legacy file was deleted β full removal remains S-03, blocked on the stabilization window. - B-4 (π ): see the
TrustResolverrow above. - B-5 (π ): see the
StepUpPolicyrow above. - B-6 (π ): see the
PulseGeneratorrow above (pulse TTL strategy). - B-7 β known pending follow-up: a parallel Ouroboros-side effort is adding a canonical
CredentialTiertosparxstar-ouroboros-integrity(tracked here as OQ-009 indocs/sirus-tech-spec.md). This repo's local provisionalsrc/Infrastructure/DTOs/CredentialTier.phpand the"Starisian\\Sparxstar\\Infrastructure\\": "src/Infrastructure/"autoload entry incomposer.jsonwere deliberately not touched in this pass β they cannot be removed until the promoted Ouroboros version actually ships in a released Composer version. Follow-up: once that ships, delete the local stub, drop the autoload entry, and addCredentialTiertobin/check-ouroboros-stub-drift.php's coverage. - D-4 (π ): added
bin/check-ouroboros-stub-drift.php(composer scriptcheck:ouroboros-drift) and a newouroboros-stub-driftCI job in.github/workflows/test.yml(runs afterphp-tests). Reflects the real installed Ouroboros package and checksTrustLevelPrimitive,ContextPulse,Platform,ContextPulseSigningMaterial, andContextBootExceptionagainst the shapes this repo's code assumes β the automated version of the check that would have caught the historical drift indocs/DRAFT-OQ-016-trustlevelprimitive-drift.mdbefore it reached CI as 94 failures. - Pre-existing failures observed while running the full suite (not caused by this pass, not
fixed β out of scope):
AuthorityResolverTest/CapabilityEngineTest(6 + 8 tests) call a test helper (makeContext(string $credentialTier)) that passesTrustLevelPrimitivestring values ('NORMAL','STEP_UP_REQUIRED','LOCKED') intoCredentialTier::from(), which throwsValueErrorsince those are not validCredentialTierbacking values β a test-authoring bug confusing the two enums.RestApiTest(2 tests) callsWP_REST_Request::set_body_params(), which the test bootstrap'sWP_REST_Requeststub does not implement. Both predate this branch.
- Runtime/security review found
/contextaccepted an optionaldevice_idparameter but did not enforce it. The handler now rejects mismatches for both current-context andctx_token-derived responses. - Dependency validation is currently gated by the installability of
sparxstar-ouroboros-integrity. Keep S-07 validation rows π‘ until CI or a credentialed environment can install dependencies and run the full suite.
- Restore authenticated/package access for
starisian/sparxstar-ouroboros-integrityand makecomposer install --no-interaction --prefer-distreproducible; keepcomposer run smoke:api-contractas the no-dependency preflight. - Run
composer run test,composer run test:unit, andcomposer run analyze; flip S-07 validation rows from π‘ to β only after those commands pass without deprecations or failures. - Complete S-05 by raising PHPStan toward Level 7 in small, no-baseline increments.
- After the UEC stabilization window closes, execute S-03 legacy removal while preserving
StarUserEnvmethod signatures. - Verify Helios and Dheghom consume the same Ouroboros release and that pulse verification remains outside Sirus runtime.
The provisional Sirus mirrors have been removed; these rows record the completed migration to sparxstar-ouroboros-integrity.
| Provisional file | Canonical owner | Migration status |
|---|---|---|
src/exceptions/ContextBootException.php |
sparxstar-ouroboros-integrity |
β Migrated β Ouroboros CO-001 |
src/dto/ContextPulse.php |
sparxstar-ouroboros-integrity |
β Migrated β Ouroboros CO-001 |
Hard rule:
Keep importing the Ouroboros-owned types directly. Do not reintroduce local mirrors.
Ouroboros must own and export:
ContextPulseDTOContextBootExceptionGovernanceTokenDTOAgreementResultenumValidationHelper- All shared cross-repo enums
Legacy sparxstar-user-environment-check files remain in the codebase during the migration window. Scheduled for removal once all call sites are confirmed migrated.
| File | Replacement | Status | Sprint |
|---|---|---|---|
src/SparxstarUserEnvironmentCheck.php |
src/SirusPlugin.php |
ποΈ | S-03 |
src/core/SparxstarUECAssetManager.php |
src/core/ContextEngine.php |
ποΈ | S-03 |
src/core/SparxstarUECDatabase.php |
src/core/SirusDatabase.php |
ποΈ | S-03 |
src/core/SparxstarUECInstaller.php |
src/core/SirusDatabase.php |
ποΈ | S-03 |
src/core/SparxstarUECKernel.php |
src/SirusPlugin.php |
ποΈ | S-03 |
src/core/SparxstarUECSnapshotRepository.php |
src/core/SirusEventRepository.php |
ποΈ | S-03 |
src/cron/SparxstarUECScheduler.php |
src/SirusPlugin.php (cron hooks) |
ποΈ | S-03 |
src/includes/SparxstarUECCacheHelper.php |
src/core/ContextCache.php |
ποΈ | S-03 |
src/includes/SparxstarUECSessionManager.php |
src/core/DeviceContinuity.php |
ποΈ | S-03 |
src/services/SparxstarUECGeoIPService.php |
src/services/EnvironmentResolver.php |
ποΈ | S-03 |
src/api/SparxstarUECRESTController.php |
src/api/SirusRESTController.php |
ποΈ | S-03 |
src/admin/SparxstarUECAdmin.php |
src/admin/SirusDashboardPage.php |
ποΈ | S-03 |
UEC compatibility layer established. StarUserEnv facade frozen.
-
StarUserEnvfacade (frozen public API) -
UECCompatibilityShim(namespace aliasing) -
SirusPlugin,SirusDatabase,SirusEventRepository -
IpAnonymizer(last-octet zeroing enforced)
All components from Sirus Context Engine Spec v3.0 built. Behavior locked, not just structure.
-
ContextEngine::current()β deterministic, throwsContextBootException, never null - CLI system context path (
SYSTEM/GLOBAL/CLI) -
SirusContextDTO βtrust_scorefield added -
TrustEngineβ frozen algorithm (base 1.0, deductions clamped to [0.0, 1.0]) -
TrustResolverβ credential-level base + drift/session deductions forbuildFromDevice() -
PulseGeneratorβ HMAC-SHA256, no identity in pulse, key from constant only -
ContextPulseDTO β immutable, provisional Ouroboros mirror -
ContextBootExceptionβ provisional Ouroboros mirror -
EnvironmentResolverβ Matomo DeviceDetector + regex fallback + Throwable guard -
DeviceMatcherβ spec Β§14.3:STRONG_MATCH_THRESHOLD=0.8/WEAK_MATCH_THRESHOLD=0.6;MatchResultenum (STRONG/WEAK/NO);classify()static method;hardware_concurrencykey (nothardware_conc) -
ConsentManagerβ three-level cascade (user meta β site option β deny), purpose consent, append-only history -
StepUpPolicyβ usesContextPulse+ResourceSensitivityenum;requiresStepUp()/getRequiredLevel()frozen boundary;TRUST_LEVEL_STEP_UP_REQUIREDpre-flag; 17 tests inStepUpPolicyTest -
NetworkContextBrokerβissueToken(context, secret)/verifyToken(token, secret)β explicit secret;tl/tsround-trip; absenttsderived fromtl; 10 tests - README.md β full spec alignment documentation
- PUBLIC_API.md β public surface document for cross-repo consumers
Every S-01 component built without a unit test needs one. PHPUnit ^11.5.50, extends
SirusTestCase.
-
TrustEngineTestβ 18 tests: frozen algorithm, all signal combos, clamping to [0.0, 1.0], level mapping -
PulseGeneratorTestβ 20 tests: key validation, pulse fields, no identity_id, TTL = issued_at + default, explicit$now/$ttlSecondshonoured, sig is 64-char hex -
TrustResolverTestβ 15 tests: all credential bases, drift deduction, new-session deduction, combined, clamping -
β removed from scope;ContextPulseTestContextPulseis owned by Ouroboros since S-04 -
β removed from scope;ContextBootExceptionTestContextBootExceptionis owned by Ouroboros since S-04 -
EnvironmentResolverTestβ delivered in S-07 (client-first signals, UA/regex fallback, network filter) -
DeviceMatcherTestβ β COMPLETE (22 tests: classify() three-way branching, STRONG/WEAK/NO_MATCH cases, boundary at 0.8 and 0.6, scoreHash, scoreComponents, hardware_concurrency key validation) -
ConsentManagerTestβ cascade order (userβsiteβdeny), privacy-first hard default, anonymous user skip, invalid meta fallthrough, multisite isolation, history append-only, purpose consent (16 tests β ) -
StepUpPolicyTestβ β COMPLETE (17 tests β includes STEP_UP_REQUIRED trust level pre-flag)
Acceptance criteria: composer run test:unit passes with no failures or deprecations.
Remove all
SparxstarUEC*files. Confirm no production call sites reference old namespace directly.
Prerequisite: 30-day stabilisation window post S-01 deployment closed.
- Audit all active site call sites for
Starisian\SparxstarUEC\namespace references - Remove all 12 legacy UEC files listed in the UEC Legacy Scoreboard above
- Remove
UECCompatibilityShim(no longer needed) - Remove
src/admin/SparxstarUECAdmin.php - Update
phpcs.xmlandphpstan.neon.distto drop UEC exclusions - Confirm
composer run testpasses after removals
Replace provisional mirrors with Ouroboros package imports.
Current gate: sparxstar-ouroboros-integrity must remain installable from the configured Packagist/private VCS source for local and CI validation.
- Add
sparxstar-ouroboros-integritytocomposer.jsonrequire - Delete
src/exceptions/ContextBootException.php(provisional) - Delete
src/dto/ContextPulse.php(provisional) - Update all import statements to use Ouroboros namespace
- Import
AgreementResultenum from Ouroboros (remove any local copy) - Import
ValidationHelperfrom Ouroboros (remove any local copy) - Run
composer run testto confirm no regressions - Confirm Helios and Dheghom are updated to the same Ouroboros version
Target PHPStan Level 7 across the entire
src/tree.
- Resolve all Level 6 findings in
src/core/ - Resolve all Level 6 findings in
src/services/ - Resolve all Level 6 findings in
src/helpers/ - Resolve all Level 6 findings in
src/api/ - Update
phpstan.neon.disttolevel: 6, confirm clean - Repeat for Level 7
Signal pipeline completeness and cross-layer tracing.
- Confirm
SirusSignalEvaluatorcovers all signal types defined in spec - Add structured logging to
TrustEngine(score deltas, reason codes) - Add structured logging to
PulseGenerator(pulse_id, issued_at, expiry) - Add
ConsentManageraudit log integration withSirusEventRepository - Expose
GET /sirus/v1/contextREST endpoint for debug/admin - Add admin UI panel for live trust score and consent status per device
S-07 β Spec Completeness and Helios Integration Readiness (Complete except Ouroboros-blocked VerificationResult import)
Close the spec components that exist in the codegen order (Spec Β§24) but were never built, complete the REST surface Helios consumes, and finish the test coverage S-02 left dangling. Theme: make Sirus a complete, integration-ready producer for the edge.
Status (post PR #88): implementation merged in
main. Every S-07 item is π‘ ("validation pending"). Test, PHPCS, and PHPStan verification is blocked on the CI gate consolidation in S-08 (seeGATE-AUDIT-PAM003.md). The 10 Ouroboros-coupled tests additionally need v2.0shared-test-vectors.jsonand PAM-003 acceptance β those flips wait for S-09.
Prerequisite for the verification items: Ouroboros must export VerificationResult and the canonical PulseVerifier contract. If not yet published, item 1 ships the round-trip test against ContextPulseSigningMaterial only and the enum import is deferred.
P0 β REST surface for Helios (Spec Β§18β19)
- Register
POST /sparxstar/v1/pulseβ request a fresh signedContextPulse(HttpOnly cookie +{ pulse_id, expires_at, trust_level }body); server-to-server / Helios re-verification only, not browser-facing - Register
GET /sparxstar/v1/identityβ resolve current identity tier - Register
GET /sparxstar/v1/sessionβ session status - Register
POST /sparxstar/v1/client-reportβ telemetry/error reporting (never stored in post meta, Β§23) - Integration tests in
tests/integration/RestApiTest.phpcovering all six endpoints
P0 β Pulse generateβverify compatibility (Spec Β§13)
- Add
PulseRoundTripTestβ sign a pulse viaPulseGenerator, confirm it verifies against the canonical Ouroboros signing material (tamper / expiry / malformed cases) - Import
VerificationResultfrom Ouroboros when available β never redefine in Sirus - Do not add runtime verification logic to Sirus (per
.github/instructions/copilot-instructions.md); contradiction resolved βPulseVerifierownership claim removed from that file; it now reads only "Sirus generates, Helios verifies"
P1 β EnvironmentRecord DTO (Spec Β§7, Β§23)
- Build
src/core/EnvironmentRecord.phpwith all spec fields, privacy enforced at construction (IP last-octet zeroed, region-level location only, no exact coords without grant,is_bot,time_zone, brand/model/versions,captured_at) - Client-first (
AGENTS.md): populate the record from client-submitted signals; never derive browser/OS/device by parsing User-Agent β Matomo is fallback/enrichment only - Have
EnvironmentResolverreturn anEnvironmentRecord; keep the existing flat accessors as thin wrappers for backward compat -
EnvironmentResolverTest+EnvironmentRecordTest(privacy invariants asserted at construction; client signals take precedence over UA fallback)
P1 β Close S-02 test debt for built components
-
AuthorityResolverTestβ multi-authority aggregation, most-restrictive conflict outcome (Β§17) -
CapabilityEngineTestβ named capability issuance from context (Β§23 codegen) -
ClientTelemetryTestβ report/aggregation/pruning, no post-meta storage (Β§23)
Acceptance criteria:
composer run testandcomposer run test:unitpass with no failures or deprecationscomposer run analyzeclean at the configured PHPStan level (currently mid-migration to Level 6 per S-05)- All six REST endpoints from Spec Β§18β19 are registered and integration-tested
- No verification runtime added to Sirus;
VerificationResult(if used) is imported from Ouroboros copilot-instructions.mdPulseVerifier ownership contradiction resolved
Consolidate the three divergent quality gates so PHPCS / PHPStan / tests actually report verified state. Until this lands, S-07's π‘ items cannot be flipped to β , and the tracker cannot be honestly refreshed. Scope is governed by
GATE-AUDIT-PAM003.mdΒ§A/Β§B "Actionable now" and the in-repo Engineering Standards file.
Prerequisite: none β this is the unblocker for everything downstream.
Adopted conventions (decided at sprint open):
- Class files: PSR-4 PascalCase (filename matches FQCN), as already enforced by the Composer autoloader. Exclude
WordPress.Files.FileNamefrom the canonical ruleset. - Local variables: camelCase. Exclude
WordPress.NamingConventions.ValidVariableNamefrom the canonical ruleset. - This codifies the convention the autoloader already requires; the rest of the 386/310 PHPCS noise is convention collision, not latent bugs.
P0 β PHPCS gate consolidation (audit Β§A)
- Consolidate to one canonical PHPCS ruleset. Recommendation: keep
phpcs.xml.distas the committed baseline; either gitignorephpcs.xml(true local override per the existing.dist<description>) or delete it. - Unify
testVersionto8.2-across the surviving ruleset andcomposer.jsonplatform (currentlyphpcs.xml=8.1-8.4,phpcs.xml.dist=8.2-). - Exclude
WordPress.Files.FileName(PSR-4 incompatible β by policy, not preference). - Exclude
WordPress.NamingConventions.ValidVariableName(camelCase locals adopted). - Drop
<arg name="ignore-annotations"/>so reviewedphpcs:ignorewaivers work in-line. - Resolve
phpcs.xml.distself-contradiction: its<description>says "To override locally, create aphpcs.xmlfile (gitignored)" butphpcs.xmlis committed and is whatcomposer phpcsruns. - Run
composer lint:fixonce across the tree to clear the whitespace/format residue; commit. - Confirm
composer phpcsandcomposer lintno longer disagree (the 386 vs 310 discrepancy from PR #88).
P0 β Pre-commit gate (audit Β§B)
- Add
lint-staged+husky(orsimple-git-hooks) runningphpcbfthenphpcson staged PHP. - Apply the exit-code-1 guard on
phpcbfβ PHPCBF returns1when it successfully fixed violations; the hook must treat exit code1as success and only fail on exit code2. Use a cross-platform wrapper (e.g., a smallbin/phpcbf-fix.phpscript invoked via a Composer script, or a Node wrapper invoked bylint-staged) rather than a bash-only$?-style guard, which breaks on Windowscmd.exe/ PowerShell. - Document the hook in
CONTRIBUTING.md.
P0 β Un-mask PHPStan
- Run PHPStan as an independent CI job, not after the PHPCS hard-fail, so type drift surfaces. (The audit notes PHPStan is currently invisible because
composer run testshort-circuits on PHPCS.) - Fix or baseline residual findings at the level configured in
phpstan.neon(currently moving from 5 β 6 per S-05).
P1 β Validate S-07 (non-Ouroboros-coupled items only)
With the gate trustworthy, run the suite and flip π‘ β β in this tracker for items not coupled to the Ouroboros v2.0 vectors:
-
EnvironmentRecordDTO,EnvironmentResolverclient-first behavior (EnvironmentRecordTest,EnvironmentResolverTest) - REST
/pulse,/identity,/session,/client-report(integration test asserts success + permission-denied + malformed) -
AuthorityResolverTest,CapabilityEngineTest,ClientTelemetryTest -
copilot-instructions.mdPulseVerifier ownership contradiction resolved (removePulseVerifierfrom the "What this repository owns" list) - Reconcile the
GATE-AUDITcitation of "Engineering Standards Β§6.2" β the in-repo file.github/instructions/sparxstar-coding-standards-v1.mdΒ§6.2 is "GraphQL Resolver Rules", not PSR-4 naming. Either correct the audit reference or supply the actual Engineering-Standards-v1.0 document.
Out of scope (moved to S-09):
- PulseGenerator delegation to Ouroboros's canonical
PulseGenerator::generate()(audit Β§C.4). - Import
VerificationResult,AgreementResult,ValidationHelperfrom Ouroboros. - Rewrite the 10 Ouroboros-coupled tests against
shared-test-vectors.json. - Lock
geo_zoneformat (PAM-002-O3).
Acceptance criteria:
- One PHPCS ruleset is canonical;
composer phpcsandcomposer lintagree on the count. composer run test,composer run lint,composer run analyzeall run independently and report verified status; none is masked by an upstream short-circuit.- A staged PHP file with a fixable violation is corrected by the pre-commit hook and the commit succeeds; an unfixable violation blocks the commit.
- S-07 non-Ouroboros-coupled items are flipped to β in this tracker, with test counts recorded.
copilot-instructions.mdno longer contradicts itself on PulseVerifier ownership.
Finish the cross-repo migration that the gate audit blocks on. Theme: align Sirus with the canonical Ouroboros v2.0 contracts and PAM-003 acceptance, then flip the 10 Ouroboros-coupled S-07 tests to β .
Prerequisites:
- S-08 merged (CI trustworthy).
- Ouroboros v2.0.0
shared-test-vectors.jsonaccessible to this repo's CI (currently the private repo proxy returnsrepository not authorizedperGATE-AUDIT-PAM003.md). - PAM-003 acceptance criteria supplied as a file in this repo (currently referenced by PAM-002, TRACKER, copilot-instructions, and
src/core/*but not present).
Planned scope (full sequencing to be confirmed at sprint open):
- Migrate Sirus's local pulse issuance to Ouroboros's canonical
PulseGenerator::generate()(audit Β§C.4). Signing-material delegation (ContextPulseSigningMaterial::build()) is already done; issuance is the un-migrated half. The composition root issrc/SirusPlugin.php:138; consumers receivePulseGeneratorvia constructor injection (e.g.,SirusRESTController). - Import
VerificationResultenum from Ouroboros (S-07 leftover). - Import
AgreementResultenum from Ouroboros (S-04 leftover). - Import
ValidationHelperfrom Ouroboros (S-04 leftover). - Rewrite the 10 Ouroboros-coupled tests against
shared-test-vectors.jsonβ assertions derived from the spec vectors, never from current code (audit Β§C.1):PulseRoundTripTest,PulseGeneratorTest,SirusContextTest,AuthorityResolverTest,CapabilityEngineTest,StepUpPolicyTest,ContextEngineTest,ContextCacheTest,IdentityResolverTest,NetworkContextBrokerTest. - Lock
geo_zoneformat (PAM-002-O3) β required before PAM-002-P3 ships. - Confirm Sirus's pulse field set still matches PAM-002 Β§3.3 canonical (15 fields including the four PAM-002-P2 restored fields).
- Confirm Helios and Dheghom are pinned to the same Ouroboros version.
Acceptance criteria (preview):
- All 10 Ouroboros-coupled tests flipped to β against v2.0 vectors.
PulseGeneratorissuance routes through Ouroboros; Sirus retains the composition wiring only.- Tracker fully refreshed; S-04 leftover items closed.
- On sprint start β move items from
π²to a named sprint column and assign owners. - On component build β change
π² β π‘and add the file reference. - On test pass β change
π‘ β β. - On Ouroboros ship β execute S-04 and flip provisional items to β .
- On UEC removal β execute S-03 and remove the UEC Legacy rows from this tracker.
Last updated: 2026-08-01 | Spec version: Sirus Context Engine Spec v3.0 + PAM-002