Skip to content

1.0 Semantic Contract

유용태 edited this page Jun 18, 2026 · 3 revisions

1.0 Semantic Contract

json-document 1.x 호환성은 export 이름만 유지한다는 뜻이 아니다. 제품은 result branch, error code, atomicity, selection/history 복구, clipboard 기본값에 의존한다. 이 페이지는 1.0에서 고정된 의미론을 API 사용자 관점에서 정리한다.

고정 대상

  1. Public import는 @interactive-os/json-document@interactive-os/json-document/react다.
  2. 모든 result family는 ok discriminant를 유지한다.
  3. 실패 result의 stable branch key는 code다.
  4. reason은 진단 문구이며 정확한 문자열로 분기하지 않는다.
  5. Schema failure의 violations[].path는 JSON Pointer다.
  6. strict 기본값은 false다.
  7. 실패한 mutation은 value, selection, clipboard, history, subscriber event를 부분 변경 상태로 남기지 않는다.
  8. commit(..., { selectionAfter })는 patch와 final selection을 같은 history entry에 기록한다.
  9. undo()redo()는 top-level command로 JSONCapabilityResult를 반환한다.
  10. 여러 source clipboard payload를 array insertion target에 paste하면 기본적으로 item별 sibling insert가 된다.

Result Code

앱은 실패를 reason 문구가 아니라 code로 분류한다.

const result = doc.canReplace("/title", 1);

if (!result.ok) {
  switch (result.code) {
    case "schema_violation":
      result.violations;
      break;
    case "invalid_pointer":
    case "path_not_found":
      result.pointer;
      break;
  }
}

reason은 logging, debug panel, 개발자 진단에 적합하다. Localization이나 제품 분기 조건은 code, pointer, violations 같은 구조를 사용한다.

Strict Policy

기본 document는 실행 실패를 throw하지 않고 result로 반환한다.

const doc = createJSONDocument(Schema, initial);
const result = doc.patch({ op: "replace", path: "/title", value: 1 });

strict: true를 명시하면 patch, commit, load, reset 같은 execution method가 JSONDocumentError를 throw할 수 있다. can*, schema query, clipboard write 같은 non-execution API는 strict mode에서도 result surface를 유지한다.

Atomicity

Mutation은 전부 성공하거나 전부 실패한다.

const before = doc.value;
const beforeSelection = doc.selection?.snapshot();

const result = doc.commit(operations, {
  selectionAfter: "/items/2",
});

if (!result.ok) {
  // value와 selection은 실패 전 상태로 남아 있다.
  doc.value;
  doc.selection?.snapshot();
}

실패한 mutation은 subscriber에게 성공한 patch stream event처럼 보이면 안 된다. History stack도 실패한 변경을 undo 가능한 entry로 기록하면 안 된다.

Selection And History

selectionAfter를 제공하면 core auto tracking보다 explicit final selection이 우선한다.

doc.commit([
  { op: "replace", path: "/items/0/title", value: "Ready" },
], {
  label: "rename",
  selectionAfter: "/items/0",
});

이 selection은 patch 적용 이후 document state 기준으로 복원된다. Undo/redo는 value와 selection을 같은 history entry에서 복원한다.

명시 selection이 없으면 core는 applied JSON Patch를 기준으로 기존 selection을 tracking/recover한다. 구조 편집 extension처럼 다음 focus를 정확히 아는 코드라면 selectionAfter를 제공하는 편이 좋다.

Clipboard Spread

Clipboard는 browser clipboard가 아니라 document instance 안의 headless buffer다.

doc.copy(["/items/0", "/items/1"]);
doc.paste("/items/-");

여러 source를 copy/cut한 clipboard payload는 array insertion target에서 기본적으로 펼쳐진다. 외부 payload를 직접 넣는 경우에는 doc.insert(target, payload, { spread: true })를 사용해 같은 sibling insert 의미를 명시한다.

검증 위치

이 계약은 다음 repo 산출물로 보호된다.

  • packages/json-document/public-contract.json: public export name lock
  • docs/standard/result-contract.md: result/error code 의미론
  • docs/standard/selection-contract.md: selection 의미론
  • docs/standard/schema-introspection-contract.md: schema query 의미론
  • packages/json-document/tests/public/standard-conformance.test.ts: 표준 적합성 흐름
  • packages/json-document/tests/public/semantic-contract.test.ts: breaking-risk fixture
  • scripts/evaluate-standardization.mjs: release gate에서 위 산출물 존재와 핵심 패턴 확인

Clone this wiki locally