feat(integration): add versioned naruon rehearsal handoff - #737
feat(integration): add versioned naruon rehearsal handoff#737seonghobae wants to merge 74 commits into
Conversation
📝 WalkthroughWalkthroughBandScope에 naruon rehearsal handoff v1 계약을 추가했습니다. 공개 타입, 엄격한 검증, canonical JSON 직렬화·역직렬화 API, JSON Schema, 문서 및 경계 조건 테스트를 포함합니다. Changesnaruon rehearsal handoff
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant BandScope
participant SharedTypes
participant NaruonConnector
BandScope->>SharedTypes: createNaruonRehearsalHandoff(input)
SharedTypes-->>BandScope: canonical handoff
BandScope->>SharedTypes: serializeNaruonRehearsalHandoff(handoff)
SharedTypes-->>BandScope: JSON artifact
BandScope->>NaruonConnector: handoff 전달
NaruonConnector->>SharedTypes: deserializeNaruonRehearsalHandoff(JSON)
SharedTypes-->>NaruonConnector: 검증된 handoff
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
|
Maintainer hardening pass applied on the current branch:
Independent local verification on Node 22 / TypeScript strict ES2022: 73 contract tests passed; |
|
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (4)
docs/integrations/naruon.md (1)
104-110: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winTypeScript 파서가 권위를 가지는 항목에 공백 정규화(trim) 규칙을 추가하세요.
isDisplayText는value === value.trim()을 요구합니다. 공개 JSON Schema의displayText와opaqueIdentifier패턴은 이 규칙을 표현하지 않습니다. 따라서 스키마만 사용하는 커넥터는" Studio A "를 통과시키고, BandScope 파서는 같은 값을 거부합니다. 이 차이를 line 110 목록에 명시하세요.📝 제안 수정
-- The JSON Schema companion is `naruon-rehearsal-handoff-v1.schema.json`; the TypeScript parser remains authoritative for payload-size, snapshot, cross-field, RFC 9557 offset/time-zone consistency, and IANA time-zone checks. +- The JSON Schema companion is `naruon-rehearsal-handoff-v1.schema.json`; the TypeScript parser remains authoritative for payload-size, snapshot, cross-field, leading/trailing whitespace, RFC 9557 offset/time-zone consistency, and IANA time-zone checks.🤖 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 `@docs/integrations/naruon.md` around lines 104 - 110, Update the compatibility statement’s TypeScript-authoritative validation list to explicitly include whitespace normalization/trim rules enforced by isDisplayText, covering displayText and opaqueIdentifier values that must equal their trimmed form.packages/shared-types/test/naruon-schema.test.ts (1)
40-40: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win리터럴
64대신MAX_NARUON_EVIDENCE_RECEIPTS를 사용하세요.이 테스트의 목적은 스키마와 런타임 상수의 정합성 확인입니다.
artifactKind와artifactVersion은 상수와 비교하지만,maxItems만 리터럴과 비교합니다. 상수가 바뀌면 이 검사는 드리프트를 잡지 못합니다.♻️ 제안 수정
- expect(schema.properties.provenance.properties.evidence.maxItems).toBe(64); + expect(schema.properties.provenance.properties.evidence.maxItems).toBe( + MAX_NARUON_EVIDENCE_RECEIPTS + );임포트도 함께 수정하세요.
import { + MAX_NARUON_EVIDENCE_RECEIPTS, NARUON_REHEARSAL_HANDOFF_KIND, NARUON_REHEARSAL_HANDOFF_VERSION } from "../src/naruon";🤖 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 `@packages/shared-types/test/naruon-schema.test.ts` at line 40, Update the maxItems assertion in the schema test to compare against MAX_NARUON_EVIDENCE_RECEIPTS instead of the literal 64, and add or adjust the import for that runtime constant. Preserve the test’s existing schema path and assertion behavior.packages/shared-types/src/naruon.ts (1)
160-162: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
isOneOf의typeof검사는 도달 불가능한 분기를 만듭니다.
values.includes(value as T)는 이미 엄격 비교를 수행합니다. 따라서typeof value === "string"검사는 결과를 바꾸지 않습니다. 현재 테스트는commitment.status와commitment.rsvpDirection에 문자열 값만 주입하므로, 이 검사의 false 경로는 실행되지 않습니다.packages/shared-types/vitest.config.ts는 이 파일에 branches 100% 임계값을 설정합니다. 같은 문제가 line 119의length < 0조건에도 있습니다. 배열 길이는 음수가 될 수 없고, proxy 테스트는Number.MAX_SAFE_INTEGER + 1만 위조합니다.중복 검사를 제거하거나, 비문자열 status와 음수 length에 대한 테스트를 추가하세요.
♻️ 제안 수정
function isOneOf<T extends string>(values: readonly T[], value: unknown): value is T { - return typeof value === "string" && values.includes(value as T); + return values.includes(value as T); }커버리지 게이트가 실제로 통과하는지 CI 로그에서 확인하세요.
🤖 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 `@packages/shared-types/src/naruon.ts` around lines 160 - 162, Update isOneOf to remove the redundant typeof value check and rely on values.includes for membership validation. Also address the unreachable length < 0 branch near line 119 by removing it or adding coverage for the intended behavior, then verify the shared-types coverage gate passes in CI.docs/integrations/naruon-rehearsal-handoff-v1.schema.json (1)
139-144: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win공개 스키마의 숫자 전용 ID 제약을 명확히 문서화하세요.
JSON Schema의
pattern은 정규식 플래그를 정의하지 않습니다. 따라서\p{Nd}를 지원하지 않거나u플래그 없이 컴파일하는 검증기는 이 패턴을 거부하거나 숫자 전용 값을 허용할 수 있습니다.docs/integrations/naruon.md에 유니코드 정규식 지원과 TypeScript parser 검증 의무를 명시하거나, 이 검사를 parser 전용 규칙으로 분리하세요.🤖 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 `@docs/integrations/naruon-rehearsal-handoff-v1.schema.json` around lines 139 - 144, 문서화된 공개 스키마의 opaqueIdentifier 숫자 전용 제한이 검증기별로 다르게 동작할 수 있으므로, docs/integrations/naruon.md에 \p{Nd} 지원 및 TypeScript parser 검증 의무를 명시하세요. 또는 schema의 pattern에서 해당 검사를 제거하고 parser 전용 규칙으로 분리하되, 숫자로만 구성된 유니코드 ID가 거부되는 동작은 유지하세요.
🤖 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 `@packages/shared-types/src/naruon.ts`:
- Around line 384-412: Update canonicalizeSnapshot to construct source,
normGroup, event, commitment, provenance, and each evidence object with explicit
canonical field order instead of spreading caller-provided objects; preserve the
existing omission of event.venue when undefined. Ensure
serializeNaruonRehearsalHandoff produces identical JSON bytes for inputs whose
keys differ only in insertion order, and add a naruon.test.ts case covering
reversed key order.
---
Nitpick comments:
In `@docs/integrations/naruon-rehearsal-handoff-v1.schema.json`:
- Around line 139-144: 문서화된 공개 스키마의 opaqueIdentifier 숫자 전용 제한이 검증기별로 다르게 동작할 수
있으므로, docs/integrations/naruon.md에 \p{Nd} 지원 및 TypeScript parser 검증 의무를 명시하세요.
또는 schema의 pattern에서 해당 검사를 제거하고 parser 전용 규칙으로 분리하되, 숫자로만 구성된 유니코드 ID가 거부되는 동작은
유지하세요.
In `@docs/integrations/naruon.md`:
- Around line 104-110: Update the compatibility statement’s
TypeScript-authoritative validation list to explicitly include whitespace
normalization/trim rules enforced by isDisplayText, covering displayText and
opaqueIdentifier values that must equal their trimmed form.
In `@packages/shared-types/src/naruon.ts`:
- Around line 160-162: Update isOneOf to remove the redundant typeof value check
and rely on values.includes for membership validation. Also address the
unreachable length < 0 branch near line 119 by removing it or adding coverage
for the intended behavior, then verify the shared-types coverage gate passes in
CI.
In `@packages/shared-types/test/naruon-schema.test.ts`:
- Line 40: Update the maxItems assertion in the schema test to compare against
MAX_NARUON_EVIDENCE_RECEIPTS instead of the literal 64, and add or adjust the
import for that runtime constant. Preserve the test’s existing schema path and
assertion behavior.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: f81bb23e-0f22-49a8-bb0d-b39ecd7b24af
📒 Files selected for processing (10)
CHANGELOG.mddocs/integrations/naruon-rehearsal-handoff-v1.schema.jsondocs/integrations/naruon.mdpackages/shared-types/package.jsonpackages/shared-types/src/naruon.tspackages/shared-types/test/naruon-calendar.test.tspackages/shared-types/test/naruon-hardening.test.tspackages/shared-types/test/naruon-schema.test.tspackages/shared-types/test/naruon.test.tspackages/shared-types/vitest.config.ts
|
@coderabbitai autofix |
|
Note Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it. Fixes Applied SuccessfullyFixed 2 file(s) based on 1 unresolved review comment. Files modified:
Commit: The changes have been pushed to the Time taken: |
Fixed 2 file(s) based on 1 unresolved review comment. Co-authored-by: CodeRabbit <[email protected]>
|
@coderabbitai review Please review exact current head |
|
@opencode-agent Please run a review-only exact-head review for |
|
@cwl-noema-review Please independently review exact current head |
|
Queued @cwl-noema-review for PR #737 at head |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
expected='80147750f5d9c2a40c866f3f32ce5cb54b8b6472'
repo='ContextualWisdomLab/bandscope'
actual="$(git rev-parse HEAD)"
printf 'HEAD=%s\nEXPECTED=%s\n' "$actual" "$expected"
if [ "$actual" != "$expected" ]; then
printf 'ERROR: checked-out HEAD differs from requested commit\n' >&2
exit 0
fi
base="$(git merge-base "$expected" origin/main 2>/dev/null || git merge-base "$expected" main 2>/dev/null || true)"
printf 'MERGE_BASE=%s\n' "$base"
printf '\n== exact commit ==\n'
git show --no-patch --format='commit=%H%nparents=%P%nsubject=%s' "$expected"
printf '\n== worktree and whitespace ==\n'
git status --short
git diff --check "${expected}^" "$expected"
printf '\n== cumulative changed files ==\n'
if [ -n "$base" ]; then
git diff --name-status "$base" "$expected"
fi
printf '\n== implementation outline ==\n'
ast-grep outline packages/shared-types/src/naruon.ts --items all --view expanded
printf '\n== implementation ==\n'
cat -n packages/shared-types/src/naruon.ts
printf '\n== public export and coverage config ==\n'
cat -n packages/shared-types/package.json
cat -n packages/shared-types/vitest.config.ts
printf '\n== schema ==\n'
cat -n docs/integrations/naruon-rehearsal-handoff-v1.schema.json
printf '\n== documentation sections for runtime/schema boundaries ==\n'
rg -n -i -C3 'schema|authoritative|snapshot|256|RFC 3339|RFC 9557|IANA|ICU|TZDB|canonical|deterministic' \
docs/integrations/naruon.md
printf '\n== test inventories ==\n'
for f in \
packages/shared-types/test/naruon.test.ts \
packages/shared-types/test/naruon-hardening.test.ts \
packages/shared-types/test/naruon-schema.test.ts \
packages/shared-types/test/naruon-calendar.test.ts
do
printf '\n--- %s ---\n' "$f"
rg -n -C2 '\b(?:describe|it|test)\s*\(' "$f" || true
done
printf '\n== targeted assertions and source references ==\n'
rg -n -i -C2 'serialize|deserialize|JSON\.parse|JSON\.stringify|structuredClone|snapshot|proxy|getter|unknown|numeric|unicode|offset|timeZone|iana|evidence|256' \
packages/shared-types/src/naruon.ts \
packages/shared-types/test/naruon.test.ts \
packages/shared-types/test/naruon-hardening.test.ts \
packages/shared-types/test/naruon-schema.test.ts \
packages/shared-types/test/naruon-calendar.test.ts
printf '\n== temporary artifacts at exact head ==\n'
git ls-tree -r --name-only "$expected" | rg -i '(bootstrap|repair|autofix|temporary|materializ)' || true
printf '\n== authority indicators ==\n'
rg -n -i -C2 '\b(fetch|axios|http|https|websocket|node:fs|node:child_process|readFile|writeFile|spawn|exec|connect|listen|sqlite|postgres|openai|anthropic)\b' \
packages/shared-types/src/naruon.ts packages/shared-types/package.json docs/integrations/naruon.md || true
printf '\n== GitHub PR state ==\n'
gh pr view 737 --repo "$repo" \
--json headRefOid,reviewDecision,statusCheckRollup,reviews \
--jq '{headRefOid, reviewDecision, checks: [.statusCheckRollup[] | {name, conclusion, status}], reviews: [.reviews[] | {author: .author.login, state}]}'
printf '\n== unresolved review threads ==\n'
gh api graphql -F owner='ContextualWisdomLab' -F name='bandscope' -F number=737 -f query='
query($owner: String!, $name: String!, $number: Int!) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
reviewThreads(first: 100) {
nodes {
isResolved
isOutdated
comments(first: 1) { nodes { author { login } body path line } }
}
}
}
}
}' --jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false) | {isOutdated, comment: .comments.nodes[0]}]'Length of output: 97044
I did not execute repository code in this sandbox. The reported GitHub check results provide the available workflow evidence. The GitHub aggregate review decision still shows You are interacting with an AI system. |
|
Queued @cwl-noema-review for PR #737 at head |
|
Queued @cwl-noema-review for PR #737 at head |
There was a problem hiding this comment.
Pull request overview
OpenCode cannot approve yet because required coverage evidence did not pass.
Review outcome
1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
-
Problem: The required coverage-evidence job result was
failure, so OpenCode cannot establish approval sufficiency for this head. -
Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.
-
Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports
successwith required evidence or explicit no-source not-applicable evidence. -
Regression test: Keep the approval branch checking
needs.coverage-evidence.result == successbefore posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present. -
Result: REQUEST_CHANGES
-
Reason: coverage-evidence result was
failure, so required test/docstring evidence was not proven for current head7b93c197cd269c8c6d6ff61376e36d41df841dcb. -
Head SHA:
7b93c197cd269c8c6d6ff61376e36d41df841dcb -
Workflow run: 31531746280
-
Workflow attempt: 1
Coverage evidence
Coverage evidence job did not run or did not publish coverage evidence.
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Changed file (10 files)"]
S1 --> I1["repository behavior"]
I1 --> R1["Review risk: Changed file (10 files)"]
R1 --> V1["required checks"]
Evidence --> S2["Docs (2 files)"]
S2 --> I2["operator or user guidance"]
I2 --> R2["Review risk: Docs (2 files)"]
R2 --> V2["docs review"]
|
Exact-head scope cleanup is now on |
|
Queued @cwl-noema-review for PR #737 at head |
|
Exact-current-head correction: the prior body evidence is now predecessor evidence only. Current head is Exact-code review found a branch-owned round-trip defect in the documented 256 KiB handoff boundary. Individual text fields are bounded in JavaScript UTF-16 code units and evidence is bounded to 64 receipts, but The repair keeps the existing field limits and deterministic canonicalization, then measures the complete newline-terminated canonical JSON UTF-8 representation after semantic validation. Values above Fresh exact-head repository workflows are running now. Queued/in-progress results and all predecessor-head green evidence are not counted as current success. Python branch coverage also remains dependent on #861 reaching the protected lineage; #783 remains the canonical JavaScript dependency-security gate and |
Product integration slice
Add a dependency-free, fail-closed BandScope → naruon rehearsal handoff contract under
@bandscope/shared-types/naruonwhile keeping BandScope independently useful and local-first.The versioned artifact carries Band norm-group identity, a rehearsal Event with a bounded RFC 3339-derived timestamp profile and IANA time zone,
confirmed | tentative | desiredcommitment strength, organizer/attendee RSVP direction, calibrated confidence, and field-level provenance receipts. It includes canonical builders/parsers, deterministic JSON serialization, a public Draft 2020-12 JSON Schema, security/privacy integration guidance, regression coverage, and APA 7 standards evidence underdocs/doctoring/naruon-rehearsal-handoff.md.Exact current head and scope
Exact head:
82ae343e9911e30cbfe65f1264367b6ae8576cb6.Protected base:
develop@acdbea6344fe1231c39535b575f4de35e4c607c9.The protected-base diff is 12 files: handoff source/tests/schema/docs/doctoring, shared-types export metadata, Vitest coverage configuration, and
CHANGELOG.md.packages/shared-types/package.jsononly exports the./naruonentry; it adds no dependency. There is no root-lock, workflow, database, network, filesystem, model, or IPC authority delta.Current trust-boundary repair
Exact-head rotation found two commits newer than the previously documented head
30904bb26acb0af03493ce854c7976b6563d6563:5f44945b5a06b5b3580621d8b0a308111555485amakes the canonical wire-size limit authoritative for object inputs too. After structural validation, the validator canonicalizes the stable snapshot, computes UTF-8 size on the newline-terminated wire representation, and rejects a handoff whose serialized form exceedsMAX_NARUON_SERIALIZED_BYTES.82ae343e9911e30cbfe65f1264367b6ae8576cb6locks that behavior forvalidateNaruonRehearsalHandoff,parseNaruonRehearsalHandoff, andserializeNaruonRehearsalHandoffusing a multibyte payload whose individual fields remain within their field limits but whose canonical artifact exceeds the wire budget.The existing pre-parse bound in
deserializeNaruonRehearsalHandoffremains in force, so oversized serialized input is rejected before JSON parsing while application-owned object inputs cannot serialize past the same public transport ceiling.Standards and privacy boundary
The public profile is intentionally narrower than generic RFC 3339: it rejects leap-second
:60and lowercase separators. RFC 9557 semantics forZ/-00:00versus asserted numeric offsets are documented, and the TypeScript parser remains authoritative where Draft 2020-12formatis not an assertion by default. The contract preserves authorized rehearsal facts; diagnostics omit attacker-controlled schema-key text rather than masking necessary business data.The parser also rejects unknown fields, numeric-only Unicode IDs, invalid/inconsistent time-zone offsets, unsupported commitment axes, non-finite confidence, sparse/oversized evidence, control characters, leading/trailing whitespace, invalid calendar fields, and values that cannot be snapshotted. Canonicalization emits nested keys in fixed field order and newly allocated nested values.
Exact-head repository verification
All evidence in this section binds only to
82ae343e9911e30cbfe65f1264367b6ae8576cb6.Terminal-success repository workflows:
ci,build-baseline,release,sbom,SAST Semgrep,bandit, andsecret-scan-gate. Exactcirun31926567801built and installed the Rust numeric extension beforequickcheck; bothci / build-and-testjob95114975671andgate / ci / rust-checkjob95114975688completed successfully.The two exact-head failures were inspected before any metadata/action change:
security-auditrun31926567832, job95114975799, completed setup/install and failed specifically atAudit npm dependencies; Python/Rust audit stages were then skipped because npm exited first and are not counted as success. The exact check-run annotation was inspected; the job-log endpoint returned no text through the connector.Security Scanrun31926567823failed only intrivy-fsjob95114986407atPrint Trivy findings that failed the gate, after the filesystem scan and SARIF requirement succeeded.dependency-review,osv-scan(including base/head and PR-introduced comparison), and Scorecard completed successfully. The exact Trivy annotation was inspected; the job-log endpoint likewise returned no text through the connector.This branch has no JavaScript dependency/root-lock delta, while the exact-head OSV PR-introduced comparison is clean. The two whole-tree failures therefore remain inherited protected-
developdependency evidence owned by canonical #783; they are not suppressed, duplicated, or counted as success.Python branch coverage is not separately reported by the protected-base pytest invocation. Shared-types has its own 100% statement/branch/function/line threshold, but statement-only Python evidence is not substituted for the requested whole-owned statement+branch gate; #861 remains the branch-measurement dependency.
Reviews and dependency order
All currently visible inline review threads are resolved/outdated. Earlier CodeRabbit findings about deterministic nested key order, parser-authoritative trim/Unicode rules, nested
additionalProperties, C0 controls, schema constants, and temporary bootstrap artifacts are already reflected in current code/tests/docs. Formal OpenCodeCHANGES_REQUESTEDreviews on record bind to predecessor heads and centralcoverage-evidencefailures, not to this exact head. There is no qualifying independent non-author approval for this exact head.Central coverage/review remains dependency-gated by
ContextualWisdomLab/.github#1008reaching protected centralmain; canonical dependency remediation #783 must then reach protecteddevelop. Do not redispatch an unchanged reviewer agent merely to reproduce those known prerequisites.Merge gate
Keep Draft and unmerged until #1008 is protected on central
main; #783 establishes the protected dependency baseline; #861 establishes protected Python branch measurement where required; this branch is refreshed onto the then-current protecteddevelop; all required exact-current-head repository and central statement/branch coverage, docstring, SAST, security, SBOM/supply-chain and review gates are terminal-success; zero actionable current-head threads remain; a qualifying independent non-author exact-head approval satisfies the last-push rule; and branch protection permits merge without bypass.Queued, in-progress, skipped-required, failed inherited-base, predecessor-head, self/author, protected-base, or administrative-bypass evidence is not success.
Advances #610; the naruon-side importer and connector authorization path remain separately tracked.