Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions 20-product-tdd/capture-contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Capture Extension 合同

`inkcre/capture` 是 first-party extension,拥有材料、来源、采集图、收入身份和恢复语义。各平台 Distribution 为所在 Peer 提供这些能力;语言和仓库不决定业务中心。声明支持采集的分发在本 Peer 内完成采集、编辑、本机保存、构图和共享写入,不依赖另一个分发补齐收入流程。

原生 Mac 分发通过 PostgreSQL 原生协议操作共享 info-base。Host 提供连接、同连接事务与标准 Block/Relation/Storage 基础操作;Capture 编排业务事务。Python 仓库拥有权威 schema/迁移的交付,不因此成为运行时采集执行者。其他 Peer 按自身能力读取或提供采集分发。

## 材料与持久图

材料包含提交 UUID `submission_id`、采集时间 `captured_at`、入口 `selection | paste | screenshot | manual`、可缺失的 `origin`、有序 `materials` 和可缺失的 `annotation`。出处的应用 ID、标题和 URL 允许缺失;显式粘贴不推断来源。材料和附注不能同时为空。单次至多 128 份材料,文字与附注 UTF-8 加原图 bytes 累计不超过 32 MiB。

支持 PNG、JPEG、GIF、WebP,验证 MIME、实际格式与解码尺寸。已有支持编码保留原 bytes;系统仅提供原生位图时,由平台分发生成 PNG 后作为本次原图。原文和自己的补充保持可区分,OCR、模型处理不阻塞收入。

| 对象或关系 | 合同 |
| --- | --- |
| 根 Block | `extensions.capture.capture.v1`,JSON 内容包含提交身份 `submission_id`、材料摘要 `payload_digest`、采集时间、入口、出处 |
| 根 → 材料 | 从 `material:0` 连续递增,无重复序号 |
| 文字 | `core.text.v1`,保持原文 |
| 图片附件 | `extensions.capture.attachment.v1`,JSON 内容包含 MIME、可选文件名 |
| 图片附件 → 内容 | 唯一 `content` 关系,目标为 `core.image.v1` |
| 原图 | 标准 PostgreSQL binary storage `-4`,使用标准 `{"blob_id":"…"}` 指针 |
| 根 → 用户附注 | 至多一条 `annotation` 关系,目标为 `core.text.v1` |

读取分发按关系解释顺序和附注,畸形关系显式报错。Web 来源只允许 HTTP(S) 点击。信息属于共享 info-base,读取不依赖采集设备本地路径或原分发存活。

## 收入、事务与恢复

用户确认后在本机冻结 UUID、材料和目标;草稿、待办与确认结果由本机持久化保存。Capture 在事务外完成校验和构图,再于同一数据库连接、同一事务内锁定提交身份、查找现有 Capture 根、写图与原图 bytes。任何写入错误整体回滚。并发重试以 UUID 字符串的 `hashtextextended(value,0)` 取得事务 advisory lock。

Capture 根的 `submission_id` 与 `payload_digest` 用于提交恢复。相同身份和摘要返回现有根;摘要冲突保留本机材料并要求处理。Extension 不拥有独立共享表,也不在 Extension state 中累积提交回执。图和原图使用既有 Block/Relation/Storage;本机确认后保存根 ID 和时间,再清理本机材料。

材料指纹为规范 JSON 的 SHA-256:键排序、紧凑 UTF-8、缺失可选值为 null、时间 UTC 六位小数、图片数据替换为 bytes SHA-256。文本换行及 Unicode 组合形式不变,材料顺序不变。本机时间冻结为毫秒精度,再规范化为上述时间文本。

网络超时不证明提交失败。恢复查询原目标中的 Capture 根并核对材料摘要;没有根时以原身份重试。明确提交成功或恢复核对成功前保留本机材料。更改当前连接不重定向待办;用户再次采集同内容使用新 UUID,不按内容去重。已经在本机确认的记录不再发送。提交响应丢失后、恢复前又由其他 Peer 删除根的窄窗口不提供防重建保证;不为此保留永久回执或墓碑。

## 平台分发与启停

Capture 的本机草稿格式、待办状态机、系统采集策略和界面属于其平台分发。Host 提供应用、窗口/命令挂载、凭据、持久目录和扩展生命周期。停用某个 Peer 的 Capture 不删除材料或改变共享 schema。

Swift 原生分发以 `swift_bundled` 标识,随签名应用携带精确 producer manifest;扩展版本独立于应用版本。未配置数据库时可本机运行。本机运行开关只控制本机入口与任务,不隐式修改当前或其他信息库的共享参与。首次加入创建缺失的参与记录,已有选择必须读取且不得覆盖;加入成功后,重连不重建已移除的参与,不用缓存启用值覆盖共享意图。用户可以明确指定信息库,选择并启用当前应用携带的版本;该操作允许更新旧版本选择或重新创建缺失的参与,无需动态下载。共享写入前仍复核精确版本与启用意图,本机启动不覆盖其他 Peer 的停用决定。

此 Capture 合同尚未发布,采用一个原生收入协议,不提供旧 HTTP 提交 API、历史本机格式迁移。平台通用数据库协议仍保持原生与 HTTP 的权限对等;未来 HTTP 收入实现须明确自己的事务入口。
12 changes: 11 additions & 1 deletion 20-product-tdd/extension-release-and-installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ Extension 发布者、Registry、开发工具和宿主共同消费本契约。Re

prepare、upload、publish 一次针对一个 Native Release。只有它自己的全部原生对象齐备时才可公开,检查与提交之间改变产物身份或关联必须重新验证。发布 Python 不等待 MF,发布 MF 不等待 Python。已发布的坐标及产物身份不可覆盖;相同请求可幂等重试,冲突需要新版本。文档不使缺少可执行产物的分发成为可安装版本。

共享参与协议中的 Distribution 是开放的非空字符串,不枚举语言、打包方式或现有宿主。各宿主报告自己支持的格式,并在实际加载边界校验;一个新宿主不需要修改共享数据库的格式白名单。Registry 只对自己能交付的产物提供安装能力。

Extension 不拥有独立共享数据表。资料使用 Block/Relation/Storage,共享配置与业务状态使用已有 Extension config/state;仅本机需要的草稿、队列和运行状态保存在本机。

## 随签名应用交付的原生分发

`swift_bundled` 表示宿主签名应用携带的原生分发。producer manifest 定义 Extension Name、分发格式和精确版本,由模块资源与签名应用一起交付。宿主只运行实际携带的模块,不下载动态代码、不替换精确选择;需要其他版本时明确要求更新应用。其产物供应链是签名应用,不把不存在的 Registry 发布或原生热加载能力作为已完成事实。

此分发仍有真实启停生命周期和 Peer 参与记录;应用关闭只停止实际运行,不撤回共享启用意图。未配置数据库时可离线使用扩展。首次加入与重连须区分:首次事务内创建缺失的参与,冲突则读已有值;加入或明确启用成功后,重连不重建已移除记录、不重放离线开关。用户在线明确启用可以重新创建本 Peer 的缺失参与;离线操作只改变本机运行并显示共享意图尚未更新。共享写入前复核参与选择和启用意图。Python/MF 原生产物继续按各自 Registry 发布流程交付。

## 部署共享状态与 Peer 参与

部署中一个插件只有一个逻辑身份及其共享配置、业务状态。安装选择属于 `Peer × Extension`:该 Peer 选择一种宿主支持的 Distribution 及精确版本,并保存自己的启用意图。数据库保存这些持久事实;运行端报告实际加载的分发、版本和运行结果。
Expand Down Expand Up @@ -43,7 +53,7 @@ prepare、upload、publish 一次针对一个 Native Release。只有它自己

宿主在改变运行状态前校验目标坐标、发布状态、元数据、原生产物和 SDK 条件。启用成功须包含完成启动和相应副作用;持久化失败需要按宿主生命周期清理或报告真实未收敛状态。保存目标版本不等于升级完成。

显式启用和停用命令先保存参与意图,再应用运行变化;运行失败保留意图并报告实际错误,不以运行成功回调重新写入意图。自动恢复只消费已有意图,不能将用户已撤回的启用写回。宿主串行处理同一参与记录的生命周期,并在异步初始化或激活后复核精确选择与启用意图;若意图已撤回或版本已变,清理迟到实例,不将它报告为当前运行结果。该串行边界只协调当前宿主,不能排除其他已准入客户端的数据库写入,也不保证持久意图与进程状态瞬时原子切换。
针对共享参与的显式启用和停用命令先保存参与意图,再应用运行变化;运行失败保留意图并报告实际错误,不以运行成功回调重新写入意图。原生宿主的本地停用先保存本机停用状态并停止运行,再尝试更新共享意图;连接、凭据或授权错误不能阻止本机停止,也不能将共享更新报告为成功。自动恢复只消费已有意图,不能将用户已撤回的启用写回。宿主串行处理同一参与记录的生命周期,并在异步初始化或激活后复核精确选择与启用意图;若意图已撤回或版本已变,清理迟到实例,不将它报告为当前运行结果。该串行边界只协调当前宿主,不能排除其他已准入客户端的数据库写入,也不保证持久意图与进程状态瞬时原子切换。

离线 Peer 只能接收待应用选择,不能被宣称已停止旧实例或已运行新版。租约过期不证明进程停止。Python 等宿主若安装会修改共享原生依赖环境,应暂停该 Peer 的执行,安装后从新进程启动;只停目标插件不足以证明其他已加载依赖安全。应用失败应报告失败或待处理,不能假定自动恢复旧环境或撤销插件已经执行的业务迁移。具体进程、打包和恢复操作留在宿主本地文档。

Expand Down
37 changes: 37 additions & 0 deletions 20-product-tdd/local-files-contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# 本地文件扩展合同(候选 v1)

`inkcre/local-files` 将指定 Peer 可访问的文件持续收入同一 info-base。执行分发拥有目录访问、监视、提取与对账;读取分发解释同一份图。原文件留在原 Peer 的文件系统,数据库保存已提取正文和位置引用。其他 Peer 阅读正文无需原 Peer 在线。首版不提供原件传输、备份、OCR 或历史版本。

## 位置与来源

原件位置为 `inkcre-peer-file://<peer UUID>/<机器绝对路径>`。例如 `inkcre-peer-file://a143b185-f43d-47d1-8ef7-1d3857284b01/Users/alice/note.md`。authority 是 Peer UUID,path 是绝对路径;空格、中文、`#`、`?` 按 URI 编码。禁止凭据、端口、query、fragment 和 NUL。URI 不授权文件访问,也不注册系统 URL handler。只有匹配 Peer 的执行分发可以按现有文件权限打开原件;其他读取端显示位置,不把它当作可远程下载的 URL。

目录 Source 类型是 `extensions.local_files.directory.v1`,config 包含 `peer`(UUID)、`path`(绝对目录路径)、`enabled`(布尔值),不接受其他字段。其普通采集参数为空对象。Source 的 `core.source.v1` 锚点通过 `manages` 关系指向本来源管理的文件资料。只领取 `config.peer` 等于当前 Peer 且已获得目录访问能力的 `core.source.collect.v1` Job。读取分发只注册 Resolver,不注册无法执行的 Source 类;catalog 中存在类型不代表本 Peer 具有执行能力。

FSEvents 等平台通知触发被动核对;手动扫描使用普通 Source Job。两者执行相同对账逻辑。同一 Source 串行运行。Source 与原信息库及 Peer 绑定,切换当前连接不迁移来源。暂停停止监视及后续提交;移除经确认后删除 Source,已经收入的图保留。

## 文件资料与正文

文件根 Block 使用 `extensions.local_files.file.v1`,content 为以下 JSON。成功提取后恰有一条 `body` 关系指向 `core.text.v1`;首次提取失败时可没有正文。用户批注或其他组织关系不属于本扩展更新范围。

| 字段 | 合同 |
| --- | --- |
| `location` | 上述位置 URI。位置可以随文件重命名改变,Block ID 保持稳定。 |
| `format` | `pdf`、`docx`、`markdown`、`org`、`html`、`text`。 |
| `identity` | 可省略;含 `volume` 字符串、`number` 非负整数、`created` UTC 时间,用于证明同一文件在原 Peer 的移动。它不是内容摘要或跨 Peer 身份。 |
| `available` | 最近完整核对时原件是否存在;无法访问目录不等于不存在。 |
| `observed_at` | 此状态的 UTC 观察时间。 |
| `revision` | 可省略;最后成功正文对应的 `sha256`(原始文件字节)、`extractor`(提取实现版本)、`extracted_at`(UTC)、`scope`(`text`、`text_layer`、`main_document`)。 |
| `issue` | 可省略;当前提取失败的可读原因。失败不能清空旧正文或替换成功修订。 |

更新先按本来源中的当前路径匹配,以支持编辑器原子保存。旧位置消失且系统身份唯一证明重命名时更新原资料;否则创建新资料,不能依据内容相同合并两个文件。身份需持久保存,重启后仍可核对。摘要只判断修订。

单份文件元数据、正文和关系在一个事务中写入。提交回包丢失后重新读取共享图,避免重复创建。删除原件保留最后成功正文,将 `available` 改为 false;这不是软删除或回收站。只有完整枚举成功且目录仍可访问,才可认定原件缺失。目录离线、权限失败、取消扫描不得批量标记缺失。断网后重连核对当前文件,不承诺保存离线期间出现又消失的文件。

Source state 包含最近完整扫描时间 `scanned_at`、失败文件数 `errors`、可选 `issue`。部分提取失败仍完成目录核对,但主动 Job 以 failed 关闭并呈现失败数量;取消、超时按普通 Job 终态处理。

## 文字提取范围

PDF 提取文字层并分隔页面;无文字层、加密和损坏分别报告。DOCX 首版提取主文档文字与表格单元格,不含脚注、批注等附属内容;读取界面须呈现 `main_document` 范围。Markdown、Org、纯文本保留原语法和换行,不执行代码或 include。HTML 只解析本地 DOM,剔除脚本、样式与模板,保留基本段落,不执行脚本或下载外链。

首个 Swift 分发的 extractor 为 `mac-native-text.v1`。输入上限 64 MiB,输出 UTF-8 正文上限 8 MiB;超限报错,不截断后标成功。空白文本允许为空正文,但 PDF/DOCX 没有可提取文字是失败。文本支持 UTF-8、带 BOM 的 UTF-16;不能可靠解码时报告失败。
5 changes: 4 additions & 1 deletion 20-product-tdd/unit-topology.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Define cross-unit technical boundaries and ownership so changes do not leak resp

## Database Peer Topology

- `impl-py`, `impl-ts`, and future units are peer nodes; frontend/backend hierarchy is not
- `impl-py`, `impl-ts`, `impl-swift`, and future units are peer nodes; frontend/backend hierarchy is not
part of the durable topology.
- Native PostgreSQL and PostgREST are transports over one admitted database protocol, not
separate semantic authorities.
Expand All @@ -22,6 +22,9 @@ Define cross-unit technical boundaries and ownership so changes do not leak resp
- Peer equality does not imply identical execution ability. A business facade may execute
locally on a capable Peer or delegate one exact synchronous capability to another live
Peer without turning the deployment into a fixed frontend/backend hierarchy.
- `inkcre/capture` 是 first-party extension,拥有跨平台的材料、采集图与收入语义。Mac 原生分发在本 Peer 内完成采集、持久待办、构图与共享写入;Host/Core 提供通用运行和数据库能力。
- `inkcre/local-files` 拥有目录来源、文件位置引用、正文与持续更新合同。具备文件访问能力的分发直接收入,读取分发解释已存正文,不要求执行 Peer 在线;见[本地文件合同](local-files-contract.md)。
- Mac 使用 PostgreSQL 原生协议,Web 按浏览器运行能力使用 PostgREST;传输选择不划分 Peer 业务权威。仓库维护位置不构成运行时流水线。具体语义见[Capture Extension 合同](capture-contract.md)。
- Shared actors,assets,trust boundaries and proportional security classification use the
[Security Boundary Model](security-boundary-model.md)。Each Unit still owns its executable
admission,rendering,runtime and deployment mechanics。
Expand Down
2 changes: 2 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
- [Cross-unit contracts](../20-product-tdd/cross-unit-contracts.md)
- [跨 Peer 可观测性契约](../20-product-tdd/observability-contract.md)
- [Twitter 归档信息与接入契约](../20-product-tdd/twitter-archive-contract.md)
- [主动采集持久化契约](../20-product-tdd/capture-contract.md)
- [本地文件位置与持续收入合同](../20-product-tdd/local-files-contract.md)
- [Knowledge capability contract](../20-product-tdd/knowledge-capability-contract.md)
- [Semantic retrieval and Peer capabilities](../20-product-tdd/semantic-retrieval-and-peer-capabilities.md)
- [Feature retrieval and media interpretation](../20-product-tdd/feature-retrieval-and-media-interpretation.md)
Expand Down
Loading