feat: show progress against the direction proof gate - #14
Conversation
… run Add a generated Direction Proof Gate section to the 11/10 Proof Run surface showing approved/recorded/sent Loom progress against 5 and qualified-touch progress against 40, with source and definition text and explicit pending, unknown, and missing states. Counters read only existing repository state: approval rows and recorded Loom URLs in prospects/loom-links.txt, and pipeline touches/sentAt/notes under prospects/<slug>/. Drafts, raw LOOM_URL placeholders, unapproved rows, and prospects without touch evidence never count. Regenerated the tracked surface from a clean tree at the fixed clock date so the deterministic operator-surface gate stays byte-identical, and added a focused fixture test proving the counters.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
📝 WalkthroughWalkthroughThe market proof export now tracks approved, recorded, sent, and qualified-touch Direction Proof Gate metrics. It emits the metrics in Markdown and JSON. An end-to-end harness validates controlled fixtures and edge cases. ChangesDirection Proof Gate
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant LoomLinksSheet
participant ProspectPipeline
participant ExportMarketProofRun
LoomLinksSheet->>ExportMarketProofRun: Provide Loom approval and recording data
ProspectPipeline->>ExportMarketProofRun: Provide sent-proof and touch evidence
ExportMarketProofRun->>ExportMarketProofRun: Calculate Direction Proof Gate metrics
ExportMarketProofRun-->>LoomLinksSheet: Preserve input sheet
ExportMarketProofRun-->>ProspectPipeline: Emit Markdown and JSON proof results
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
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 `@scripts/export-market-proof-run.mjs`:
- Line 335: Update the missing-touch calculation in the export output to clamp
40 minus directionGate.qualifiedTouches at zero using the requested Math.max
behavior, and add a fixture covering more than 40 qualifying touches to verify
no negative count is reported.
- Line 333: Update the pending-recording message in the export output to
accurately describe all rows counted by directionGate.pendingRecording: approved
rows lacking a valid recorded Loom URL, including empty or malformed values.
Either use this broader wording or report raw placeholders and malformed URLs as
separate categories.
- Around line 141-142: Update the referencesLoom logic to inspect only sent
notes and touches, extract URL tokens from their text, and require an exact
token equality with row.loomUrl instead of using substring matching. Add a
fixture covering a different URL that merely contains row.loomUrl as a
substring.
🪄 Autofix
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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 557a4fa5-4423-4bd4-a142-5bb0b25c488f
📒 Files selected for processing (4)
growth-brain/ops/11-10-proof-run.mdpackage.jsonscripts/export-market-proof-run.mjsscripts/test-direction-proof-gate.mjs
| const referencesLoom = notes.some((note) => note?.action === "sent" && String(note.note || "").includes(row.loomUrl)) | ||
| || touches.some((touch) => touch?.action === "sent" && String(touch.note || "").includes(row.loomUrl)); |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Require an exact Loom URL reference.
String.prototype.includes() accepts a different URL that contains row.loomUrl as a substring. It can count invalid sent proof. Extract URL tokens from each sent note or touch, then compare each token to row.loomUrl for equality. Add a near-match fixture.
🤖 Prompt for 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.
In `@scripts/export-market-proof-run.mjs` around lines 141 - 142, Update the
referencesLoom logic to inspect only sent notes and touches, extract URL tokens
from their text, and require an exact token equality with row.loomUrl instead of
using substring matching. Add a fixture covering a different URL that merely
contains row.loomUrl as a substring.
| | Sent Looms | ${directionGate.sentLooms}/5 | recorded Looms whose pipeline has \`sentAt\` plus a sent touch or note naming that exact Loom URL | | ||
| | Qualified touches | ${directionGate.qualifiedTouches}/40 | recorded \`touches\` entries with channel or note evidence in lead-scored prospect pipelines | | ||
|
|
||
| - Pending: ${directionGate.pendingRecording} approved row(s) still carry a raw Loom placeholder and do not count as recorded. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Describe all pending-recording states.
pendingRecording includes every approved row without a valid Loom URL. An empty or malformed URL increases this count, but the generated text says that every pending row has a raw placeholder. State that the row lacks a valid recorded Loom URL, or report placeholder and malformed values separately.
🤖 Prompt for 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.
In `@scripts/export-market-proof-run.mjs` at line 333, Update the
pending-recording message in the export output to accurately describe all rows
counted by directionGate.pendingRecording: approved rows lacking a valid
recorded Loom URL, including empty or malformed values. Either use this broader
wording or report raw placeholders and malformed URLs as separate categories.
|
|
||
| - Pending: ${directionGate.pendingRecording} approved row(s) still carry a raw Loom placeholder and do not count as recorded. | ||
| - Unknown: ${directionGate.recordedWithoutSentProof} recorded Loom(s) have no pipeline sent proof tied to that Loom URL yet. | ||
| - Missing: ${40 - directionGate.qualifiedTouches} qualified touch(es) are still absent; ${directionGate.qualifiedProspectsWithTouches} qualified prospect(s) currently carry touch evidence. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Clamp missing touches at zero.
If qualified touches exceed 40, this output reports a negative missing count. Use Math.max(0, 40 - directionGate.qualifiedTouches) and add a fixture with more than 40 qualifying touches.
🤖 Prompt for 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.
In `@scripts/export-market-proof-run.mjs` at line 335, Update the missing-touch
calculation in the export output to clamp 40 minus
directionGate.qualifiedTouches at zero using the requested Math.max behavior,
and add a fixture covering more than 40 qualifying touches to verify no negative
count is reported.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3138c6e266
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const touches = Array.isArray(pipeline.touches) ? pipeline.touches : []; | ||
| const referencesLoom = notes.some((note) => note?.action === "sent" && String(note.note || "").includes(row.loomUrl)) | ||
| || touches.some((touch) => touch?.action === "sent" && String(touch.note || "").includes(row.loomUrl)); | ||
| return Boolean(pipeline.sentAt) && referencesLoom && Boolean(pipeline.sentChannel || pipeline.lastChannel); |
There was a problem hiding this comment.
Exclude untrusted email sends from the sent-Loom count
When a historical or --force-recorded send uses email while sender setup still has warnings, this predicate counts the Loom as sent. That contradicts the Proof Capture Rules rendered by this same script and check-market-proof-run.mjs, which explicitly rejects email proof until sender trust is clean, so the new direction gate can report progress that the canonical proof check refuses to accept.
Useful? React with 👍 / 👎.
| const approvedRows = loomRows.filter((row) => row.path && existsSync(row.path) && approved(row.approval)); | ||
| const approvedLooms = approvedRows.length; | ||
| const recordedLooms = approvedRows.filter((row) => isValidLoomUrl(row.loomUrl)).length; | ||
| const sentLooms = approvedRows.filter((row) => isValidLoomUrl(row.loomUrl) && sentProofFor(row)).length; |
There was a problem hiding this comment.
Deduplicate Loom rows before counting gate progress
If loom-links.txt contains the same approved row more than once, each copy increments all three Loom counters; five duplicate rows for one sent video therefore display 5/5 approved, recorded, and sent. Because this file is manually maintained and the gate is stated in terms of Looms rather than rows, count distinct prospect/Loom evidence instead of raw rows to prevent duplicate entries from satisfying the proof gate.
Useful? React with 👍 / 👎.
| .sort((a, b) => a.weight - b.weight || a.name.localeCompare(b.name)) | ||
| .slice(0, limit); | ||
|
|
||
| const directionGate = directionGateCounts( |
There was a problem hiding this comment.
Compute progress after merging generated sheet rows
When the sheet is missing or does not yet contain a newly selected recording-batch prospect, the gate is calculated from the old sheet here, but the command later appends approved placeholder rows before returning. The generated report and JSON can consequently say 0 approved and 0 pending while the resulting repository state contains up to five approved pending rows; rerunning the command changes the counters without any new evidence.
Useful? React with 👍 / 👎.
|
|
||
| - Pending: ${directionGate.pendingRecording} approved row(s) still carry a raw Loom placeholder and do not count as recorded. | ||
| - Unknown: ${directionGate.recordedWithoutSentProof} recorded Loom(s) have no pipeline sent proof tied to that Loom URL yet. | ||
| - Missing: ${40 - directionGate.qualifiedTouches} qualified touch(es) are still absent; ${directionGate.qualifiedProspectsWithTouches} qualified prospect(s) currently carry touch evidence. |
There was a problem hiding this comment.
Clamp the missing-touch count at zero
Once the pipeline records more than 40 qualified touches, this subtraction renders values such as Missing: -1 qualified touch(es) are still absent. Continued outreach after satisfying the gate is a normal state, so the operator surface should report zero missing touches rather than a negative deficit.
Useful? React with 👍 / 👎.
Intended outcome
Make the 5-approved/recorded/sent Loom and 40-qualified-touch proof gate visible on the generated operator surface without inventing evidence or sending outreach.
What changed
Verify
npm test— 126 checks passednpm run ci— 126 checks passedsgscan— no new security findingsgit diff --check— passedCo-Authored-By: Claude noreply@anthropic.com
Summary by CodeRabbit
New Features
Documentation
Tests