Skip to content

สัญญาของ OpenSpec Agent ​

พื้นผิวที่เครื่องสามารถอ่านได้ของ CLI openspec ซึ่งได้รับการตรวจสอบกับ src/ (การตรวจสอบแบบ capstone, 2026-06-11) รายละเอียดโครงสร้างทั้งหมดด้านล่างนี้ถูกจัดทำขึ้นจากโค้ดที่เป็นแหล่งกำเนิด

1. ข้อตกลงทั่วไป ​

  • หนึ่งเอกสาร JSON ต่อหนึ่งครั้งของการเรียกใช้งาน ในโหมด --json stdout จะส่งคืนเอกสาร JSON เพียงหนึ่งฉบับ (จัดรูปแบบสวยงามโดยเว้นวรรค 2 ช่อง) ข้อความอธิบายสำหรับมนุษย์ ตัวหมุนสถานะ (spinners) และแบนเนอร์ของ store จะถูกส่งไปยัง stderr
  • แบนเนอร์ของ store ในโหมดสำหรับมนุษย์ เมื่อมีการเลือก root ของ store แล้ว จะพิมพ์ข้อความ Using OpenSpec root: <id> (<path>) ไปยัง stderr และไม่มีการพิมพ์ข้อความนี้ในโหมด JSON
  • การใช้ตัวพิมพ์ใหญ่-เล็กของคีย์ขึ้นอยู่กับพื้นผิวการใช้งาน (ดูส่วนความไม่สอดคล้องที่ทราบ): โหลดข้อมูลของ store/doctor/context ใช้ snake_case; โหลดข้อมูลของ workflow (status, instructions, new change, validate, list) ใช้ camelCase ยกเว้นออบเจกต์ root ที่ฝังอยู่ ซึ่งจะใช้ store_id เสมอ
  • คีย์ที่ไม่จำเป็นจะถูกตัดออก ไม่ใช่กำหนดเป็น null ในโหลดข้อมูลส่วนใหญ่ (เช่น root.store_id, member.path) ข้อยกเว้นที่กำหนดค่า null อย่างชัดเจนจะระบุไว้ในแต่ละโครงสร้าง (git.* ของ store doctor, โหลดข้อมูลความล้มเหลว)

2. เอ็นเวลอปสำหรับการวินิจฉัย (The diagnostic envelope) ​

รูปร่างของเอ็นเวลอปหนึ่งรูปแบบถูกใช้ร่วมกันโดยทุกการวินิจฉัยที่เครื่องอ่านได้ (StoreDiagnostic):

json
{
  "severity": "error" | "warning" | "info",
  "code": "snake_case_string",
  "message": "human sentence",
  "target": "dotted.surface (optional)",
  "fix": "one actionable sentence/command (optional)"
}

การวินิจฉัยปรากฏในสองตำแหน่ง: อาร์เรย์สถานะ (status: StoreDiagnostic[] ที่ระดับบนสุดหรือต่อรายการ) สำหรับการค้นพบด้านสุขภาพ และ ข้อผิดพลาดที่ถูกโยน (thrown errors) ซึ่งแปลงเป็นอาร์เรย์ status ขนาดหนึ่งองค์ประกอบเมื่อคำสั่งล้มเหลว

3. การเลือกรากและ RootOutput ​

คำสั่งทั้งหมดที่แก้ไขราก (list, show, validate, status, instructions, instructions apply, instructions archive, new change, archive, doctor, context, schemas) จะแก้ไข OpenSpec root เพียงหนึ่งตัวด้วยลำดับความสำคัญดังนี้:

  1. --store <id> → รากของสต็อกที่ลงทะเบียน (source: "store").
  2. หากไม่เป็นเช่นนั้น ให้หาผู้บรรพบุรุษที่ใกล้ที่สุดที่มี openspec/: รูปร่างการวางแผน → source: "nearest" (ตัวชี้ store: จะถูกละเว้นพร้อมคำเตือน stderr); ไดเรกทอรีที่มีเฉพาะคอนฟิกพร้อมตัวชี้ store: ที่ถูกต้อง → สต็อกนั้น, source: "declared".
  3. ไม่มีรากที่ใกล้ที่สุด + มีการตั้งค่า defaultStore ทั่วโลก (openspec config set defaultStore <id>) → สต็อกนั้น, source: "global_default"; id ที่ล้าสมัยจะล้มเหลวพร้อมข้อผิดพลาดของสต็อกพื้นฐานและ fix ที่ระบุ openspec config unset defaultStore.
  4. ไม่มีรากที่ใกล้ที่สุด, ไม่มีค่าเริ่มต้น + มีสต็อกที่ลงทะเบียนอยู่ → ข้อผิดพลาด no_root_with_registered_stores.
  5. ไม่มีราก, ไม่มีค่าเริ่มต้น, ไม่มีสต็อก: คำสั่งอาจถือว่า cwd เป็น source: "implicit"; doctor, context, list และการตรวจสอบแบบกลุ่ม validate จะล้มเหลวแทนด้วย no_openspec_root. list จะรักษาการสลับกลับแบบ implicit สำหรับโปรเจกต์รุ่นเก่าที่มี openspec/project.md

โหลด JSON ที่สำเร็จปกติจะฝังรากไว้ภายใน; schemas --json ที่สำเร็จจงใจยังคงเป็นอาร์เรย์เปล่าตามเอกสารใน §4.13:

json
"root": { "path": "/abs/path", "source": "store" | "declared" | "global_default" | "nearest" | "implicit", "store_id": "id (only when store-selected)" }

สัญญาความล้มเหลวของราก: ในโหมด JSON ความล้มเหลวในการแก้ไขจะพิมพ์ { ...commandNullShape, "status": [diagnostic] } บน stdout และออกด้วยรหัส 1

4. รูปร่าง JSON ของคำสั่ง ​

4.1 list --json ​

{ "changes": [ { "name", "completedTasks", "totalTasks", "lastModified", "status": "no-tasks"|"complete"|"in-progress" } ], "root": RootOutput } — โปรดสังเกตว่า status ต่อการเปลี่ยนแปลงเป็นเอนัมสตริงที่นี่ --specs: { "specs": [ { "id", "requirementCount" } ], "root" }.

4.2 show <item> --json ​

การเปลี่ยนแปลง: { "id", "title", "deltaCount", "deltas": [...], "root" }. สเปค: { "id", "title", "overview", "requirementCount", "requirements": [...], "metadata": { "version", "format", "sourcePath"? }, "root" }.

4.3 validate --json ​

{ "items": [ { "id", "type": "change"|"spec", "valid", "issues": [ { "level", "path", "message", "line"?, "column"? } ], "durationMs" } ], "summary": { "totals": {items,passed,failed}, "byType": {...} }, "version": "1.0", "root" }. ออกด้วยรหัส 1 เมื่อมีรายการใดรายการหนึ่งล้มเหลว

4.4 status --json ​

{ "changeName", "schemaName", "planningHome"?: { "kind", "root", "changesDir", "defaultSchema" }, "changeRoot", "artifactPaths": { "<id>": {outputPath, resolvedOutputPath, existingOutputPaths} }, "nextSteps": ["..."], "actionContext": { "mode": "repo-local", "sourceOfTruth": "repo", "planningArtifacts", "linkedContext", "allowedEditRoots", "requiresAffectedAreaSelection", "constraints" }, "isPlanningComplete", "isComplete", "applyRequires", "artifacts": [ {id, outputPath, status: "done"|"skipped"|"ready"|"blocked", requires, missingDeps?} ], "root" }. isPlanningComplete หมายถึงอาร์ติแฟกต์การวางแผนที่ไม่ได้ถูกละเว้นทุกชิ้นมีอยู่; อาร์ติแฟกต์ที่ถูกละเว้นนับว่าเป็นที่พอใจโดยไม่ต้องสร้าง มันไม่ได้หมายถึงงานด้านการนำไปปฏิบัติเสร็จสิ้น isComplete ถูกเก็บไว้เป็นอิลิแอสความเข้ากันได้ที่มีค่าเดียวกัน requires ของแต่ละอาร์ติแฟกต์คือไอดีของการพึ่งพาโดยตรงของมัน (มีอยู่ในทุกสถานะ ดังนั้นชุดที่ต้องพึ่งพาแบบทรานซิติฟจึงสามารถคำนวณได้แม้ว่าอาร์ติแฟกต์จะเป็น done; missingDeps จะปรากฏเฉพาะเมื่อ blocked เท่านั้น) อาร์เรย์ artifacts อยู่ในลำดับการพึ่งพา โดยลำดับการประกาศ artifacts: ของสเปคมักจะใช้เพื่อแก้กรณีเสมอกันระหว่างอาร์ติแฟกต์ที่กลายเป็น ready พร้อมกัน (ไม่ใช่ตามตัวอักษร) ดังนั้นรายการ ready ตัวแรกคืออาร์ติแฟกต์ที่จะเขียนถัดไป; missingDeps ใช้ลำดับเดียวกัน "skipped" ทำเครื่องหมายอาร์ติแฟกต์whose generates path อยู่ภายใต้ specs/ ในการเปลี่ยนแปลงwhose .openspec.yaml ประกาศ skip_specs: true; มันทำให้การพึ่งพามีความสมบูรณ์แต่ไม่ควรสร้างไฟล์ ไม่มี actively changes: { "changes": [], "message", "root" }, ออกด้วยรหัส 0

--all (แบบแบตช์, ขัดแย้งกับ --change — การรวมกันทั้งสองอย่างถือเป็นข้อผิดพลาดด้วย null-shape { "changes": [], "root": null, "status": [d] }): { "changes": [ <per-change status object, no per-change root>, ... ], "root" }, เรียงตามชื่อการเปลี่ยนแปลง การเปลี่ยนแปลงที่โหลดไม่สำเร็จจะมีส่วน { "changeName", "status": [d] } แทนที่; การกวาดล้างจะดำเนินต่อไป รักษาเอ็นเวลอปให้สมบูรณ์ และออกด้วยรหัส 1 ทั้งในโหมดข้อความและ JSON การกำหนดค่า --schema ที่ไม่ถูกต้องจะทำให้การเรียกใช้งานทั้งหมดล้มเหลวด้วย null-shape แม้ว่าจะไม่มีการเปลี่ยนแปลงก็ตาม

4.5 instructions <artifact> --json ​

{ "changeName", "artifactId", "schemaName", "changeDir", "planningHome"?, "outputPath", "resolvedOutputPath", "existingOutputPaths", "description", "instruction"?, "context"?, "rules"?, "references"?: ReferenceIndexEntry[], "skipped"?, "warning"?, "template", "dependencies": [{id,done,path,description,skipped?}], "unlocks", "root" }. unlocks ระบุอาร์ติแฟกต์ที่ทำให้ชิ้นนี้พร้อมใช้งาน ตามลำดับการประกาศในสเปค (ลำดับเดียวกับที่ status แนะนำ) "skipped": true (พร้อม "warning") จะปรากฏเมื่อการเปลี่ยนแปลงประกาศ skip_specs: true และอาร์ติแฟกต์นี้ถูกละเว้น — อย่าสร้างไฟล์ของมัน รายการการพึ่งพาที่มี skipped: true ถือว่าเสร็จสมบูรณ์โดยไม่ต้องใช้ไฟล์ — อย่าพยายามอ่านเส้นทางของมัน

ReferenceIndexEntry: { "store_id", "root"?, "specs"?: [{id,summary}], "fetch"?, "status": [] } — รายการที่แก้ไขแล้วจะมี root/specs/fetch; รายการที่ยังไม่แก้ไขจะมี store_id + สถานะ warning ดัชนีจำกัดอยู่ที่ 50KB (reference_index_truncated).

4.6 instructions apply --json ​

{ "changeName", "changeDir", "schemaName", "contextFiles": { "<artifactId>": ["/abs", ...] }, "progress": {total,complete,remaining}, "tasks": [{id,description,done}], "state": "blocked"|"all_done"|"ready", "missingArtifacts"?, "missingPrerequisites"?, "warnings"?, "instruction", "references"?, "context"?, "operationGuidance"?, "root" }. missingArtifacts คือสิ่งที่ apply ล่าช้า (the schema's apply.requires); missingPrerequisites คือทุกอย่างที่ยังต้องสร้างก่อนที่ apply จะทำงานได้ ในลำดับการสร้าง - ปิดล้อมแบบทรานซิติฟของ those requires ดังนั้นอาจเป็นรายการที่ยาวกว่า warnings ระบุปัญหาที่ไม่บล็อกกับการเปลี่ยนแปลงเอง — ปัจจุบันคือการเปลี่ยนแปลงที่พร้อมสำหรับการนำไปปฏิบัติโดยไม่มี delta specs และไม่มี skip_specs: true ซึ่ง state openspec validate ปฏิเสธ ทั้งฟิลด์ root สองฟิลด์ (context, operationGuidance) อ่านจาก root ที่เลือกในทุกการเรียกใช้งาน context เป็นการป้อนข้อมูลระดับ prompt whose ข้อเท็จจริงโครงการที่เกี่ยวข้อง แนวทางปฏิบัติ และข้อจำกัดต้องถูกนำไปใช้; operationGuidance เป็นการป้อนข้อมูลเชิงคำแนะนำ whose entries จะปฏิบัติตามก็ต่อเมื่อเกี่ยวข้องและเข้ากันได้กับ workflow ภายใน ทั้งสองยังคงแยกออกจาก state, tasks, progress, context files และ instruction ภายใน

4.7 instructions archive --json ​

{ "changeName", "context"?, "operationGuidance"?, "root" }. ต้องการ --change ที่ถูกต้องใน root ของ repo/store ที่แก้ไขแล้ว และใช้ semantics ของ required-context/advisory-guidance เดียวกันกับ apply นี่คือพื้นผิว runtime-input แบบอ่านอย่างเดียว: มันไม่คืนค่า workflow archivestatic, ตรวจสอบหรือรวม delta specs, เขียน main specs หรือย้ายการเปลี่ยนแปลง

4.8 new change <name> --json ​

สำเร็จ: { "change": { "id", "path", "metadataPath", "schema" }, "root" }. ล้มเหลว: { "change": null, "status": [d] }, ออกด้วยรหัส 1

4.9 archive <name> --json ​

สำเร็จ: { "archive": { "change", "archivedAs": "YYYY-MM-DD-name", "path", "specsUpdated", "totals"?, "warnings"? }, "root" }. ล้มเหลว: { "archive": null, "root"?, "status": [d] }, ออกด้วยรหัส 1 specsUpdated เป็นจริงเฉพาะเมื่อมีไฟล์สเปคอย่างน้อยหนึ่งไฟล์ถูกเขียนหรือเกษียณ (ความสามารถwhose requirement สุดท้ายการเปลี่ยนแปลงลบไปจะมีสเปคถูกลบ ซึ่งต้องการ retire_capabilities: true ใน .openspec.yaml ของการเปลี่ยนแปลง; การเกษียณทุกครั้งจะถูกตั้งชื่อใน warnings โดยมีคำสั่งกู้คืน Git ที่สามารถวางแปะได้เฉพาะเมื่อสเปคนั้นอยู่ใน checkout ของผู้เรียกใช้งาน); การเปลี่ยนแปลงที่ซิงค์แล้วจะจัดเก็บด้วย totals เป็นศูนย์ทั้งหมดและการข้ามรายการที่ระบุใน warnings โหมด JSON เป็นแบบโต้ตอบอย่างเคร่งครัด: จุด prompt ทุกจุดจะกลายเป็นโค้ด archive_*

4.10 doctor --json ​

{ "root": { "path", "source", "store_id"?, "healthy", "status": [] }, "store": { "id", "metadata": {present,valid,remote?}, "origin_url"?, "drift"?: {ahead,behind}, "status": [] } | null, "references": [...], "status": [] }. drift (ปรากฏเฉพาะสำหรับ git-backed store checkout ที่มี upstream tracking ref) คือจำนวน ahead/behind เทียบกับ upstream ที่ดึงล่าสุด ไม่ใช่ remote จริง การค้นพบด้านสุขภาพของความรุนแรงใดๆ ออกด้วยรหัส 0 โหลดความล้มเหลว: { "root": null, "store": null, "references": [], "status": [d] }, ออกด้วยรหัส 1

4.11 context --json ​

{ "root": { "path", "source", "store_id"?, "role": "openspec_root" }, "members": [ { "role": "referenced_store", "id", "path"?, "remote"?, "fetch"?, "status": [] } ], "status": [] }. AVAILABLE = path present AND status empty. --code-workspace <path> เขียน {folders:[{name,path}]} (referenced stores ที่พร้อมใช้งานเท่านั้น, ref: prefixes); ในโหมด JSON การเขียนจะดำเนินการก่อนการพิมพ์ดังนั้น stdout จึงมีเอกสารเดียวเสมอแม้ในการเขียนล้มเหลว ความล้มเหลว: { "root": null, "members": [], "status": [d] }, ออกด้วยรหัส 1

4.12 store ... --json ​

setup/register: { "store": {id, root, metadata_path?}, "registry": {path, registered, already_registered}, "git": {is_repository, initialized, committed}, "created_files": [], "status": [] }. unregister/remove: { "store", "registry": {path, removed}, "files": {deleted, deleted_path, left_on_disk}, "status": [] }. list: { "stores": [{id, root}], "status": [] }. doctor: { "stores": [ { id, root, metadata_path?, openspec_root: {...healthy, status}, metadata: {present, valid, id?, remote}, git: {is_repository, has_commits, has_uncommitted_changes, has_remote, origin_url}, status } ], "status": [] } (null = unknown/not probed). การค้นพบด้านสุขภาพออกด้วยรหัส 0; ความล้มเหลวออกด้วยรหัส 1 ด้วย null-shape ที่สอดคล้องกัน การยกเลิก prompt ออกด้วยรหัส 130

4.13 schemas --json / templates --json ​

schemas: สำเร็จยังคงเป็นอาร์เรย์เปล่า [ {name, description, artifacts, source} ]; มันแก้ไขลำดับความสำคัญของการเลือก root แบบมาตรฐานและยอมรับ --store <id>. ความล้มเหลวในการเลือก root: { "schemas": [], "root": null, "status": [d] }, ออกด้วยรหัส 1 templates: ออบเจกต์ที่มี key { "<artifactId>": {path, source} }, ยังคงใช้ cwd-based โดยไม่มี root/status keys

5. สัญญา exit-code ​

สถานการณ์ExitStdout
สำเร็จ รวมถึงผลการตรวจสุขภาพ (doctor/context/store doctor)0payload
คำสั่งล้มเหลวในโหมด --json1เอกสาร JSON เอกเดียวที่มี status: [d] และ null-shape ของคำสั่ง
validate ที่มีรายการล้มเหลว1รายงานฉบับเต็ม
ยกเลิกการป้อนข้อมูล (store group, โหมดมนุษย์)130stderr เท่านั้น

6. แคตตาล็อกโค้ดวินิจฉัย ​

การแก้ไข ​

no_openspec_root, no_root_with_registered_stores, no_registered_stores, unknown_store, store_identity_mismatch, unhealthy_store_root, store_path_not_supported, invalid_store_pointer, initiative_option_removed, areas_option_removed; pass-through: invalid_store_id, invalid_store_registry, invalid_store_metadata.

สุขภาพ OpenSpec-root (error, ไม่มีวิธีแก้ไข) ​

openspec_store_root_missing, openspec_store_root_not_directory, openspec_root_missing, openspec_root_not_directory, openspec_config_missing, openspec_config_not_file, openspec_specs_not_directory, openspec_changes_not_directory, openspec_archive_not_directory. ในช่วง stores beta, openspec/specs/, openspec/changes/, และ openspec/changes/archive/ อาจไม่ปรากฏใน root ที่สุขภาพดี; พวกมันจะเป็น error ด้านสุขภาพเฉพาะเมื่อมีอยู่แต่ไม่ใช่ directory

Registry/identity/state ของ store ​

invalid_store_id, invalid_store_registry, invalid_store_metadata, store_registry_busy, store_not_found, no_store_registry, store_registry_changed, store_metadata_missing, store_metadata_id_mismatch, store_metadata_invalid, store_id_conflict, store_path_conflict, store_already_registered (info).

Setup/register/remove ของ store ​

store_setup_id_required, store_setup_path_required, store_setup_path_not_directory, store_setup_inside_git_repo, store_setup_non_empty_directory, store_setup_cancelled, store_path_required, store_path_missing, store_path_not_directory, store_root_pointer_declared, store_register_root_unhealthy, store_register_identity_confirmation_required, store_register_cancelled, store_remote_empty, store_remote_requires_hand_edit, store_remove_confirmation_required, store_remove_cancelled, store_remove_path_not_directory, store_remove_metadata_missing, store_root_missing (warning ใน remove, error ใน doctor), store_root_not_directory.

Git ของ store ​

store_git_init_failed, store_git_identity_missing, store_git_commit_failed, store_git_no_commits (warning), store_clone_fragile_directories (warning), store_remote_divergence (info, doctor), store_checkout_drift (info, doctor).

References (warning) ​

reference_invalid_id, reference_registry_unreadable, reference_unresolved, reference_root_unhealthy, reference_index_truncated.

Relationships (warning; doctor; context เก็บเฉพาะ registry เท่านั้น) ​

relationship_registry_unreadable, root_pointer_ignored, root_pointer_invalid, pointer_declarations_inert.

Archive (โหมด JSON) ​

archive_change_name_required, archive_change_not_found, archive_change_symlink, archive_validation_failed, archive_confirmation_required, archive_tasks_incomplete, archive_spec_update_failed, archive_spec_validation_failed, archive_target_exists, archive_error.

การเขียน Context ​

context_file_exists, context_output_dir_missing.

Fallbacks ​

doctor_failed, context_failed, store_error, change_error, archive_error.

ความไม่สอดคล้องที่ทราบแล้ว ​

บันทึกโดย capstone audit; การเปลี่ยนชื่อ published-key เป็น product decisions ที่เลื่อนไปหลังการปล่อยเวอร์ชันนี้:

  1. ในโหมด --json, เส้นทางความล้มเหลวหลายเส้นทางพิมพ์ stderr เท่านั้นโดยไม่มีเอกสาร JSON แก้ไขแล้วในรอบ capstone gauntlet: show/validate รายการที่ไม่รู้จักและไม่ชัดเจนจะส่ง {status:[{code: unknown_item | ambiguous_item, ...}]}; thrown errors ใน status/instructions/list/show/validate จะผ่าน JSON-aware failure helper (null-shape ของคำสั่ง + status); store <unknown subcommand> --json จะส่ง {status:[{code: unknown_store_subcommand}]}; list จะนำ null-shape ของ {changes|specs: [], root: null} ไปใช้เมื่อการแก้ไขล้มเหลว
  2. store_root_missing ถูกส่งด้วย severity สองระดับ (warning ใน remove, error ใน store doctor) — ขึ้นอยู่กับบริบท, อธิบายไว้ด้านบน
  3. snake_case (store family) กับ camelCase (workflow family) ในการตั้งชื่อ key; root.store_id เป็น snake_case ทุกที่
  4. มีคำประกาศประเภท envelope แบบขนานสี่แบบใน src; archive diagnostics ไม่เคยมี target
  5. list --json นำ key status กลับมาใช้เป็น string enum ต่อ change
  6. เฉพาะ output ของ validate ที่มีฟิลด์ version
  7. templates เพิกเฉยการเลือก root (ใช้ cwd เป็นฐาน, ไม่มี --store)
  8. รูปแบบคำนามที่เลิกใช้แล้ว (change/spec subcommands) ส่ง payload ที่ไม่มี envelope โดยไม่มี root/status