239 lines
15 KiB
Markdown
239 lines
15 KiB
Markdown
# 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](3-protocol.md)の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規則を使用する。単純な成分も引用してよい。
|
||
- `::`と`#`は引用符の外側でだけ境界となる。区切りの前後に空白を出力しない。
|
||
|
||
```text
|
||
"/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
|
||
|
||
```text
|
||
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
|
||
|
||
```text
|
||
/// "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)`は異なる表示になる。
|
||
|
||
```text
|
||
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の表記
|
||
|
||
```text
|
||
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`とする。
|
||
|
||
```text
|
||
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の直前に置く。
|
||
|
||
```text
|
||
/// "対象を検索する。"
|
||
/// 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は要求しない。一方、文字列・名前の内部にある空白は表示上の余白ではないため、元の値として保持する。
|