Files

15 KiB
Raw Permalink Blame History

4.2. Text View

位置付け

Objectの公開情報と、Interfaceの型・Operation・documentationは、Clientが取得・検証したデータである。それをAIや人間へプレーンテキストで示す形式が、WIP Text Viewである。Tool結果、CLI、GUIのテキスト表示などで共通に使える。

一つのObjectの公開情報を表すまとまりをObject signature、一つのInterfaceの型・Operation・documentationを表すまとまりをInterface signatureと呼ぶ。Signatureは表示上のまとまりであり、暗号学的な署名やidentityではない。

表示対象、配置、順序、両signatureを同時に提示するかは、表示側が決める。Signatureを包む共通document構造、ObjectとInterfaceの組み合わせ、Tool response envelopeは定義しない。

データの正本は3. ProtocolのObjectとInterface Descriptorである。Text Viewは、検証済みの情報から生成する表示である。

  • Interfaceの交換形式、手書きのschema言語、Objectのserializationではない。
  • Parser、round-trip、表示textからのDescriptor復元は要求しない。
  • Operationの実行言語ではない。Clientは保持するInterface参照とOperation名を別々に扱い、表示textを再parseしてProtocol requestを構築しない。
  • Textの一致をObject identity、Descriptorの同一性、validator、digestの代用にしない。
  • HostへText Viewの生成・配信を要求せず、Transport BindingやAI providerのTool schemaとは独立させる。

表示の入力と責務

Object signatureの入力は、検証済みObjectと、分かる場合はそのObjectを観測したpathである。Interface Descriptorは必要ない。PathはObjectのfieldではなく、配置contextとして使う。

一方、Interface signatureの入力は、Interface参照と、それに対応する検証済みかつ対応formatのDescriptorである。Objectは必要ない。Interface参照も、Descriptor自身のfieldではない。

どちらも観測時点の公開情報を表示するものであり、最新状態、Operationの実行権限、実行成功は保証しない。観測、Descriptor取得、cache、表示対象の選択、rendererの呼び出しAPIや内部structは規定しない。

Object tree全体の描画、Operation arguments / resultのvalue表示、Protocol errorや診断metadataの表示は本章の対象に含めない。

参照表記

Interface参照のscopeとlocal nameの境界は::、InterfaceとOperationの境界は#で表す。

対象 短縮表記
完全なOperation指定 /github::issue.read#read
完全なInterface参照 /github::issue.read
Scope省略のOperation指定 issue.read#read
Root scopeのOperation指定 /::issue.read#read

/github::issue.read#readはscope = "/github"、name = "issue.read"、operation = "read"の組を示す。対象Objectのpath、arguments、validatorを含まず、request全体の代わりにはならない。Protocolでは構造化Interface参照とOperation名を別fieldに保持し、この連結stringをwireやcache keyに使用しない。

成分の引用

  • Scopeはcanonical absolute pathであり、文字列全体が[A-Za-z0-9_./-]+に一致する場合は引用せず表示できる。
  • Interface名とOperation名は、文字列全体が[A-Za-z0-9_.-]+に一致する場合は引用せず表示できる。
  • それ以外は成分全体を二重引用符で囲み、JSON stringのescape規則を使用する。単純な成分も引用してよい。
  • ::と#は引用符の外側でだけ境界となる。区切りの前後に空白を出力しない。
"/github::archive"::issue.read#read
/github::"issue#read"#read
/github::issue.read#"read#raw"
"/開発"::"課題.read"#read
"/github"::"issue.read"#"read"

最後の例と/github::issue.read#readは、同じ成分を表す。引用やescapeを変えても、元の値は変わらない。ProtocolへASCII制限や禁止文字を追加せず、Unicode normalization、case変換、URL encodingも行わない。

制御文字等には名前と文字列の安全なescape規則も適用する。境界を読むときは引用とescapeを考慮し、単純な文字列splitを使わない。

Scope省略とcontext

Scopeの相対pathは、Protocol dataにも短縮表記にも認めない。github::issue.readや../github::issue.readを相対scopeとして解決しない。Scopeを明示するなら、引用の有無にかかわらずcanonical absolute pathを使う。

issue.read#readや、Interfaceだけのissue.readは、scopeが別途明示されたcontextでのみ使える省略形である。省略はroot scope /の指定ではない。Contextがなければ解決できず、rootへのdefault、対象Objectのpathからの推測、祖先の同名Interfaceの探索も行わない。

Scopeが確定した後も、membership、祖先制約、authorizationは検証する。

短縮表記を入力として受けるかはToolやUIが決める。受ける場合は専用の入力境界で成分を検証し、構造化参照とOperation名へ変換する。Signature全体を再parseして呼出先を決めることとは区別し、invokeを単一string引数の操作へ変更しない。

Signature内の参照

両signature内のInterface参照は、公開先の絶対scopeを含む完全な短縮表記を生成し、その全体をJSON stringとして引用する。例えば、scope /github、name issue#readの参照は"/github::\"issue#read\""となる。

成分ごとの引用と、参照全体をsignature内の文字列として示す外側の引用は、別の層である。Scopeを省略したり、Upstreamの参照へ戻したりしない。

Object signature

object at "/issues/123" {
  name: "123";
  description: "Issue 123の公開操作。本文はOperationで取得する。";
  interfaces: ["/::issue.read", "/::issue.lifecycle"];
}

Objectはobject at "<path>" { ... }と表示する。Pathが分からない場合はobject { ... }とし、nameやrefからpathを推測しない。

Block内は次の順に表示する。

  1. name: "...";にObjectのnameをそのまま表示する。自由なtitleへ置き換えない。
  2. descriptionがある場合はdescription: "...";で表示する。Object全体の説明を通常のpropertyとして示す。
  3. interfaces: ["...", "..."];に全Interface参照をHostの立項順で表示する。空集合はinterfaces: [];と明示する。

Descriptionがない場合はそのpropertyを省略し、存在する空文字列はdescription: "";と表示する。説明の欠落からObjectの用途を補完しない。

Rootの表示はobject at "/"かつname: "";となり、scope /のInterfaceを公開できる。Interface参照は参照表記に従って絶対scopeを含め、別の参照やlocal nameだけへ置き換えない。

Scope Objectのrefやvalidatorを@...として参照に付け足さない。scope_refはClient runtimeが扱う観測・precondition metadataである。Object自身のrefとvalidatorもsignatureへ含めず、同一性管理と条件付き実行はClient runtimeが引き受ける。

Objectの本文やdomain metadataを推測してpropertyとして追加しない。Childrenもsignatureに含めないため、表示にchildrenがないことから、未観測か観測済みの空集合かを判断することはできない。

Interface signature

/// "Issueの内容と関連項目を読む。"
interface "/::issue.read" {
  type Relation = enum { parent, sibling, related };

  type RelatedItems = {
    /// "同じWorldspace内の関連項目。"
    items: [entry],
    next_cursor?: string,
  };

  /// "本文を取得する。"
  operation read_body() -> { body: string };

  /// "関係を指定して関連項目を取得する。"
  operation get_related_items(
    relation: Relation,
    limit?: integer,
  ) -> RelatedItems;
}

Interfaceはinterface "<reference>" { ... }と表示する。<reference>は構造化参照から生成した完全な短縮表記であり、前述の規則で全体を引用表示する。

Block内には、Descriptorの全types、全operationsの順で、それぞれを宣言順に表示する。Record field、parameter、enum / union caseも元の順序を保つ。これは表示の順序であり、Protocol上の名前解決やvalidationには影響しない。

宣言を折りたたんだり抜粋したりせず、budgetによる省略も行わない。型を...へ置き換えず、field、parameter、caseを削らない。DescriptorにtypeもOperationもなければ、空のblockを表示する。

同名Operationが異なるInterfaceにあっても、それぞれのblock内に表示する。Blockの参照によって出所を示し、Operation名を改名したり、参照をOperation名へ連結したりしない。異なるInterfaceの宣言を、一つのnamespaceへ平坦化しない。

型の表記

DescriptorのTypeExpr 表示
Unit / Boolean / Integer / Number unit / boolean / integer / number
String / Bytes / Json / Entry string / bytes / json / entry
Named 参照先typeの名前
Record { field: Type, optional_field?: Type }
List [Type]
Enum enum { first, second }
Union union { empty, found(Type) }

Named type declarationはtype Name = Type;とする。Enum、unionを含むすべてのTypeExprを、Descriptorで現れる位置にそのまま表示する。Named typeは同じInterface Descriptor内の宣言を参照し、別Interfaceの同名typeとは混同しない。

?を付けるのは、required = falseのfieldまたはparameterだけである。Nullable、default value、一般化したoptional型を示す記号ではなく、unitとも区別する。

Unionでは、payloadがなければempty、あればfound(Type)と表示する。そのため、emptyとempty(unit)は異なる表示になる。

type CloseResult = union {
  closed,
  blocked({ dependencies: [entry] }),
};

空record、空enum、空unionが検証済みDescriptorに現れる場合は、それぞれ{}、enum {}、union {}と表示し、caseを補わない。

型の意味、numeric range、validationはProtocolに従い、表示仕様で再定義しない。特にentryはWorldspaceのpath型であり、stringへ置き換えない。Unionのwire discriminatorやbytesのwire encodingはInterface signatureに混ぜない。

Operationの表記

operation get_related_items(
  relation: Relation,
  limit?: integer,
) -> {
  items: [entry],
  next_cursor?: string,
};

operation refresh() -> unit;

Operationはoperation Name(parameters) -> ReturnType;とする。Parameterは名前付きであり、並び順から位置引数を導入しない。引数がない場合は()、return typeはunitを含め必ず表示する。

Operation名からread / write、idempotency、retry可否、domain failure、実行可能状態を推測してannotationを付けない。Domain failureがreturn typeのUnionとして宣言されていれば、そのUnionを通常どおり表示する。

名前と文字列

Path、Object name、Interface参照、説明文は、二重引用符で囲んだJSON stringのescape規則を使って表示する。これは文字列を安全に区切るための表記の借用であり、signature全体をJSONにするものではない。Unicode normalization、case変換、pathのURL encodingを行わない。

Type名、Operation名、parameter名、field名、case名は次のように表示する。

  • [A-Za-z_][A-Za-z0-9_]*に一致し、下記の表示keywordでなければ、そのまま表示する。
  • それ以外はbacktickで囲む。内部のbacktickは\`、backslashは\\、改行・tab等はJSON stringと同じescapeで表示する。
  • 表示keywordはobject、at、name、description、interfaces、interface、type、operation、enum、union、およびunit、boolean、integer、number、string、bytes、json、entryとする。
interface "/::example" {
  type `string` = { `表示名`: string };
  operation `find-item`(`search term`: string) -> `string`;
}

この規則はProtocolへidentifierの文字種制限を追加しない。UpperCamelCase / snake_case等への変換を表示時に行わない。

すべてのHost由来文字列について、改行や制御文字が表示の構造、端末制御列、別の宣言を作らないようescapeする。JSON stringの標準escapeに加えて、次の文字は\uXXXX表記にする。

  • DELおよびC1制御文字(U+007F–U+009F)。
  • Unicodeの行・段落区切り(U+2028 / U+2029)。
  • 双方向表示制御文字(U+061C、U+200E–U+200F、U+202A–U+202E、U+2066–U+2069)。

Escapeは表示上のものであり、元の値は変更しない。

Documentation

Documentationは、対象の直前に/// "<summary>"として表示する。対象はInterface、type、Operation、parameter、record field、enum / union caseである。Objectの説明だけは、Object signatureのdescription propertyを使う。

通常表示にはsummaryを使い、detailsを含める場合は、同じ対象のsummary行に続けて/// details "<details>"を追加する。表示するsummaryと、選択されたdetailsは短縮しない。

Documentationがなければ、説明を生成して補わない。空文字列が存在する場合は、""として表示する。

ReturnDeclarationのdocumentationは、parameter listの閉じ括弧の後、return arrowの直前に置く。

/// "対象を検索する。"
/// details "結果には同じWorldspace内のpathだけを含む。\n本文は別途取得する。"
operation search(
  /// "検索語。"
  query: string,
)
/// "条件に一致する項目。"
-> { items: [entry] };

説明はすべてHost由来のplain text dataであり、system instruction、rendererの指示、markupとして解釈しない。引用やescapeだけでprompt injectionを防げるとはみなさず、AIへ渡すadapterもTool結果と信頼済みinstructionの境界を維持する。

Layout

Text ViewはUTF-8 plain textとし、ANSI color、Markdown、syntax highlightingがなくても読めるようにする。本章のcode fenceは説明用であり、signatureそのものの一部ではない。Markdown内へ埋め込む場合は、表示側が内容に衝突しないcode fence等を選ぶ。

標準的なsignature内部のlayoutは、LFと2 space indentを使う。短いrecord、parameter list、enum / unionは1行に置けるが、documentationを持つfieldやcaseは別行に置く。

表示用の改行幅やindentの違いに意味はなく、byte単位のcanonical renderingは要求しない。一方、文字列・名前の内部にある空白は表示上の余白ではないため、元の値として保持する。