Skip to content

docs: Plan 6 — network score computation - #11

Merged
messagesgoel-blip merged 6 commits into
mainfrom
docs/plan-6-network-score-computation
Jul 29, 2026
Merged

docs: Plan 6 — network score computation#11
messagesgoel-blip merged 6 commits into
mainfrom
docs/plan-6-network-score-computation

Conversation

@messagesgoel-blip

@messagesgoel-blip messagesgoel-blip commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Add docs/superpowers/plans/2026-07-28-network-score-computation.md for productization §13 step 10
  • Refresh HANDOVER.md to mark Plans 1–5 done and Plan 6 ready (PR A/B split)
  • Locked: in-process 60s debounce + hourly tick; live gRPC RunVeriRank; Verify stays in-process Node; scores + sync_events in one TX

Test plan

  • Docs-only review — no runtime change
  • Confirm plan matches design §4.5 / §13 item 10
  • Approve to start implementation (PR A then PR B)

@coderabbitai review

Summary by CodeRabbit

  • Documentation
    • Added a detailed implementation plan for network score computation, including scoring, synchronization, scheduling, filtering, and verification requirements.
    • Updated project handover documentation with the current plan status, execution guidance, next steps, and key documentation references.

Lock step-10 scope (loader, RunVeriRank gRPC, transactional score/sync writes, in-process debounce) and point HANDOVER at execution.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@cursor

cursor Bot commented Jul 28, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 26 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: b188db7c-7f1e-43f6-8bef-0277dfc838a5

📥 Commits

Reviewing files that changed from the base of the PR and between a8b07e6 and 7bd7f95.

📒 Files selected for processing (2)
  • docs/superpowers/plans/2026-07-28-network-score-computation.md
  • docs/superpowers/plans/HANDOVER.md

Walkthrough

The pull request adds a detailed Plan 6 document for network score computation and updates the project handover with its execution status, implementation scope, verification requirements, follow-on ordering, and key-file reference.

Changes

Network score computation planning

Layer / File(s) Summary
Plan 6 scope and execution model
docs/superpowers/plans/2026-07-28-network-score-computation.md
Defines score materialization, transactional sync events, filtering rules, recomputation scheduling, implementation tasks, verification steps, out-of-scope work, and a suggested PR split.
Execution handover updates
docs/superpowers/plans/HANDOVER.md
Marks Plan 6 as drafted and ready to execute, records its implementation approach and follow-on ordering, and adds the plan document to the key files table.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding Plan 6 documentation for network score computation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/plan-6-network-score-computation

Comment @coderabbitai help to get the list of available commands.

Co-authored-by: Cursor <cursoragent@cursor.com>
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Document Plan 6 network score computation

📝 Documentation 🕐 10-20 Minutes

Grey Divider

AI Description

• Defines Plan 6 architecture, invariants, tasks, and verification for network score computation.
• Locks gRPC scoring, transactional sync writes, and in-process recompute scheduling.
• Advances handover status and recommends a two-PR implementation sequence.
Diagram

graph TD
  INGEST["Attestation Ingest"] --> SCHED["Recompute Scheduler"] --> LOAD["Graph Loader"] --> GRPC["RunVeriRank gRPC"] --> WRITE["Score Writer"] --> SCORES[("Score Tables")]
  WRITE --> EVENTS[("Sync Events")]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Durable distributed scheduler
  • ➕ Survives process restarts without losing dirty state
  • ➕ Supports multiple control-plane instances safely
  • ➕ Provides centralized retries and job observability
  • ➖ Introduces Redis or another queue dependency before deployment requires it
  • ➖ Adds coordination, operations, and failure modes to the initial implementation
  • ➖ Expands Plan 6 beyond productization step 10

Recommendation: Use the planned in-process scheduler for the current single-node control plane while keeping recomputation idempotent and lifecycle wiring explicit. Move to a durable distributed queue when multi-instance deployment becomes necessary; live gRPC should remain the scoring boundary to avoid duplicating VeriRank in TypeScript.

Files changed (2) +172 / -13

Documentation (2) +172 / -13
2026-07-28-network-score-computation.mdDefine the Plan 6 network score computation roadmap +157/-0

Define the Plan 6 network score computation roadmap

• Adds the implementation plan for loading the active attestation graph, invoking RunVeriRank over gRPC, and transactionally persisting score changes with sync events. It locks scheduler behavior, grouping rules, retries, migration requirements, test coverage, exclusions, and the proposed PR split.

docs/superpowers/plans/2026-07-28-network-score-computation.md

HANDOVER.mdAdvance the handover to Plan 6 execution +15/-13

Advance the handover to Plan 6 execution

• Marks Plans 1–5 complete, records the latest main revision, and directs the next session to execute Plan 6. It summarizes the locked architecture, recommended PR A/B split, and subsequent productization steps.

docs/superpowers/plans/HANDOVER.md

@qodo-code-review

qodo-code-review Bot commented Jul 28, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 18 rules

Grey Divider


Action required

1. Permitted weights break recomputation ✓ Resolved 🐞 Bug ☼ Reliability
Description
The loader will stream persisted weights directly, but both database columns permit values above 1
while RunVeriRank rejects weights outside [0,1]. A database-valid value such as 1.01 therefore
makes every recomputation fail and leaves the last-good table stale.
Code

docs/superpowers/plans/2026-07-28-network-score-computation.md[R86-87]

+- Issuer `trust_weight` / `is_bootstrap` from `issuers`
+- Roots from `bootstrap_issuers.current_weight`
Relevance

⭐⭐⭐ High

PR #4 accepted database bounds checks and consistent weight-domain constraints.

PR-#4

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Both persisted weight columns have only a lower-bound check, and createIssuer forwards an
arbitrary supplied value. The gRPC server explicitly rejects principal and root weights greater than
one, so the newly planned direct mapping activates an incompatibility already permitted by the
database.

control-plane/migrations/001_graph/migration.sql[39-42]
control-plane/migrations/003_sync/migration.sql[18-22]
control-plane/src/domains/principal/principalRepository.ts[154-164]
internal/trustengine/service.go[100-127]
docs/superpowers/plans/2026-07-28-network-score-computation.md[84-87]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Add migration and loader requirements enforcing inclusive `[0,1]` bounds for issuer trust weights and bootstrap root weights. Validate existing rows during migration and fail with a clear diagnostic rather than repeatedly submitting invalid gRPC requests.

## Issue Context
Current constraints only enforce non-negativity, and the issuer repository accepts arbitrary numeric weights. The trust-engine server rejects both principal and root weights above one.

## Fix Focus Areas
- docs/superpowers/plans/2026-07-28-network-score-computation.md[84-87]
- control-plane/migrations/001_graph/migration.sql[39-42]
- control-plane/migrations/003_sync/migration.sql[18-22]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Expired attestations remain active ✓ Resolved 🐞 Bug ≡ Correctness
Description
The plan makes expiration filtering optional, but RunVeriRank does not exclude expired claims when
constructing graph edges. Following the plan literally can preserve trust or blacklist effects until
the 1800-day cutoff instead of the attestation's expiry.
Code

docs/superpowers/plans/2026-07-28-network-score-computation.md[39]

+   - Prefer excluding clearly expired rows where `expires_at IS NOT NULL AND expires_at <= evaluation_time`
Relevance

⭐⭐⭐ High

PR #6 accepted analogous expiry enforcement preventing inactive credentials from remaining usable.

PR-#6

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The authoritative design requires the active attestation set, while RunVeriRank's edge construction
only checks and clamps IssuedAt before appending every claim. Although the proto conversion
carries ExpiresAt, the engine never tests it, making loader-side exclusion necessary.

docs/superpowers/plans/2026-07-28-network-score-computation.md[36-39]
docs/superpowers/specs/2026-07-25-verilink-productization-design.md[216-221]
internal/trustengine/service.go[221-226]
pkg/trust/engine.go[185-204]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Make expiration filtering mandatory when loading the active attestation graph. Exclude every row whose non-null `expires_at` is less than or equal to the recomputation's evaluation time.

## Issue Context
The trust engine retains `expires_at` in claims but does not consult it while constructing edges, so the control plane must enforce expiry before streaming attestations. Use the same explicit evaluation time for expiration and age-cutoff predicates.

## Fix Focus Areas
- docs/superpowers/plans/2026-07-28-network-score-computation.md[36-39]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Allocator lock ends prematurely ✓ Resolved 🐞 Bug ☼ Reliability
Description
Reusing the existing session-level advisory-lock pattern in appendEventWithClient would release
the lock before the outer score transaction commits. A concurrent allocator can then observe the old
maximum, select the same sync_version, and fail or violate the required commit ordering.
Code

docs/superpowers/plans/2026-07-28-network-score-computation.md[91]

+- Advisory lock for sync version allocation (reuse `8392018` or dedicated lock; document)
Relevance

⭐⭐ Medium

PR #4 partially accepted transaction-scoped locking for atomic sync-version allocation.

PR-#4

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The current repository acquires pg_advisory_lock, allocates MAX(sync_version)+1, and explicitly
unlocks before its callback returns. withTransaction commits only after that callback resolves,
leaving a window where another session holds the allocator lock but cannot see the uncommitted
version; the design requires allocation ordering to cover commit.

docs/superpowers/plans/2026-07-28-network-score-computation.md[90-93]
control-plane/src/domains/sync/syncRepository.ts[18-33]
control-plane/src/db/transaction.ts[11-24]
docs/superpowers/specs/2026-07-25-verilink-productization-design.md[348-350]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Require the sync-version allocator lock to remain held through the transaction's commit. Implement this with `pg_advisory_xact_lock` or an equivalent allocator whose serialization lifetime covers commit, and add a concurrent-writer integration test.

## Issue Context
The existing allocator unlocks inside the transaction callback, before `withTransaction` issues `COMMIT`. Directly extracting that behavior into `appendEventWithClient` is unsafe for score-writer transactions.

## Fix Focus Areas
- docs/superpowers/plans/2026-07-28-network-score-computation.md[90-94]
- control-plane/src/domains/sync/syncRepository.ts[13-33]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (3)
4. Recomputes can regress scores ✓ Resolved 🐞 Bug ☼ Reliability
Description
The debounce and hourly triggers can call recomputeNow concurrently because the plan defines no
single-flight or stale-result guard. An older graph snapshot that finishes last can overwrite or
delete results produced by a newer run, even if writer transactions themselves are serialized.
Code

docs/superpowers/plans/2026-07-28-network-score-computation.md[R104-105]

+- Debounce timer coalesces bursts
+- Hourly interval always calls `recomputeNow`
Relevance

⭐⭐ Medium

Repository accepts concurrency hardening, but no historical finding covers overlapping score
recomputations.

PR-#4
PR-#6

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The plan creates two independent scheduling paths but specifies no mutual exclusion for the complete
recomputation. RunVeriRank output depends on the supplied evaluation time, while graph loading also
happens before the writer lock, so commit serialization alone cannot stop an older computation from
applying after a newer one.

docs/superpowers/plans/2026-07-28-network-score-computation.md[30-33]
docs/superpowers/plans/2026-07-28-network-score-computation.md[96-106]
pkg/trust/engine.go[172-206]
pkg/trust/engine.go[270-279]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Define scheduler-wide single-flight semantics across ingest and hourly triggers. If the graph becomes dirty during an active run, coalesce it into exactly one follow-up run; also test an hourly tick racing with a debounced run.

## Issue Context
Serializing only score-writer transactions does not order the graph snapshots or evaluation times used before those transactions. The full load, engine call, and apply sequence needs stale-result protection.

## Fix Focus Areas
- docs/superpowers/plans/2026-07-28-network-score-computation.md[30-33]
- docs/superpowers/plans/2026-07-28-network-score-computation.md[96-106]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Empty roots preserve scores ✓ Resolved 🐞 Bug ≡ Correctness
Description
Returning when bootstrap_issuers is empty bypasses the absent-result deletion pass, so removing
the final root leaves all previously computed scores indefinitely. With no roots the engine would
produce no propagated rows, which should cause score deletions and corresponding sync events.
Code

docs/superpowers/plans/2026-07-28-network-score-computation.md[44]

+8. **Missing bootstrap rows:** if no `bootstrap_issuers`, recompute is a no-op success (log warn) — cold-start seed is step 14.
Relevance

⭐⭐ Medium

No directly relevant history on empty-root recomputation or deleting stale scores.

PR-#1

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The engine seeds scores solely from the provided roots and outputs rows from that resulting map. The
plan simultaneously requires deletion of previous rows absent from engine output but skips the
engine and writer entirely when roots are empty.

docs/superpowers/plans/2026-07-28-network-score-computation.md[43-47]
docs/superpowers/plans/2026-07-28-network-score-computation.md[96-100]
pkg/trust/engine.go[230-233]
pkg/trust/engine.go[301-337]
docs/superpowers/specs/2026-07-25-verilink-productization-design.md[337-343]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Replace the unconditional empty-bootstrap no-op with behavior that distinguishes a pristine cold start from removal of existing roots. If materialized scores exist and the root set becomes empty, transactionally delete them and emit `score.delete` events.

## Issue Context
The engine initializes its score map exclusively from roots. Returning before diff/apply prevents stale score revocation after the final root is removed.

## Fix Focus Areas
- docs/superpowers/plans/2026-07-28-network-score-computation.md[43-47]
- docs/superpowers/plans/2026-07-28-network-score-computation.md[96-100]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Entity-kind changes emit nothing ✓ Resolved 🐞 Bug ≡ Correctness
Description
The change predicate excludes entity_kind even though it is part of each materialized score and
sync snapshot. A kind-only update can change network_scores without emitting score.upsert,
leaving incremental-sync consumers with stale identity metadata.
Code

docs/superpowers/plans/2026-07-28-network-score-computation.md[46]

+   - Engine row present → upsert `network_scores`; if score/blacklist/reason changed vs previous → insert `network_score_history` + `score.upsert` event
Relevance

⭐⭐ Medium

PR #4 partially accepted entity-kind consistency fixes, but no direct score-event precedent exists.

PR-#4

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The score snapshot exposes entity_kind, principals can be updated independently, and the engine
stamps the current kind onto every output row. The plan's explicit three-field comparison omits that
consumer-visible value.

docs/superpowers/plans/2026-07-28-network-score-computation.md[45-47]
control-plane/src/domains/sync/syncService.ts[5-13]
control-plane/src/domains/principal/principalRepository.ts[175-185]
internal/trustengine/service.go[190-208]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Include `entity_kind` and every other consumer-visible score field in the event change predicate. Add a test where a principal changes kind while score, blacklist status, and reason remain unchanged, and assert `score.upsert` is emitted.

## Issue Context
The engine stamps current principal kinds into score rows, and snapshots expose that field. Limiting event detection to numeric score, blacklist, and reason allows snapshot and incremental state to diverge.

## Fix Focus Areas
- docs/superpowers/plans/2026-07-28-network-score-computation.md[45-47]
- docs/superpowers/plans/2026-07-28-network-score-computation.md[90-94]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread docs/superpowers/plans/2026-07-28-network-score-computation.md Outdated
Comment thread docs/superpowers/plans/2026-07-28-network-score-computation.md Outdated
Comment thread docs/superpowers/plans/2026-07-28-network-score-computation.md Outdated
Comment thread docs/superpowers/plans/2026-07-28-network-score-computation.md Outdated
Comment thread docs/superpowers/plans/2026-07-28-network-score-computation.md Outdated
Comment thread docs/superpowers/plans/2026-07-28-network-score-computation.md Outdated
Address PR #11 review: mandatory expires_at/active-principal filters with one evaluationTime, pg_advisory_xact_lock through commit, single-flight dirty latch, entity_kind in change detection, and mandatory live RunVeriRank CI in PR B.

Co-authored-by: Cursor <cursoragent@cursor.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/superpowers/plans/2026-07-28-network-score-computation.md`:
- Line 72: Add a blank line immediately after each Markdown heading in the newly
added documentation sections, including all headings corresponding to the listed
locations, so the document conforms to MD022.
- Around line 54-59: Update the missing-bootstrap handling in the recompute flow
so it does not leave previously materialized scores when eligible bootstrap
roots disappear. Restrict the no-op success path to an initial empty score
state, or transactionally remove all existing network scores and emit the
corresponding score.delete events before returning; preserve the existing
warning and cold-start behavior.
- Line 35: Resolve the conflicting shutdown contract in the scheduler plan:
choose one deterministic behavior for an active recompute with a pending dirty
rerun, then update the shutdown requirements and related scheduler/tests
consistently. Ensure the contract explicitly defines timer cancellation,
active-run awaiting, and whether the dirty rerun is drained or discarded.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 544f197d-d619-4627-b2e9-941d25883c7c

📥 Commits

Reviewing files that changed from the base of the PR and between 2f7ed92 and a8b07e6.

📒 Files selected for processing (2)
  • docs/superpowers/plans/2026-07-28-network-score-computation.md
  • docs/superpowers/plans/HANDOVER.md

Comment thread docs/superpowers/plans/2026-07-28-network-score-computation.md Outdated
Comment thread docs/superpowers/plans/2026-07-28-network-score-computation.md Outdated
Comment thread docs/superpowers/plans/2026-07-28-network-score-computation.md
Sanjay and others added 2 commits July 28, 2026 21:26
Empty-roots clears stale scores; weight [0,1] migration; entity_kind on history; deterministic shutdown drain; MD022 spacing; HANDOVER date 2026-07-29.

Co-authored-by: Cursor <cursoragent@cursor.com>
Bump Updated date to 2026-07-29 and sync locked decisions with empty-roots clear, weight bounds, history entity_kind, and shutdown drain.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add a review-closure matrix for human/CodeRabbit/Qodo comments; require API [0,1] weight validation; use blacklisted/score_reason; clarify deletes emit score.delete without history rows.

Co-authored-by: Cursor <cursoragent@cursor.com>
@messagesgoel-blip

Copy link
Copy Markdown
Collaborator Author

Review findings closed (recommit)

Audited all present/past PR comments (human chat reviews, CodeRabbit CHANGES_REQUESTED → APPROVED, Qodo 6 bugs) and recommitted Plan 6 with an explicit Review findings closure matrix.

Also tightened:

  • Change predicate field names → score / blacklisted / score_reason / entity_kind (match schema)
  • Deletes → score.delete only (no history row)
  • Weight [0,1] at DB migration + createIssuer/bootstrap writers
  • Empty-roots cold-start vs stale-clear (already locked)

HEAD: after this push. Please re-approve if needed.

@messagesgoel-blip
messagesgoel-blip merged commit 232e409 into main Jul 29, 2026
5 checks passed
@messagesgoel-blip
messagesgoel-blip deleted the docs/plan-6-network-score-computation branch July 29, 2026 02:53
@coderabbitai coderabbitai Bot mentioned this pull request Jul 29, 2026
2 tasks
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.

1 participant