Skip to content

Commit f136a45

Browse files
committed
fix: clarify workspace setup and status readiness
1 parent 8c2a5d6 commit f136a45

5 files changed

Lines changed: 117 additions & 8 deletions

File tree

‎README.md‎

Lines changed: 92 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@ DevCodex 不替代业务框架、GitHub CI、安全审计或人工评审。它
2323
- [它如何工作?](#它如何工作)
2424
- [适合谁?](#适合谁)
2525
- [5 分钟开始](#5-分钟开始)
26+
- [首次信任提示](#首次信任提示)
2627
- [更新](#更新)
2728
- [卸载](#卸载)
2829
- [生效方式](#生效方式)
2930
- [添加自己的 Skill](#添加自己的-skill)
3031
- [与宿主原生 Skill 共存](#与宿主原生-skill-共存)
32+
- [用户可见交付与链接兼容](#用户可见交付与链接兼容)
3133
- [边界](#边界)
3234
- [许可证](#许可证)
3335

@@ -131,7 +133,41 @@ npm install -g devcodex
131133
devcodex --version
132134
```
133135

134-
安装完成后,重新打开 Codex、Claude Code、GitHub Copilot、Gemini CLI 或 Grok 的新会话。
136+
然后进入你要使用的项目或工作区根目录,初始化 DevCodex 运行态:
137+
138+
```bash
139+
cd <你的项目或工作区根目录>
140+
devcodex init
141+
```
142+
143+
如果你使用的是 `D:\Worker\v2` 这类多项目 workspace,建议在 workspace 根目录执行一次 `devcodex init`,而不是分别在子项目里猜目录。DevCodex 会在 workspace 根目录创建 `.devcodex/layout.json` 与 `.devcodex/workspace/` 基线;后续子项目的报告、记忆会按项目名稳定落到 `.devcodex/<project>/`,Profile 配置会先查项目 overlay,缺失时回退到 workspace 层。
144+
145+
安装和初始化完成后,重新打开 Codex、Claude Code、GitHub Copilot、Gemini CLI 或 Grok 的新会话。
146+
147+
如果 `devcodex status` 提示 `profile missing`,这不代表安装失败,只是当前项目还没有生成 Profile 文档。需要完整 Profile 基线时,可以先预览再生成:
148+
149+
```bash
150+
devcodex profile plan --tier profile-lite
151+
devcodex profile init --tier profile-lite
152+
```
153+
154+
多项目 workspace 中,如果希望所有子项目共用一份基础 Profile,请在 workspace 根目录执行上面两条命令;如果某个子项目需要自己的覆盖配置,再进入该子项目执行。
155+
156+
## 首次信任提示
157+
158+
第一次在宿主里打开新会话时,宿主可能会提示是否信任或允许 DevCodex 管理的 Hooks、MCP、插件或本地命令。请允许 DevCodex-managed 项,然后重新打开一个新会话。
159+
160+
不同宿主的提示形式不完全一样:
161+
162+
| 宿主 | 可能看到的提示 | 建议 |
163+
|------|----------------|------|
164+
| Codex | Hooks、commands、MCP server、trust / allow | 允许 DevCodex-managed 配置 |
165+
| Claude Code | settings、hooks、MCP 或本地命令确认 | 允许 DevCodex-managed 配置 |
166+
| GitHub Copilot | MCP、工具或命令确认 | 允许 DevCodex-managed 配置 |
167+
| Gemini CLI | settings、hooks 或命令确认 | 允许 DevCodex-managed 配置 |
168+
| Grok | plugin、workspace 或本地命令确认 | 允许 DevCodex-managed 配置 |
169+
170+
如果拒绝这些提示,DevCodex 仍可能通过普通指令语义生效,但依赖 Hook、MCP 或插件的能力不会完整。DevCodex 只要求信任它自己管理的配置,不要求接管宿主原生 Skill、个人配置或业务项目指令。
135171

136172
### 第一次怎么用
137173

@@ -200,11 +236,42 @@ npm uninstall -g devcodex
200236

201237
DevCodex 内置 Skill 随安装包一起提供。普通使用者不需要手动配置内置 Skill;新会话开始后,DevCodex 会按请求意图自动选择需要的 Skill。
202238

239+
DevCodex 分两层生效:
240+
241+
| 层 | 位置 | 用途 |
242+
|----|------|------|
243+
| 用户级宿主适配 | 用户 HOME 下的 Codex、Claude Code、GitHub Copilot、Gemini CLI、Grok 配置目录 | 让五个宿主知道 DevCodex 的入口、指令、Hook、MCP 或插件配置 |
244+
| 工作区运行态 | 当前项目或 workspace 根目录下的 `.devcodex/` | 保存当前项目的 Profile、报告、记忆、任务状态和工作区 Skill |
245+
246+
单项目时,运行态通常在:
247+
248+
```text
249+
<项目根目录>/.devcodex/
250+
```
251+
252+
多项目 workspace 推荐在 workspace 根目录执行 `devcodex init`。初始化后,运行态通常是:
253+
254+
```text
255+
<workspace根目录>/.devcodex/
256+
layout.json
257+
workspace/
258+
profile/ # 按需创建:workspace 级 Profile 配置
259+
skills/ # 按需创建:workspace Skill
260+
<project>/
261+
profile/ # 按需创建:项目 overlay
262+
reports/
263+
.memory/
264+
```
265+
266+
这样你在 `<workspace根目录>/<project>` 中开启会话时,DevCodex 有一个清晰、可验证的目录基线,不会把报告、记忆或 Profile 写到不稳定的 legacy 位置。
267+
203268
## 添加自己的 Skill
204269

205-
如果你希望为某个项目增加自己的流程、检查清单或团队约定,在这个项目根目录下创建工作区 Skill。
270+
如果你希望为某个项目增加自己的流程、检查清单或团队约定,可以创建 DevCodex 工作区 Skill。
206271

207-
这里的“项目根目录”就是你用 Codex、Claude Code、GitHub Copilot、Gemini CLI 或 Grok 打开的业务项目目录。
272+
这里的 Skill 属于 DevCodex 工作区层,不是某个宿主的原生 Skill。新会话开始后,DevCodex 会读取它,并可在 Codex、Claude Code、GitHub Copilot、Gemini CLI 和 Grok 中按意图触发。
273+
274+
单项目时,可以放在项目根目录:
208275

209276
```text
210277
<你的项目根目录>/
@@ -216,6 +283,18 @@ DevCodex 内置 Skill 随安装包一起提供。普通使用者不需要手动
216283
intent.json
217284
```
218285

286+
多项目 workspace 时,请放在 workspace 根目录:
287+
288+
```text
289+
<workspace根目录>/
290+
.devcodex/
291+
workspace/
292+
skills/
293+
<id>/
294+
SKILL.md
295+
intent.json
296+
```
297+
219298
例如:
220299

221300
```text
@@ -279,14 +358,23 @@ DevCodex 不扫描、复制、合并、覆盖或删除这些用户资产。即
279358
<你的项目根目录>/.devcodex/workspace/skills/<id>/SKILL.md
280359
```
281360

361+
多项目 workspace 时,把上面的 `<你的项目根目录>` 换成 workspace 根目录。
362+
282363
如果只希望某个宿主单独使用,继续使用该宿主自己的 Skill 或指令机制。
283364

365+
## 用户可见交付与链接兼容
366+
367+
DevCodex 会尽量按当前宿主支持的方式输出报告、记忆和产物链接:宿主支持点击时给出可点击链接,不支持时给出可复制路径。
368+
369+
如果你在宿主日志或调试输出中看到 `profile_load`、`invoke` 等字样,通常表示 DevCodex 正在通过本地工具读取项目 Profile 或调用本地能力;普通使用者不需要手动执行这些内部动作。
370+
284371
## 边界
285372

286373
- DevCodex 不替代业务框架、GitHub CI、安全审计或人工评审。
287374
- 不同宿主的 Hook、指令和插件能力不同;同一工作流在不同宿主中的强制能力可能不同。
288375
- DevCodex 不接管宿主原生 Skill、个人配置或项目指令文件。
289-
- 工作区 Skill 只影响创建它的项目目录。
376+
- DevCodex 安装不会把 `.codex/`、`.claude/`、`.gemini/`、`.grok/`、`.agents/` 或宿主项目指令文件写进业务 workspace;宿主适配写在用户 HOME,workspace 侧只保留 `.devcodex/` 运行态。
377+
- 工作区 Skill 只影响创建它的项目或 workspace。
290378

291379
---
292380

‎changelogs/unreleased.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
> **当前**: v1.15.7 已归档到 `changelogs/releases/v1.15.7.md`;本文件仅保留历史锚点索引与镜像供 validate 探针消费。发版后新实现再写入下方「当前未发布」。
55
66
## 当前未发布实现候选
7+
- **README 首次信任与 workspace 初始化说明 + status 初始化误报修复**:公共 README 补充 `devcodex init`、多项目 workspace `.devcodex/layout.json` 基线、首次宿主 trust/allow 提示、工作区 Skill 路径、Profile missing 不是安装失败以及可选 `profile plan/init`;`devcodex status` 改为基于 workspace layout/runtime 证据判断 `.devcodex` 是否 ready,避免 fresh workspace 已初始化后仍提示 “Workspace runtime not initialized”;CLI 行为测试增加防复发断言。
78
- **v1.15.7 已归档**:SkillRoute MCP schema 与 closeout/rebind 防复发已进入 `changelogs/releases/v1.15.7.md`。
89
- **v1.15.6 已归档**:README 目录导航与 SkillRoute stale receipt 防复发修复已进入 `changelogs/releases/v1.15.6.md`。
910
- **v1.15.5 已归档**:README 产品入口与 `@rocky` 自动推进说明、SkillRoute package runtime portfolio、MCP 来源观测桥接和 runtime contract digest 已进入 `changelogs/releases/v1.15.5.md`。

‎index.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ function inspectProfileState(profileDir) {
372372

373373
const { cmdStatus, cmdProfileInit, cmdDoctor, cmdHelp } = buildCliMaintenanceCommands({
374374
fs, os, path, process, console, c, SOURCES, CODEX_HOOK_COMMAND,
375-
walkDir, isSourceRepo, resolveActiveRuntimeRoot, resolveProfileDir, getLegacyCounts,
375+
walkDir, isSourceRepo, findLayoutInfo, resolveActiveRuntimeRoot, resolveProfileDir, getLegacyCounts,
376376
getCodexConfigState, inspectProfileState, detectProfileTier,
377377
inspectProfileContract, normalizeProfileTier, filesForProfileTier,
378378
compareProfileTiers, updateProfileTierDeclaration,

‎scripts/lib/cli-maintenance-commands.js‎

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ function buildScopedHostParity(hostParity, globalHostComparison) {
7171
function buildCliMaintenanceCommands(ctx) {
7272
const {
7373
fs, os, path, process, console, c, SOURCES, CODEX_HOOK_COMMAND,
74-
walkDir, isSourceRepo, resolveActiveRuntimeRoot, resolveProfileDir, getLegacyCounts,
74+
walkDir, isSourceRepo, findLayoutInfo, resolveActiveRuntimeRoot, resolveProfileDir, getLegacyCounts,
7575
getCodexConfigState, inspectProfileState,
7676
detectProfileTier, inspectProfileContract, normalizeProfileTier,
7777
filesForProfileTier, readJsonSafe, safeFirstLine, detectArch, listTopDirs,
@@ -283,6 +283,16 @@ function buildCliMaintenanceCommands(ctx) {
283283
const profileState = inspectProfileState(profileDir)
284284
const legacy = getLegacyCounts(ghDir)
285285
const activeRoot = resolveActiveRuntimeRoot(cwd)
286+
const layoutInfo = typeof findLayoutInfo === 'function'
287+
? findLayoutInfo(cwd)
288+
: { enabled: false, workspaceRoot: cwd }
289+
const workspaceLayoutReady = Boolean(
290+
layoutInfo?.enabled &&
291+
layoutInfo.workspaceRoot &&
292+
fs.existsSync(path.join(layoutInfo.workspaceRoot, '.devcodex', 'layout.json')) &&
293+
fs.existsSync(path.join(layoutInfo.workspaceRoot, '.devcodex', 'workspace'))
294+
)
295+
const workspaceRuntimeReady = fs.existsSync(activeRoot) || workspaceLayoutReady
286296
const executionOptimization = inspectExecutionOptimization(cwd)
287297
const globalHostConfig = inspectGlobalHostConfig({ env: process.env, cwd })
288298
const globalHostComparison = buildGlobalHostComparison(sourceRepository, globalHostConfig)
@@ -307,6 +317,9 @@ function buildCliMaintenanceCommands(ctx) {
307317
schemaVersion: 'StatusDiagnosticV1',
308318
cwd,
309319
hostRoot,
320+
activeRoot,
321+
workspaceLayoutReady,
322+
workspaceRuntimeReady,
310323
sourceRepository,
311324
trackedEntryFiles,
312325
installSurfaces,
@@ -388,7 +401,7 @@ function buildCliMaintenanceCommands(ctx) {
388401
console.log()
389402
console.log()
390403
console.log(c.bold(' Workspace state:'))
391-
console.log(` ${c.cyan('.devcodex'.padEnd(14))} ${fs.existsSync(path.join(hostRoot, '.devcodex')) ? c.green('present') : c.dim('not initialized')}`)
404+
console.log(` ${c.cyan('.devcodex'.padEnd(14))} ${facts.workspaceRuntimeReady ? c.green('present') : c.dim('not initialized')}`)
392405
console.log(` ${c.cyan('host dirs'.padEnd(14))} ${total
393406
? c.yellow(`${total} legacy artifact(s); not required`)
394407
: c.green('none; expected')}`)
@@ -431,7 +444,7 @@ function buildCliMaintenanceCommands(ctx) {
431444

432445
console.log()
433446
if (total === 0) {
434-
if (isSrc) {
447+
if (isSrc || facts.workspaceRuntimeReady) {
435448
console.log(` ${c.dim('No workspace host artifacts.')} ${c.dim(`This is expected in ${workspaceCleanMode}.`)}`)
436449
} else {
437450
console.log(` ${c.yellow('Workspace runtime not initialized.')} Run ${c.bold('devcodex init')}; host adapters require ${c.bold('npm install -g devcodex')}.`)

‎scripts/test-cli-behavior.js‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,13 @@ function testDefaultInitBootstrapsActiveRootData() {
501501
for (const relative of ['.github', '.claude', '.codex', '.gemini', '.grok', '.agents', 'AGENTS.md', 'CLAUDE.md', 'GEMINI.md', '.mcp.json']) {
502502
assert.ok(!fs.existsSync(path.join(root, relative)), `default init must not create ${relative}`)
503503
}
504+
const statusAfterInit = runCli(['status'], root)
505+
assert.match(statusAfterInit, /\.devcodex\s+.*present/)
506+
assert.doesNotMatch(statusAfterInit, /Workspace runtime not initialized/)
507+
const statusAfterInitJson = JSON.parse(runCli(['status', '--json'], root))
508+
assert.strictEqual(statusAfterInitJson.payload.workspaceRuntimeReady, true)
509+
assert.strictEqual(statusAfterInitJson.payload.workspaceLayoutReady, true)
510+
assert.strictEqual(statusAfterInitJson.payload.activeRoot, path.join(root, '.devcodex', 'workspace'))
504511
const updated = JSON.parse(runCli(['update', '--json'], root))
505512
assert.strictEqual(updated.payload.runtimeRoot, path.join(root, '.devcodex', 'workspace'))
506513
assert.strictEqual(updated.payload.layoutCreated, false)

0 commit comments

Comments
 (0)