Skip to content

feat(apply): add preflight liveness and role-match gate#887

Merged
santifer merged 4 commits into
santifer:mainfrom
luochen211:codex/apply-preflight-gate
Jun 11, 2026
Merged

feat(apply): add preflight liveness and role-match gate#887
santifer merged 4 commits into
santifer:mainfrom
luochen211:codex/apply-preflight-gate

Conversation

@luochen211

@luochen211 luochen211 commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add an explicit Step 0 preflight gate to apply mode before drafting form answers.
  • Require liveness checks when a URL is available and stop on closed postings unless the user explicitly overrides.
  • Require an explicit user decision when the visible company/title materially differs from the matched report.
  • Add mode integrity coverage so the gate cannot silently disappear.

Fixes #885

Tests

  • node --check test-all.mjs
  • node test-all.mjs --quick — 166 passed, 0 failed, 7 existing README.ua personal-data warnings

Summary by CodeRabbit

  • Documentation

    • Added "Step 5 — Preflight gate" to the application workflow to verify posting liveness, confirm company/role match with the loaded report, halt on material mismatches, and refuse final copy generation for closed postings unless explicitly overridden by the user
    • Tightened role-change behavior to only adapt responses after the candidate explicitly accepts a mismatch
  • Tests

    • Added integrity checks that assert the workflow docs include the required preflight and liveness/role-match safeguards

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 97fbdffd-e756-4799-9220-a10aeabbf920

📥 Commits

Reviewing files that changed from the base of the PR and between f3ac568 and 520d29c.

📒 Files selected for processing (2)
  • modes/apply.md
  • test-all.mjs

📝 Walkthrough

Walkthrough

Adds "Step 5 — Preflight gate" to apply mode that verifies visible URL/page title/company/role, optionally checks liveness with Playwright, enforces stop-and-ask for material mismatches, refuses final-copy drafting for closed postings unless overridden, tightens role-adapt acceptance, and renumbers subsequent steps.

Changes

Apply Mode Preflight Gate

Layer / File(s) Summary
PREFLIGHT gate and role/company checks
modes/apply.md
Adds "Step 5 — Preflight gate" after detection/identification/search/load that verifies the active form via visible URL/page title and Playwright liveness/closed-signals when available, confirms a matching report has been loaded, stops for user decision on material company/role mismatches, refuses to generate final copy when posting appears closed unless explicitly overridden, provides fallback instructions when liveness cannot be verified from pasted/screenshot inputs, and requires explicit candidate acceptance before adapting responses to a changed role.
Mode file integrity test
test-all.mjs
Adds an assertion that reads modes/apply.md and fails unless it contains the full set of expected liveness/role-match preflight gate text fragments (the "Step 5 — Preflight gate" heading, "verify liveness with Playwright", "matching report has been loaded", the "Do not continue to Step 6…" continuation restriction, and the "refuse to generate final copy" refusal line).
sequenceDiagram
  participant User
  participant ApplyMode
  participant PlaywrightChecker
  participant ReportLoader
  User->>ApplyMode: start apply flow (URL/paste/screenshot)
  ApplyMode->>PlaywrightChecker: verify liveness / closed-signals (when available)
  PlaywrightChecker-->>ApplyMode: liveness/closed result
  ApplyMode->>ReportLoader: ensure matching report has been loaded (company/role)
  ReportLoader-->>ApplyMode: report metadata
  ApplyMode->>User: show preflight summary and ask decision (accept/adapt/override/abort)
  User-->>ApplyMode: decision (confirm proceed / accept role-change / override closed / stop)
Loading

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels: 📄 docs

🚥 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 a preflight liveness and role-match gate to apply mode, which is the primary objective.
Linked Issues check ✅ Passed The PR implementation meets all coding requirements from issue #885: preflight gate with liveness checks, role-match comparison, explicit user decision prompts, and mode integrity tests added.
Out of Scope Changes check ✅ Passed All changes are scoped to the preflight gate objective: modes/apply.md workflow documentation and test-all.mjs integrity test additions align with PR scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@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: 2

🤖 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 `@modes/apply.md`:
- Around line 13-22: The PREFLIGHT step is shown first but depends on a matched
report found during SEARCH; update the workflow so execution order is clear by
either (A) moving "PREFLIGHT" after "SEARCH" in the numbered list or (B) keeping
it as a logical gate and adding an explicit note that PREFLIGHT runs after
DETECT→IDENTIFY→SEARCH using the matched report; also replace numeric references
in the prose (e.g., "Do not continue to Step 4") with descriptive step names
like "LOAD" or "Analyze form questions" (referencing DETECT, IDENTIFY, SEARCH,
PREFLIGHT, LOAD, COMPARE, ANALYZE, GENERATE, PRESENT) so the gate/sequence is
unambiguous.
- Line 18: The document duplicates the role-mismatch gating between "Step 0
(Preflight)", the "COMPARE" bullet, and "Step 3", causing ambiguity about when
each check runs and what happens after user decisions; update the prose to
clearly state whether COMPARE is the same gate as Preflight or the Step 3
detection, consolidate duplicated wording into a single canonical description,
and add a short sentence explaining sequencing and outcomes (e.g.,
"Preflight/COMPARE: initial visible company/role check that stops for user
decision; if the user accepts/overrides, continue to Step 3; Step 3: re-check
for subsequent changes and decide adapt vs re-evaluate") so readers can find one
authoritative rule for initial vs later mismatch handling.
🪄 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: d3038eba-3db7-4166-9740-ec352fe8dbf6

📥 Commits

Reviewing files that changed from the base of the PR and between 214f5f8 and 264dd19.

📒 Files selected for processing (2)
  • modes/apply.md
  • test-all.mjs

Comment thread modes/apply.md Outdated
Comment thread modes/apply.md Outdated
@luochen211

Copy link
Copy Markdown
Contributor Author

Fixed the valid CodeRabbit feedback about the preflight execution order. The workflow now runs DETECT/IDENTIFY/SEARCH/LOAD before the preflight gate, and the gate explicitly states it runs after the matching report is loaded and blocks Step 6 answer analysis/generation until resolved. Updated the mode integrity test to guard the clarified wording.\n\nValidation: node --check test-all.mjs; node test-all.mjs --quick (166 passed, 0 failed, existing README.ua warnings only).

@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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
test-all.mjs (1)

410-421: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Test does not verify section heading uniqueness.

The integrity test checks that required text fragments exist in modes/apply.md, but it does not verify that section headings are unique. As a result, it passes despite the duplicate "Step 5" heading in the documentation (lines 23 and 77 of apply.md).

Consider adding a check to ensure each step number appears exactly once in section headings.

🧪 Proposed enhancement to catch duplicate headings
 const applyMode = readFile('modes/apply.md');
 if (
   applyMode.includes('## Step 5 — Preflight gate') &&
   applyMode.includes('verify liveness with Playwright') &&
   applyMode.includes('matching report has been loaded') &&
   applyMode.includes('Do not continue to Step 6 until this preflight is resolved') &&
   applyMode.includes('refuse to generate final copy')
 ) {
   pass('apply mode includes liveness and role-match preflight gate');
 } else {
   fail('apply mode missing liveness/role-match preflight gate');
 }
+
+// Check for duplicate step headings
+const stepHeadings = applyMode.match(/^## Step \d+/gm) || [];
+const stepNumbers = stepHeadings.map(h => h.match(/\d+/)[0]);
+const uniqueSteps = new Set(stepNumbers);
+if (stepNumbers.length === uniqueSteps.size) {
+  pass('apply mode has unique step numbers');
+} else {
+  fail(`apply mode has duplicate step numbers: ${stepNumbers.join(', ')}`);
+}
🤖 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 `@test-all.mjs` around lines 410 - 421, The test currently only checks for
substring presence in applyMode (from readFile) and misses duplicate section
headings; update the test logic (around the applyMode variable and the existing
pass/fail check) to parse the headings (e.g., using a regex for "## Step
<number>") and assert each step number appears exactly once, failing via
fail(...) if any step number has a count !== 1 so duplicate "Step X" headings
are detected.
modes/apply.md (1)

56-63: ⚠️ Potential issue | 🟠 Major

Clarify overlap and numbering between Step 5 preflight gate and Step 3 role-change handling in modes/apply.md.

  • Step 5 — Preflight gate (lines 23-37) already compares visible company/role vs the matched report and, on material change, asks re-evaluate vs adapt-with-mismatch vs stop before drafting.
  • Step 3 — Detect changes in the role (lines 56-62) repeats the same role-mismatch handling (adapt vs re-evaluate, regenerate Section G, update applications.md).
  • Align sequencing/step numbering: the workflow lists preflight as step 5 after load (lines 12-21), but the doc places “Step 5 — Preflight gate” before “Step 1”, and also reuses “Step 5” for “Generate responses” (lines 77-85). Make clear when each mismatch check runs and whether either one is redundant or intended for different mismatch types/timing.
🤖 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 `@modes/apply.md` around lines 56 - 63, The document duplicates and misorders
role-mismatch logic between "Step 5 — Preflight gate" and "Step 3 — Detect
changes in the role", causing confusion about when to ask adapt vs re-evaluate
and when to update applications.md and regenerate Section G; consolidate and
clarify by (1) explicitly stating that the Preflight gate (the check in "Step 5
— Preflight gate") is the initial, pre-draft materiality check run immediately
after load/visibility and that it prompts re-evaluate vs adapt-with-mismatch vs
stop, (2) redefining "Step 3 — Detect changes in the role" to cover only
mid-session role changes detected during interaction (or remove it if
redundant), explain that only mid-session changes trigger
adapt-with-candidate-consent or a full A–F re-evaluation and Section G
regeneration, and (3) renumber the steps so they appear in logical order (load →
preflight → drafting → generate responses) and update any references to "Step 5"
used elsewhere (including the "Generate responses" section) to the new numbering
and explicitly reference applications.md and Section G in the relevant step so
it's clear when to update those artifacts.
♻️ Duplicate comments (1)
modes/apply.md (1)

37-37: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Clarify the blocking reference to avoid ambiguity.

"Do not continue to Step 6 until this preflight is resolved" is ambiguous because:

  • The section heading "## Step 6 — Post-apply" appears at line 111
  • The workflow item 6. ANALYZE appears at line 18

The intended meaning is to block workflow item 6 (ANALYZE) and item 7 (GENERATE), but the numeric reference could be misread as blocking only the "Post-apply" section.

✏️ Suggested clarification
-Do not continue to Step 6 until this preflight is resolved.
+Do not continue to answer analysis and generation (ANALYZE/GENERATE) until this preflight is resolved.
🤖 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 `@modes/apply.md` at line 37, Replace the ambiguous sentence "Do not continue
to Step 6 until this preflight is resolved." with an explicit blocking reference
that calls out the workflow items by number and name (e.g., "Do not continue to
workflow item 6 (ANALYZE) or workflow item 7 (GENERATE) until this preflight is
resolved.") so readers cannot confuse it with the "## Step 6 — Post-apply"
heading or any other section; update the line containing that sentence
accordingly.
🤖 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 `@modes/apply.md`:
- Line 23: The document has two identical headings "## Step 5 — Preflight gate"
and "## Step 5 — Generate responses"; rename the later heading "## Step 5 —
Generate responses" and all subsequent step headings to increment their step
numbers (e.g., change "## Step 5 — Generate responses" to "## Step 6 — Generate
responses" and bump following steps accordingly) so the sequence is unique and
sequential; update any internal references or cross-links that mention the old
step numbers to match the new numbering.

---

Outside diff comments:
In `@modes/apply.md`:
- Around line 56-63: The document duplicates and misorders role-mismatch logic
between "Step 5 — Preflight gate" and "Step 3 — Detect changes in the role",
causing confusion about when to ask adapt vs re-evaluate and when to update
applications.md and regenerate Section G; consolidate and clarify by (1)
explicitly stating that the Preflight gate (the check in "Step 5 — Preflight
gate") is the initial, pre-draft materiality check run immediately after
load/visibility and that it prompts re-evaluate vs adapt-with-mismatch vs stop,
(2) redefining "Step 3 — Detect changes in the role" to cover only mid-session
role changes detected during interaction (or remove it if redundant), explain
that only mid-session changes trigger adapt-with-candidate-consent or a full A–F
re-evaluation and Section G regeneration, and (3) renumber the steps so they
appear in logical order (load → preflight → drafting → generate responses) and
update any references to "Step 5" used elsewhere (including the "Generate
responses" section) to the new numbering and explicitly reference
applications.md and Section G in the relevant step so it's clear when to update
those artifacts.

In `@test-all.mjs`:
- Around line 410-421: The test currently only checks for substring presence in
applyMode (from readFile) and misses duplicate section headings; update the test
logic (around the applyMode variable and the existing pass/fail check) to parse
the headings (e.g., using a regex for "## Step <number>") and assert each step
number appears exactly once, failing via fail(...) if any step number has a
count !== 1 so duplicate "Step X" headings are detected.

---

Duplicate comments:
In `@modes/apply.md`:
- Line 37: Replace the ambiguous sentence "Do not continue to Step 6 until this
preflight is resolved." with an explicit blocking reference that calls out the
workflow items by number and name (e.g., "Do not continue to workflow item 6
(ANALYZE) or workflow item 7 (GENERATE) until this preflight is resolved.") so
readers cannot confuse it with the "## Step 6 — Post-apply" heading or any other
section; update the line containing that sentence accordingly.
🪄 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: 9ed652c1-50ad-4b2c-962d-fde9a7961659

📥 Commits

Reviewing files that changed from the base of the PR and between 264dd19 and 9ac847d.

📒 Files selected for processing (2)
  • modes/apply.md
  • test-all.mjs

Comment thread modes/apply.md
8. PRESENT → Show formatted responses for copy-paste
```

## Step 5 — Preflight gate

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Critical: Duplicate "Step 5" heading.

The document contains two sections both labeled "Step 5":

  • Line 23: "## Step 5 — Preflight gate"
  • Line 77: "## Step 5 — Generate responses"

When the preflight gate was inserted as Step 5, subsequent sections were not renumbered. This breaks the documentation structure and will confuse users following the workflow.

📝 Proposed fix: renumber subsequent sections
-## Step 5 — Generate responses
+## Step 6 — Generate responses

And update the final section:

-## Step 6 — Post-apply (optional)
+## Step 7 — Post-apply (optional)

Also applies to: 77-77

🤖 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 `@modes/apply.md` at line 23, The document has two identical headings "## Step
5 — Preflight gate" and "## Step 5 — Generate responses"; rename the later
heading "## Step 5 — Generate responses" and all subsequent step headings to
increment their step numbers (e.g., change "## Step 5 — Generate responses" to
"## Step 6 — Generate responses" and bump following steps accordingly) so the
sequence is unique and sequential; update any internal references or cross-links
that mention the old step numbers to match the new numbering.

@luochen211

Copy link
Copy Markdown
Contributor Author

Fixed the new CodeRabbit feedback about duplicate Step 5 headings in apply mode. The preflight gate remains Step 5, and the following sections are now Step 6 (analyze questions) and Step 7 (generate responses), matching the workflow list.

Validation: node test-all.mjs --quick (166 passed, 0 failed, existing README.ua warnings only).

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
modes/apply.md (2)

23-37: 🧹 Nitpick | 🔵 Trivial | ⚖️ Poor tradeoff

Consider reordering sections to match workflow sequence.

The "Step 5 — Preflight gate" heading appears before "Step 1 — Detect the job" (line 39), "Step 2 — Identify and search for context" (line 48), and "Step 3 — Detect changes in the role" (line 56). This document structure (5 → 1 → 2 → 3 → 6 → 7) makes it harder for readers to follow the logical workflow sequence (1 → 2 → 3 → 4 → 5 → 6 → 7 → 8).

Reordering the sections to match the workflow execution sequence would improve readability.

🤖 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 `@modes/apply.md` around lines 23 - 37, The document's section order is out of
sequence (Step 5 appears before Steps 1–3), which breaks the logical workflow;
reorder the headings so the steps read in natural execution order (Step 1 —
Detect the job, Step 2 — Identify and search for context, Step 3 — Detect
changes in the role, Step 4 — ..., Step 5 — Preflight gate, then continue to
Step 6 and Step 7/8). Locate the "Step 5 — Preflight gate" block and move it
after the section titled "Step 4" (or immediately after "Step 3" if Step 4 is
implicit), ensuring all internal numbered items and references remain intact and
any cross-references or "Do not continue to Step 6" notes are updated to reflect
the new ordering.

111-111: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Critical: Duplicate "Step 6" heading.

Line 111 contains "## Step 6 — Post-apply (optional)" but there is already a "## Step 6 — Analyze form questions" at line 64. This creates ambiguous step numbering and will confuse users following the workflow.

📝 Proposed fix
-## Step 6 — Post-apply (optional)
+## Step 8 — Post-apply (optional)
🤖 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 `@modes/apply.md` at line 111, There are two identical step numbers causing
confusion: replace or renumber the duplicate heading "## Step 6 — Post-apply
(optional)" so step ordering is unique; update the heading text (e.g., to "##
Step 7 — Post-apply (optional)" or merge its content into "## Step 6 — Analyze
form questions") and ensure any internal references to "Step 6 — Post-apply
(optional)" are updated accordingly; locate the duplicate by searching for the
headings "## Step 6 — Analyze form questions" and "## Step 6 — Post-apply
(optional)" and change the second heading to the correct sequence or consolidate
content.
🤖 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.

Outside diff comments:
In `@modes/apply.md`:
- Around line 23-37: The document's section order is out of sequence (Step 5
appears before Steps 1–3), which breaks the logical workflow; reorder the
headings so the steps read in natural execution order (Step 1 — Detect the job,
Step 2 — Identify and search for context, Step 3 — Detect changes in the role,
Step 4 — ..., Step 5 — Preflight gate, then continue to Step 6 and Step 7/8).
Locate the "Step 5 — Preflight gate" block and move it after the section titled
"Step 4" (or immediately after "Step 3" if Step 4 is implicit), ensuring all
internal numbered items and references remain intact and any cross-references or
"Do not continue to Step 6" notes are updated to reflect the new ordering.
- Line 111: There are two identical step numbers causing confusion: replace or
renumber the duplicate heading "## Step 6 — Post-apply (optional)" so step
ordering is unique; update the heading text (e.g., to "## Step 7 — Post-apply
(optional)" or merge its content into "## Step 6 — Analyze form questions") and
ensure any internal references to "Step 6 — Post-apply (optional)" are updated
accordingly; locate the duplicate by searching for the headings "## Step 6 —
Analyze form questions" and "## Step 6 — Post-apply (optional)" and change the
second heading to the correct sequence or consolidate content.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: d1a610f4-4e9e-45a0-80b4-9b95b4b575be

📥 Commits

Reviewing files that changed from the base of the PR and between 9ac847d and f3ac568.

📒 Files selected for processing (1)
  • modes/apply.md

…ield contract inside Analyze, preserve preflight step numbering, fix duplicate Step 6 heading
@santifer santifer merged commit 42bb9ab into santifer:main Jun 11, 2026
6 of 7 checks passed
@santifer

Copy link
Copy Markdown
Owner

Merged — this is the airbag the apply flow needed: never draft answers against a dead or mismatched posting, and on ambiguity ask instead of assume. Exactly the human-in-the-loop discipline this project is built on. (Resolved the #821 collision in your branch — the form-field contract now lives inside your renumbered Analyze step.) 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(apply): add preflight liveness and role-match gate before form assistance

2 participants