Skip to content

Commit 2785b56

Browse files
committed
feat: govern workspace temporary artifacts
1 parent 197d5ca commit 2785b56

41 files changed

Lines changed: 2234 additions & 121 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎README.md‎

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,23 @@ devcodex doctor
449449

450450
然后完全关闭旧任务并新建任务。完全访问可以作为短时诊断对照,但不是默认修复方案。
451451

452+
### 为什么 `.devcodex` 或工作区里会出现很多 `tmp` / `.tmp-*` 目录?
453+
454+
这通常来自旧版安装备份、测试/审计脚本自行拼接路径,或任务把一次性脚本放进了需求目录。集中工作区的新写入只允许进入:
455+
456+
```text
457+
<workspace>/.tmp/devcodex/
458+
```
459+
460+
这里的 `<workspace>` 是当前打开工作区的物理根;无集中布局的单项目把项目根视为 workspace。从工作区根、项目子目录或 `.devcodex` active-root 调用时必须得到同一个根。旧 `.devcodex/workspace/.tmp/` 与 `<project>/.devcodex/.tmp/` 只作为遗留只读输入报告,不能继续写入。先执行:
461+
462+
```bash
463+
devcodex tmp status
464+
devcodex tmp prune --dry-run
465+
```
466+
467+
只有带 `WorkspaceTempManifestV1`、owner/type 可识别、TTL 已到期、没有活动 lease,且备份事务已完成的对象才会成为候选。确认后再执行 `devcodex tmp prune --apply`。一次状态检查的 canonical 文件/目录与 legacy 目录观察共用 10,000 项相关对象上限;四个 artifact 分区根不能被 manifest 整体认领,unknown owner、共享/损坏 lease、未知分区、lock、reparse point、路径逃逸、不完整备份和扫描截断都会保持 blocked。DevCodex 只拥有 `.tmp/devcodex/`:`.tmp/` 容器、`.tmp/<other-producer>/`、工作区根的 `tmp/.tmp-*` 以及 `.tmp.drive*` 外部传输 spool 都不进入 DevCodex ownership、blocked 列表或 `--apply` 删除集合;它们必须由各自生产者盘点并取得独立删除授权。
468+
452469
## 更新
453470

454471
```bash
@@ -464,7 +481,7 @@ devcodex --version
464481
npm uninstall -g devcodex
465482
```
466483

467-
## 运行态检查
484+
## 运行态与临时产物检查
468485

469486
需要排查空间占用或旧电脑遗留的运行态时,可以查看各类状态的负责人、文件数、体积和最后使用时间:
470487

@@ -475,6 +492,16 @@ devcodex runtime prune --dry-run
475492

476493
清理命令默认只预览。确认列表后使用 `devcodex runtime prune --apply`;它只清理达到保留期限的原子写入临时文件,不会自动删除锁文件、当前任务状态或无法识别的文件。
477494

495+
工作区临时产物使用独立命令,不与 `.runtime-state` 混删:
496+
497+
```bash
498+
devcodex tmp status --json
499+
devcodex tmp prune --dry-run
500+
devcodex tmp prune --apply
501+
```
502+
503+
`tmp prune` 无参数时等价于 `--dry-run`。所有布局的 canonical root 都是 `<workspace>/.tmp/devcodex/`,按 `runs/cache/backups/leases/quarantine/manifests` 分区;安装器和宿主配置备份会先验证 canonical/partition 非 reparse,再写入 `backups/<project>/` 并登记保留期限。对象删除时会同步回收其唯一且已过期的 lease;共享 lease 保持 blocked。旧 `.devcodex/**/.tmp` 和没有 manifest 的历史内容只报告,不会被自动迁移或删除。
504+
478505
## 生效方式
479506

480507
安装或更新 DevCodex 后,npm 会在安装生命周期中刷新用户级宿主适配。已打开的宿主会话会继续使用它启动时已经加载的版本,不会被更新过程强制终止;更新后的配置由新会话读取,因此完成安装或更新后请重新打开一个新会话。

‎changelogs/unreleased.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
66
## 当前未发布实现候选
77

8+
- **工作区临时产物统一治理 v0.1.1-candidate(PI-241 / PF-290)**:所有布局统一使用当前物理工作区 `<workspace>/.tmp/devcodex/`,旧 `.devcodex/workspace/.tmp/` 与 `<project>/.devcodex/.tmp/` 仅作只读迁移输入;DevCodex 不接管 `.tmp` 容器、其他 producer、根级 `tmp/.tmp-*` 或 Drive spool。`WorkspaceTempManifestV1` 以 owner/type/project/producer/TTL/lease/backup transaction 约束清理资格,分区根不可整体认领,unknown owner、未知分区、lock、reparse、路径逃逸、不完整备份和有界检查截断全部 fail closed。新增 `devcodex tmp status|prune [--dry-run|--apply] [--json]`,prune 默认预览;安装器与 Grok adapter 备份统一写入 `backups/<project>/` 并登记 manifest,content-root 删除隔离区进入 canonical `quarantine/` 且回滚不信任回执内 manifest 路径,package projection 的短期锁/回执迁到按物理源码根隔离的 OS temp;10 个已定位的 OS-temp 测试生产者在成功与异常退出时统一自清理,63/63 个 `mkdtempSync` 生产者均具备回收信号,定向回归前后 15 组前缀计数净增长为零。既有 `runtime status/prune` 与 SkillRoute 摘要语义不变。V27、README FAQ、输出路径规范、数据库一次性脚本规则、Profile 01/02/04/05/06/07、package files 与聚焦/CLI 回归同步更新;历史 57 个目标及本轮用户精确授权的 8 个外部目录均已清理,新根的 742 个普通文件逐文件 SHA-256 一致,3 个 retain manifest 仅重绑定 targetPath,旧源未删除。本条仅为未发布候选,不代表 tag/registry/GitHub Release 已形成。
89
- **v1.17.3 Cursor Windows Hook、SkillRoute 恢复与发布安全闭环(PF-286~PF-289)**:Hook adapter 在 JSON stdin 边界只剥离一个前导 U+FEFF,保留双 BOM、畸形 JSON 与超限帧的失败关闭;Cursor Windows 的 `/X:/...` / `\X:\...` 工作区路径在文件系统调用前规范化,同时保留 UNC、POSIX 和相对路径语义。Cursor 导入的 DevCodex Claude Hook 通过强 Cursor 指纹返回事件合法的最小 no-op,由专用 Cursor Hook 单独执行生命周期,避免同一请求重复推进。专用入口同时把 Cursor 官方 `MCP:<tool_name>` 规范为路由可识别名称,并在 `preToolUse` 拒绝时把生命周期生成的精确 `Next call (exact)` 投影到 `agent_message`;不依赖 `beforeSubmitPrompt` 的 allow 响应传递官方 schema 不支持的动态上下文。Resolver Skill 和安装态 verifier 会阻止模型臆造 binding 或遗漏恢复契约。用户级升级合并器识别 `devcodex/runtime-<generation>/.../lifecycle-cursor-compatible.cjs`,Cursor/Claude 活动事件只保留一个当前 generation,同时保留用户第三方 Hook 与 rolling-upgrade retained runtime;受管 ownership 使用路径与精确文件名边界,compatible helper/preload/wrapper 进入 Claude/Cursor 专用身份,Cursor verifier 精确验证 current wrapper、Plugin path 与 Resolver anchors。共享 runtime digest 与其他四宿主入口保持发布基线;真实 Cursor IDE 因订阅额度耗尽仍未做模型回放,Local 保持 Beta,Cloud/模型 replay 保持 `UNVERIFIED`。正式已发布事实仍以 Git tag、npm registry 与 GitHub Release 为准。
910
- **v1.17.2 生产回执绑定与跨宿主 Hook 隔离修复**:发布后 R7 在 Windows 源码树发现生产 Grok 探针用 CRLF 源码重算 `RuntimeGenerationManifestV1`,与 npm Linux 发布包的 LF 安装代次不同;Codex/Grok production S15 现统一从 committed `global-host-receipt.json` 绑定 runtime 与 shared Skill 根,校验版本、摘要与物理边界,Grok launcher 不再内部重复推演。继续实装复验又发现 Grok 1.0.0 默认扫描官方 Cursor 扁平 `~/.cursor/hooks.json`,其兼容解析器会报 matcher group 结构错误并干扰回合;所有 DevCodex 管理的 Grok 子进程现统一以环境变量关闭 Cursor Hook 外部兼容,且 `inspect --json` 必须证明来源为 `env`、发现列表中不存在 `.cursor`。Cursor 官方 Hook schema、用户 Grok 持久配置及直接运行 `grok` 的偏好均不改变;其他五宿主、Cursor Cloud 与模型 replay 的能力边界也不升级。
1011
- **v1.17.1 六宿主 HOME 隔离修复**:`global-adapters apply --home <dir>` 将显式 HOME 作为 CLI 隔离权威,在目标解析前屏蔽 Copilot/Claude/Codex/Gemini/Grok/Cursor、共享 Skill 根与 VS Code MCP 的 ambient 路径覆盖;空值/纯空白 `--home` 失败关闭,未传 `--home` 时保留原环境变量语义。事务后调用 Grok 官方 CLI 时,再把 committed `GlobalHostTargetV1.root` 绑定为派生环境的 `GROK_HOME`,且不修改 ambient process env;target root 缺失时返回 typed failure。单测覆盖六宿主 root、12 个路径覆盖键、原环境不变、legacy 路线和 malformed target;真实探针证明隔离 HOME 6/6 committed、12 个 ambient 目标零创建、真实五个既有宿主加 Grok 的 34 个受管条目快照不变。同步修复 package-lock 根版本漂移并扩展版本校验器。Cursor Local 继续为 Beta,Cloud 与模型驱动 replay 继续为 `UNVERIFIED`。

‎content/duplication-inventory.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"schemaVersion": "ControlContentDuplicationInventoryV1",
3-
"sourceBundleDigest": "33b2f4cbc2d9f82c21e29103e50e634665f200f03c498168230613d837de7b4a",
3+
"sourceBundleDigest": "968e656c67f8112a80cc751aba26031218d6f4009daefd04cb9bf10734cf2558",
44
"thresholds": {
55
"minParagraphChars": 100,
66
"sectionThreshold": 0.94,

‎content/instructions/02-output-paths.instructions.md‎

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ version: 1.17.3
1313
> - 集中布局全工作区:`<工作区根>/.devcodex/workspace/`
1414
> 🔴 当 `<工作区根>/.devcodex/layout.json` 启用 `workspace-namespace` 时,进入集中布局;不存在时保持旧布局兼容。
1515
> 🔴 禁止在当前 active namespace 根下创建规范路径之外的一级目录。
16-
> ⚠️ `init` 命令自动将 `.devcodex/.memory/` 加入 `.gitignore`;`requirements/`、`bugs/`、`reports/` 等产物目录按需提交。
16+
> 🔴 临时产物不属于任务正式产物树:所有布局的唯一写根为 `<工作区根>/.tmp/devcodex/`;无集中布局时项目根即工作区根。旧 `.devcodex/workspace/.tmp/` 与 `<项目根>/.devcodex/.tmp/` 仅作只读迁移输入。
17+
> ⚠️ `init` 命令自动将运行记忆与 canonical `.tmp/` 加入 `.gitignore`;`requirements/`、`bugs/`、`reports/` 等正式产物目录按需提交。
1718
1819
## 语言规则
1920

@@ -56,7 +57,6 @@ version: 1.17.3
5657
│ ├── *-接口验证.http # 🔴 强制(有接口变更时)
5758
│ ├── *-接口验证.cjs # 🔴 强制(有接口变更时)
5859
│ ├── .memory/sessions.md # 🔴 强制(需求级记忆)
59-
│ ├── .tmp/ # 临时文件(.gitignore 排除,可放仅本地执行的一次性脚本/配置)
6060
│ └── reports/<agent>/YYYYMMDD/ # 🔴 强制(需求级报告)
6161
├── bugs/<中文描述>/ # Bug 修复产物(fix)
6262
│ ├── 00-问题概况.md # 🔴 条件强制(Bug 报告方原始输入;SimpleTaskFastPath 可 N/A)
@@ -85,7 +85,7 @@ version: 1.17.3
8585
| **任务隔离** | 每个 `<中文描述>/` 目录只服务一个明确任务 |
8686
| **禁止非规范路径** | 当前 active namespace 根下只允许上述目录树中的一级目录 |
8787
| **scripts/ 触发条件** | 任务目录(requirements/<任务>/ 或 bugs/<任务>/)下有共享辅助脚本(数据迁移/数据填充/自动化验证等)时创建对应 `scripts/` 子目录;默认禁止放入业务逻辑或网络请求。`*-接口验证.cjs` 属规范强制产物,存放任务根目录(非 scripts/)。除用户明确要求写入业务仓库/规范仓库外,需求辅助脚本默认归档到对应任务目录 `scripts/`,并在报告说明用途与执行边界;新增脚本前执行 `OneOffRequirementScriptPlacementGate`,一次性需求脚本、入库脚本、迁移辅助或验证脚本优先放入对应任务目录,只有长期复用、发布、维护或运维入口才进入项目通用 `scripts/` |
88-
| **本地临时脚本豁免** | 仅本地执行、不会提交发布链路的临时脚本/配置可放入任务目录 `.tmp/local-scripts/` 或保持未提交;允许直接使用局部常量、敏感信息和网络请求,但不得伪装成共享正式产物 |
88+
| **本地临时脚本豁免** | 仅本地执行、不会提交发布链路的临时脚本/配置必须进入 canonical temp 的 `runs/<project>/<producer>/<run-id>/local-scripts/` 并登记 `WorkspaceTempManifestV1`;禁止在 requirements、bugs、源码或 active-root 下另建 `.tmp/tmp/temp`。允许直接使用局部常量、敏感信息和网络请求,但不得伪装成共享正式产物 |
8989
| **入口类型分类** | CP1 / 问题确认前必须先区分纯新需求、需求变更和 Bug 问题:纯新需求落 `requirements/<需求>/00-需求概况.md`;需求变更落 `requirements/<需求>/00-需求变更概况.md` 并回写目标需求真相源;Bug 落 `bugs/<问题>/00-问题概况.md`。不得把 Bug 或需求变更塞入纯新需求概况 |
9090
| **00-需求概况 触发条件** | 仅当纯新需求来自用户、运营、老板、客户、内部使用方、PRD/Word、原型、截图、会议纪要、聊天记录或后续补充消息时创建/更新;它是需求方原始输入模板,只记录新增能力、背景、痛点、期望结果、样例、附件和不确定点,不写验收、测试、数据库字段或接口 Schema |
9191
| **00-需求变更概况 触发条件** | 当用户调整/修改/补充已确认需求、规则、流程、页面、字段口径、优先级或范围时创建/更新;必须锚定原需求基线、变更前后差异、影响范围、明确不变内容、兼容/迁移/回滚/告知和目标真相源 |
@@ -105,6 +105,25 @@ version: 1.17.3
105105
| **强制产物首轮完成** | 默认 00/01/04 在首轮会话结束前按 ArtifactDecisionMatrix 处理:需要则创建/更新,命中 SimpleTaskFastPath 或子类型豁免则记录 `N/A + skipReason`;PC0~PC7、Profile、报告、记忆、安全底线和必要验证不可省略;02-技术方案.md、实施方案/ 与 `06-关键决策.md` 按条件触发;services/ 在 CP2 后按需创建;强触发条件命中时 `05-实施进度.md` 必须在执行前初始化 |
106106
| **需求归档(v1.9.3+)** | 已完成且不再活跃的需求目录下创建空文件 `.archived`;CP gate 扫描跳过含此标记的需求,避免历史需求全局阻断 dev 工作流 |
107107

108+
## 临时产物生命周期
109+
110+
```text
111+
<workspace-temp-root>/ # <workspace>/.tmp/devcodex/
112+
├── runs/<project>/<producer>/<run-id>/
113+
├── cache/<producer>/<cache-key>/
114+
├── backups/<project>/<transaction-id>/
115+
├── leases/<run-id>.json
116+
├── quarantine/<timestamp>/
117+
└── manifests/<artifact-id>.json
118+
```
119+
120+
- 新写入必须由 `scripts/lib/workspace-temp-layout.js` 的 workspace-temp resolver 定位,并在写入前由 lifecycle owner 验证 canonical root/partition 非 reparse;禁止自行拼接 project-local `.tmp`,也不得让该 CLI 路径能力污染 SkillRoute 宿主运行时契约。
121+
- DevCodex 只拥有 `<workspace>/.tmp/devcodex/`;`.tmp` 容器、其他 producer 子目录、工作区根 `tmp/.tmp-*` 与外部传输 spool 不得被本 lifecycle 枚举为 owner、阻断、迁移或删除。
122+
- 可清理对象必须具有 `WorkspaceTempManifestV1`、可识别 owner/type、已到期 TTL、无活动 lease,且 backup 事务为 `completed`。
123+
- `devcodex tmp status --json` 只读盘点;`devcodex tmp prune` 默认 dry-run,只有显式 `--apply` 才删除本次检查得到的安全候选。
124+
- canonical 文件/目录与 `.devcodex/**/.tmp` legacy 目录观察共用 10,000 项相关对象上限;`runs/cache/backups/quarantine` 分区根不可被 manifest 整体认领。unknown owner、共享或损坏 lease、未知分区、lock、reparse point、路径逃逸、不完整 backup 和检查截断一律 fail closed,不自动迁移或删除。对象成功删除时同步回收其唯一且明确过期的 lease。
125+
- OS temp 仅限尚无 workspace、全局安装事务或测试隔离;目录必须使用 `devcodex-*` 前缀,并由创建者在 `finally`/收尾阶段清理。
126+
108127
## 报告路径
109128

110129
```text

‎content/skills/dev-database/SKILL.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ description: 数据库开发子类型规范 — Migration 安全策略 + Schema
3737
- 🔴 数据库、MongoDB 或数据操作连接信息默认可按用户提供内容直写或沿用项目既有模式;只有用户或项目明确指定 `config.local.json`、env、`secretRef` 或 secret manager 时,才从对应入口读取,缺失文件或字段时提醒用户补齐
3838
- 🔴 数据补齐、迁移或跨环境写入必须执行 `DataMutationPlan`:范围来自显式清单、需求目录数据源或稳定业务键;跨环境写入不得直接用 source `_id` 匹配目标库,必须在目标环境重新唯一匹配并 dry-run 输出 `source_id`、`target_id`、缺失/重复清单;不能唯一匹配时阻断写库
3939
- 🔴 数据库配置、邮件模板、模块注册、推送配置、权限配置、字典配置等记录跨环境手动迁移必须执行 `DatabaseRecordMigrationExportGate`:只读源环境,导出主记录和引用记录的全字段 JSON/Extended JSON 备份,生成可执行 insert/upsert 脚本、执行顺序、引用完整性校验和目标 dry-run 说明;不得只给单条记录或截图说明
40-
- 🔴 一次性数据脚本默认执行 `OneOffRequirementScriptPlacementGate`,放入对应 requirement/bug/任务目录 `scripts/` 或 `.tmp/local-scripts/`;只有长期复用、发布、维护或运维入口才进入项目通用 `scripts/`
40+
- 🔴 一次性数据脚本默认执行 `OneOffRequirementScriptPlacementGate`:需要留档/复核时放入对应 requirement/bug/任务目录 `scripts/`;纯本地临时执行时放入 canonical workspace temp 的 `runs/<project>/<producer>/<run-id>/local-scripts/` 并登记 `WorkspaceTempManifestV1`。禁止在任务目录另建 `.tmp`;只有长期复用、发布、维护或运维入口才进入项目通用 `scripts/`
4141

4242
## Migration 执行后验证(F-13)
4343

0 commit comments

Comments
 (0)