edit | blame | history | raw

Shared Content Publisher V3.1

项目级、声明式、失败关闭的内容发布器。它不内置行业、批次、任务或 attempt 名称;生产与测试均通过同一个严格 JSON 配置和同一个 CLI 入口运行。

python -m shared_content_publisher --config <batch-config.json> --validate-only
python -m shared_content_publisher --config <batch-config.json>
python -m shared_content_publisher --config <batch-config.json> --read-direct-current
python -m shared_content_publisher.postcommit_archive --config <archive-config.json>
python -m shared_content_publisher.postcommit_archive --rollback-config <authorized-rollback-config.json>

核心边界:

  • 首次正式写入是 exclusive lock;持锁后、任何 ledger append 前,再次完整校验 config、根/卷、ledger/current、prior manifest+self、candidate exact-set、link/evidence 与历史树,并重新推导唯一 sequence。
  • canonical_audit_idreview_handoff_id 是不同字段和不同 ID 域;release preimage 只使用 canonical audit。
  • ledger 的 next event/attempt sequence 从精确当前 ledger 推导并与配置声明交叉验证;同一个公共验证器逐行绑定全部 17 列、精确状态回执、严格递增 UTC 和每阶段 PID+UUID 进程实例身份。
  • 每个终态持久化 SHARED_CONTENT_PUBLISHER_ATTEMPT_EVENT_CHAIN_V1 规范化事件链的 SHA-256、行数、起止 UTC 和逐阶段进程身份;正常提交、幂等重放、回滚与恢复均复用同一验证入口,任一列漂移均不得返回 IDEMPOTENT_COMMITTED
  • 候选先发布到同卷新 release 目录,最后只原子替换既有 cases Markdown 当前成果索引.md;result Markdown 保持为指向 cases 的薄入口,不引入 JSON pointer 或消费者迁移。
  • current manifest 必须精确覆盖发布成员,manifest-self 路径、target exact-set、非空 link/evidence closure 都是硬门禁。
  • 完全相同的已提交调用只有在 config bytes/hash、根/卷、terminal、完整事件链、Markdown 入口、target exact-set、snapshot 与 lock absence 全部一致时才幂等返回;已切换后的有效配置漂移先回滚 Markdown current,再失败关闭。
  • Windows 路径通过长路径前缀读取;每个身份由一次完整读取和一次独立流式 SHA-256 复核。

DIRECT_STABLE_PATH_SET_V1

当既有消费者直接读取稳定 Markdown/CSV 路径、不能迁移到 release 目录时,V3 配置可选择 DIRECT_STABLE_PATH_SET_V1

  • candidate.rows[].formal_relative_path 就是唯一稳定目的地;除唯一 cases 当前成果索引.md 激活点外,只允许落在该行业的 核心文档/manifest/ana-data/result/<industry>/
  • 配置以 expected.destination_prior 同时冻结每个目的地的已有文件身份或 ABSENT 状态;已有和缺失成员可以在同一事务中发布。
  • 行业根第一次建立 canonical current 时可使用严格的 expected.prior.mode=ABSENT_GENESIS_V1prior.rows 必须为空,cases/result current、current state 与全部声明目的地必须实测 ABSENT;发布后仍复用同一锁、恢复锚、事件链、回滚与幂等验证,不以 genesis 名义绕开正式闭环。
  • 完整候选先复制到同卷 fresh staging;提交顺序固定为 payload/core、manifest/result metadata、最后 cases current index。commit_plan.json 明确绑定逐文件顺序,cases current 永远是最后且唯一激活点。
  • 每个已声明目的地在 exclusive lock 后、首个 ledger append 前重读;正式写使用同卷 per-file atomic replace/CreateNew。任何提交边界失败最多执行一次精确逆序回滚:恢复 prior snapshot、删除本 attempt 新建文件,并复核完整 prior stable set。
  • postcommit、replay、recovery 共用目的地 exact identity、candidate/current manifest、scope extra-file、snapshot、terminal 与 17 列 event-chain 验证;稳定路径漂移或 undeclared extra 永远不能返回假幂等成功。
  • 正式 current 消费必须调用公共 read_direct_current_snapshot(),或使用 --read-direct-current 做只读闭环证明。读前要求 publisher lock absent 并冻结 cases current index/current manifest 双身份;读完整目标集后再次要求 lock absent 且双身份不变。锁存在返回 RETRY_PUBLISH_IN_PROGRESS,identity/exact-set 漂移返回 STOP_NOT_CURRENT,均不返回 payload 或 current 标记。
  • 快照、PREPAREDVERIFIED、首个稳定目的地前和每个稳定目的地提交后的 durable prefix 均由一个恢复验证器管理。同 config 新进程先绑定 snapshot、receipt、staging、全部 17 列 event chain 与每个目的地 prior/candidate 真值,再精确恢复 prior 并返回可严格重放的 ROLLED_BACK;合法未完成前缀不再返回 TERMINAL_REPEAT_BLOCKED
  • 正式 attempt receipt 不再逐文件暴露 pre-anchor 半成品。完整 prior snapshot、commit plan、attempt contract 与 canonical anchor manifest 先在由 task/case/batch/run/config 身份唯一推导的同卷私有目录内逐成员 fsync、关闭、回读,再以 no-overwrite 原子目录改名一次发布。原子改名前的可归属残片在 formal prior/ledger 不变时由同 config 安全退役并重建;finalized member、extra 或 official anchor 的篡改返回明确 RECOVERY_REQUIRED,不得盲删或继续发布。
  • MARKDOWN_CURRENT_INDEX_REPLACE_V1 / V2 schema 保持兼容,不改变其 release-directory 行为。

机器可读 schema:

  • batch_config.schema.json:V2 release-directory 策略;
  • batch_config.direct_stable_path_set.schema.json:V3 direct stable-path 策略。
  • postcommit_archive.schema.json:发布成功后的旧目录原子归档及恢复回执。
  • postcommit_archive.rollback.schema.json:仅在独立 AUTH-AUDIT- 绑定后恢复 legacy 原路径。

发布后旧目录归档

正式 current 已由 DIRECT_STABLE_PATH_SET_V1 提交并完成精确回读后,可用独立的
postcommit_archive 协调器把一个完整旧目录原子改名到同卷审计包:

  • 移动前必须完整回放发布器 COMMITTED 状态,并逐行验证旧路径映射、旧树和新正式树;
  • 归档合同、映射表和 manifest 先以 CreateNew 方式形成持久回执锚,目录原子改名是唯一旧目录变更;
  • 重命名前中断保留旧目录,重命名后中断由同一配置验证归档树并补齐终态;
  • source/target 同时存在或同时缺失、回执不完整、旧树/归档树/正式树漂移都进入
    RECOVERY_REQUIRED,不得把不确定状态声明为已归档;
  • 成功终态为 ARCHIVED,同配置完整回放为 IDEMPOTENT_ARCHIVED

归档回放会从冻结的 publisher config 复核完整正式集合(包括所有 core、manifest-self、
cases/result 两入口),并复算 17 列事件链及 lock absence,不只验证 legacy map 覆盖的
目标。若整体迁移随后获得独立回退授权,必须另建严格 rollback config;协调器先绑定原
archive config/terminal、完整正式集合、归档树和授权身份,建立独立回退回执锚后,才可
以一次 no-overwrite 原子改名恢复 legacy 原路径。回退成功与同配置重放分别返回
LEGACY_RESTOREDIDEMPOTENT_LEGACY_RESTORED,原 archive config 不得再次归档。
即使进程在 rollback 目录原子改名后、terminal 发布前中断,重启也必须先重新验证
archive anchor、648 项正式集合、17 列事件链、lock、canonical 645 项及恢复后的 legacy
645 项;任一漂移只返回 RECOVERY_REQUIRED,不得补写或重放成功终态。

正式批次配置由项目管理员在实现审核通过后另行生成,本实现不包含任何真实批次配置。