Skip to content

fix(pilot): reject placeholder or ambiguous readiness evidence - #493

Merged
seonghobae merged 20 commits into
mainfrom
fix/pilot-readiness-placeholder-evidence
Aug 23, 2026
Merged

fix(pilot): reject placeholder or ambiguous readiness evidence#493
seonghobae merged 20 commits into
mainfrom
fix/pilot-readiness-placeholder-evidence

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Fail closed when otherwise-complete pilot-readiness records use documented sample/local markers, local-only or non-routable listener identities, or contradictory duplicate authoritative fields to manufacture commercial completion evidence.

Repair lineage

Earlier test-first repairs on this canonical branch reject sample contract/KPI/trace references, conflicting or malformed duplicate scalar/metric authority, 127/8 and IPv6 loopback, IPv4-mapped loopback, absolute local DNS names, and .local support channels.

This run added a further validated production-identity boundary:

  • RED 61a5263c697b10ad20657b7dc80142d43e92d0aa adds tenant.localhost, 0.0.0.0, and [::] as otherwise-valid production URLs. Its CI/reviewer/Security runs were cancelled when the candidate immediately superseded that head, so cancelled runs are not claimed as terminal RED evidence.
  • Candidate dae9b00df73d69918c104308844d09a96f24fdf0 rejects .localhost descendants plus IPv4/IPv6 unspecified listener identities while preserving private enterprise production networks.
  • After feat(sandbox): restack patch-validator image on current main #407 integrated, non-destructive two-parent convergence cec399a594d92f35b94f1ac07d0323f8d1011a8d rebased no history: it preserves the exact fix(pilot): reject placeholder or ambiguous readiness evidence #493 source/test blobs and incorporates protected main 8ce7c7536888ec0b596e18368eedd9379deec64f as an ancestor.

Buyer boundary

docs/pilot-readiness-log.md classifies example, localhost, and .local values as samples that cannot count toward a completed paid pilot. Loopback, unspecified-listener, and localhost-subdomain endpoints likewise are not externally operable production identities. evaluatePilotReadinessText feeds saleable-readiness-audit, so these identities and duplicate evidence authorities must fail closed rather than manufacture commercial readiness.

Current exact identity and evidence

Exact head: cec399a594d92f35b94f1ac07d0323f8d1011a8d.

Live protected base: 8ce7c7536888ec0b596e18368eedd9379deec64f, exact merge base, behind 0. The live diff remains exactly two files: scripts/lib/pilot-readiness.mjs and its realistic regression test.

Current exact-head evidence:

  • Application CI 32624571418: success
  • reviewer-ci 32624571444: success
  • central Security Scan 32624571424: success
  • dedicated patch-validator-image 32624571471: in progress
  • unresolved review threads: 0

Merge boundary

Keep Draft until every workflow actually triggered for unchanged exact head cec399a... is terminal-success and live base/review/scanner authority are freshly unchanged. Do not reuse predecessor evidence or treat the in-progress dedicated image run as passing. If that run succeeds, re-read exact head/base/threads/central scanner authority, mark Ready, refetch again after the state change, and merge only if no new non-passing evidence appears.

Summary by CodeRabbit

  • 개선 사항

    • 파일럿 준비성 평가에서 핵심 메트릭과 필드의 중복 여부를 자동으로 확인합니다.
    • 로컬 주소, 예시 도메인, 비라우팅 URL 등 유효하지 않은 지원 채널 정보를 더욱 정확히 차단합니다.
    • 분석 경로, 추적 ID, 계약 증빙에 실제로 검증 가능한 참조가 포함되었는지 확인합니다.
  • 버그 수정

    • 중복되거나 비어 있는 값, 샘플·위조 증빙 정보가 준비성 평가를 통과하던 문제를 수정했습니다.

@coderabbitai

coderabbitai Bot commented Aug 23, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: de00c9d6-b6aa-46ff-92f5-d9e7e592691f

📥 Commits

Reviewing files that changed from the base of the PR and between 8ce7c75 and cec399a.

📒 Files selected for processing (2)
  • scripts/lib/pilot-readiness.mjs
  • test/pilot-readiness-placeholder-evidence.test.ts

📝 Walkthrough

Walkthrough

파일럿 준비성 평가기가 중복 필드, 로컬 또는 예시 URL, 지원 채널, 증빙 참조를 검증하도록 강화되었습니다. 관련 실패 사유와 검증 테스트가 추가되었습니다.

Changes

파일럿 준비성 검증

Layer / File(s) Summary
검증 규칙 추가
scripts/lib/pilot-readiness.mjs
메트릭과 필드의 중복 개수를 계산합니다. 루프백, 로컬, .local, 예시 호스트와 문자열을 차단합니다. 사용 가능한 증빙 참조를 검사합니다.
평가 결과 및 테스트 연결
scripts/lib/pilot-readiness.mjs, test/pilot-readiness-placeholder-evidence.test.ts
중복 항목과 부적합한 분석 경로, trace ID, 계약·매출 증빙 경로를 실패 사유로 보고합니다. 예시·로컬 값과 비정상 중복 값을 거부하는 테스트를 추가합니다.

Estimated code review effort: 3 (Moderate) | ~20 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/pilot-readiness-placeholder-evidence

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.

@seonghobae seonghobae changed the title fix(pilot): reject placeholder evidence references fix(pilot): reject placeholder or ambiguous readiness evidence Aug 23, 2026
@seonghobae
seonghobae marked this pull request as ready for review August 23, 2026 10:01
@seonghobae
seonghobae merged commit 3d4ba08 into main Aug 23, 2026
17 of 18 checks passed
@seonghobae
seonghobae deleted the fix/pilot-readiness-placeholder-evidence branch August 23, 2026 10:01

@devin-ai-integration devin-ai-integration 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.

Devin Review found 4 potential issues.

Open in Devin Review

Comment on lines 111 to +112
const failures = [];
for (const [label] of duplicateAuthorities) failures.push(`${label} must appear exactly once`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Behavior change without a changelog entry

These new fail-closed readiness rejection rules change behavior, but no ## Unreleased bullet was added to CHANGELOG.md. The contributor rule requires a changelog entry for every behavior change, and the existing top pilot bullet covers only date/time authority, not placeholder, local, duplicate, or URL evidence.

Prompt for agents
CONTRIBUTING.md and CLAUDE.md require that CHANGELOG.md's `## Unreleased` section be updated with every behavior change. This PR adds new pilot-readiness validation behavior in scripts/lib/pilot-readiness.mjs (rejecting placeholder/example/localhost/.local evidence references, loopback / unspecified-listener / .localhost production URLs, broadened .local support-channel rejection, and duplicate authoritative fields) but adds no corresponding CHANGELOG entry. Add a Korean `## Unreleased` bullet describing this fail-closed hardening, consistent with the surrounding entries.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines 24 to +33
function fieldValue(entry, label) {
const escaped = label.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const match = entry.match(new RegExp(`^-\\s*${escaped}:\\s*(.+)\\s*$`, "m"));
return match ? match[1].trim() : "";
}

function fieldCount(entry, label) {
const escaped = label.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
return [...entry.matchAll(new RegExp(`^-\\s*${escaped}\\s*:`, "gm"))].length;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📝 Info: fieldValue and fieldCount treat pre-colon whitespace differently

fieldValue requires the colon to immediately follow the label, while fieldCount (pilot-readiness.mjs) allows whitespace before it. A line like - 고객명 : Acme is counted but read as empty. This only fails closed and cannot forge a duplicate, so it is not a bug, but the two regexes drifting apart invites future confusion.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines 67 to +81
function isUsableSupportChannel(value) {
const normalized = value.toLowerCase();
return normalized.length > 0
&& !normalized.includes("@noema.local")
&& !normalized.includes(".local")
&& !normalized.includes("example")
&& !normalized.includes("localhost");
}

function isUsableEvidenceReference(value) {
const normalized = value.toLowerCase();
return normalized.length > 0
&& !normalized.includes("example")
&& !normalized.includes("localhost")
&& !normalized.includes(".local");
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📝 Info: Coarse substring matching on sample markers

isUsableEvidenceReference and isUsableSupportChannel reject any value containing .local, example, or localhost as a substring. Real values like a path with .locale or a host like exampletech.com are rejected. This fail-closed broadening matches the documented buyer boundary, but the substring test is coarse and can reject genuine evidence in rare cases.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +39 to +46
function isLocalOnlyHostname(host) {
const normalized = host.startsWith("[") && host.endsWith("]")
? host.slice(1, -1)
: host;
if (normalized === "::" || normalized === "::1" || normalized === "0.0.0.0") return true;
if (/^::ffff:7f[0-9a-f]{2}:[0-9a-f]{1,4}$/i.test(normalized)) return true;
return /^127(?:\.\d{1,3}){3}$/.test(normalized);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📝 Info: IPv4-mapped loopback match depends on URL hex serialization

The IPv4-mapped loopback regex matches the bracket-stripped host, relying on the URL parser serializing [::ffff:127.0.0.2] to hex ::ffff:7f00:2 rather than dotted-quad. WHATWG URL does emit hex pieces, so the tested cases pass and the regex covers all of 127.0.0.0/8. Correct, but the coverage rests on serializer behavior.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

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