@walwal-harness/cli 7.1.3 → 7.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/HR-Resource/cdo/SKILL.md +2 -2
- package/HR-Resource/ceo/SKILL.md +22 -1
- package/HR-Resource/coo/SKILL.md +2 -2
- package/HR-Resource/cqo/SKILL.md +12 -7
- package/HR-Resource/cto/SKILL.md +9 -6
- package/HR-Resource/hiring/SKILL.md +11 -8
- package/HR-Resource/ops/SKILL.md +2 -2
- package/HR-Resource/resource-manager/SKILL.md +8 -5
- package/README.md +95 -343
- package/assets/templates/AGENTS.md.template +4 -0
- package/bin/init.js +170 -3
- package/package.json +1 -1
- package/scripts/harness-worker-evidence-validate.sh +22 -7
package/HR-Resource/cdo/SKILL.md
CHANGED
|
@@ -14,8 +14,8 @@ Own design strategy for the mission.
|
|
|
14
14
|
1. Read CEO and COO mission context.
|
|
15
15
|
2. Record decisions in `.harness/documents/{mission_name}/cdo.md`.
|
|
16
16
|
3. Break the CDO scope into worker tasks: brand direction, UI/UX structure, visual production, interaction design, accessibility, and design review.
|
|
17
|
-
4. Use
|
|
18
|
-
5. Use
|
|
17
|
+
4. Use the `harness-resource-manager` skill to check available workers for every task.
|
|
18
|
+
5. Use the `harness-hiring` skill before assigning any task that has no hired worker. Do not complete that task yourself.
|
|
19
19
|
6. Delegate all design deliverables and review passes to hired workers in fresh sessions.
|
|
20
20
|
7. Evaluate worker feedback for usefulness, discomfort, novelty, clarity, and differentiation.
|
|
21
21
|
8. Select the final direction and report to CEO and CTO.
|
package/HR-Resource/ceo/SKILL.md
CHANGED
|
@@ -35,13 +35,34 @@ You are the only direct conversation channel with the Owner.
|
|
|
35
35
|
- After writing `.env`, verify with `grep '^HARNESS_BASE_PORT=' .env` before routing service work.
|
|
36
36
|
- For service monitoring, collect the Owner's server mapping first: local PC, Docker, VM, AWS/cloud, host, port, health path, log path, and contact/source.
|
|
37
37
|
|
|
38
|
+
## Routing Gate — CEO Must Never Bypass CXX
|
|
39
|
+
|
|
40
|
+
CEO communicates **only** with CXX agents. CEO must **never**:
|
|
41
|
+
|
|
42
|
+
- Dispatch, hire, or brief specialist workers directly. Only CXX agents hire and manage workers.
|
|
43
|
+
- Write documents on behalf of another CXX (i.e., author `cto.md`, `cqo.md`, `coo.md`, etc.). Each CXX owns its own document.
|
|
44
|
+
- Mark a CXX step as complete without that CXX having run and produced its own document.
|
|
45
|
+
- Skip a required CXX because the scope seems small. There is no scope exemption.
|
|
46
|
+
|
|
47
|
+
**Correct routing for every implementation mission:**
|
|
48
|
+
```
|
|
49
|
+
Owner → CEO → CTO → [dev workers]
|
|
50
|
+
└─── CQO → [evaluator/tester workers]
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
If CEO needs implementation done, CEO routes to CTO. CTO then hires dev workers.
|
|
54
|
+
If CEO needs QA done, CEO routes to CQO. CQO then hires evaluator/tester workers.
|
|
55
|
+
CEO does not contact workers. CXX contact workers.
|
|
56
|
+
|
|
57
|
+
**When a CXX is unavailable or unresponsive:** escalate to the Owner. Do not act on their behalf.
|
|
58
|
+
|
|
38
59
|
## Worktree Isolation Failure — No git Repo
|
|
39
60
|
|
|
40
61
|
When an Agent spawn fails with a worktree or git error (e.g., "Cannot create agent worktree: not in a git repository"), this is an **isolation constraint**, not a hiring failure. The correct response is:
|
|
41
62
|
|
|
42
63
|
1. **Do not skip `harness-hiring`.** Run `harness-hiring` as normal to register the worker in `hr-roster.json`.
|
|
43
64
|
2. **Do not replace hired workers with inline "You are a…" prompts.** That is impersonation, not hiring.
|
|
44
|
-
3. **
|
|
65
|
+
3. **Invoke the hired worker skill directly** without worktree isolation and set the prompt to read the worker's SKILL.md from `.harness/shared/HR-Resource/{worker-name}/SKILL.md` before executing the task. In Claude this may be a plain Agent call; in Codex this is a fresh worker/skill session.
|
|
45
66
|
4. **Report the isolation constraint to the Owner** in the final summary: state that worktree isolation was unavailable and workers ran without isolation.
|
|
46
67
|
|
|
47
68
|
The worktree error only affects **isolation**. `harness-hiring`, `harness-resource-manager`, and `hr-roster.json` registration are independent of git and must always run.
|
package/HR-Resource/coo/SKILL.md
CHANGED
|
@@ -14,8 +14,8 @@ Own mission planning, research, references, hypotheses, and goal fit.
|
|
|
14
14
|
1. Read `.harness/documents/{mission_name}/ceo.md`.
|
|
15
15
|
2. Record work in `.harness/documents/{mission_name}/coo.md`.
|
|
16
16
|
3. Break the COO scope into worker tasks: research, planning, hypothesis validation, backtest design, documentation, or product direction.
|
|
17
|
-
4. Use
|
|
18
|
-
5. Use
|
|
17
|
+
4. Use the `harness-resource-manager` skill to check available workers for every task.
|
|
18
|
+
5. Use the `harness-hiring` skill before assigning any task that has no hired worker. Do not complete that task yourself.
|
|
19
19
|
6. Delegate all COO deliverables to hired workers in fresh sessions.
|
|
20
20
|
7. Review worker reports against the goal.
|
|
21
21
|
8. Reassign work or report to CEO.
|
package/HR-Resource/cqo/SKILL.md
CHANGED
|
@@ -14,20 +14,25 @@ Own quality, recurrence prevention, and archive eligibility.
|
|
|
14
14
|
1. Read CEO and CTO mission context.
|
|
15
15
|
2. Record decisions in `.harness/documents/{mission_name}/cqo.md`.
|
|
16
16
|
3. Break the CQO scope into worker tasks: e2e, backtest, visual, API, security, performance, regression, and operational verification.
|
|
17
|
-
4. Use
|
|
18
|
-
5. Use
|
|
17
|
+
4. Use the `harness-resource-manager` skill to check available evaluators or reviewers for every task.
|
|
18
|
+
5. Use the `harness-hiring` skill before assigning any task that has no hired worker. Do not complete that task yourself.
|
|
19
19
|
6. Define quality gates and delegate evidence collection to hired workers in fresh sessions.
|
|
20
20
|
7. Monitor repeated issues and promote verified lessons to `.harness/conventions`, `.harness/gotchas`, `.harness/memories`, or `.harness/shared`.
|
|
21
|
-
8. Approve or reject archive.
|
|
21
|
+
8. Approve or reject archive based solely on worker-provided evidence.
|
|
22
22
|
|
|
23
|
-
##
|
|
23
|
+
## Hard Rules
|
|
24
24
|
|
|
25
|
-
No archive without evidence.
|
|
26
25
|
CQO must not directly execute QA, visual review, security review, performance testing, or regression checks. CQO may only define gates, select evaluators, review evidence, decide archive eligibility, and document worker names and report paths.
|
|
27
26
|
|
|
28
|
-
|
|
27
|
+
**A verdict with no Worker Evidence Manifest is invalid.** CQO cannot issue ACCEPTED or REJECTED without at least one evaluator/tester worker record in `cqo.md`. Self-verification by CQO — where CQO writes a verdict based on its own inspection rather than worker-provided evidence — is a protocol violation. If no evaluator workers exist, use `harness-hiring` first.
|
|
28
|
+
|
|
29
|
+
**CQO does not communicate with dev workers.** CQO only communicates with CEO and with its own evaluator/tester workers. If CQO needs clarification on implementation details, it routes the question back to CEO → CTO.
|
|
30
|
+
|
|
31
|
+
Every evaluator/tester dispatched by CQO must write its report under `.harness/documents/{mission_name}/cqo/workers/{worker-name}.md`.
|
|
32
|
+
|
|
33
|
+
Required output sections in `cqo.md`:
|
|
29
34
|
|
|
30
35
|
1. Worker Task Briefs — gate, capability needed, selected evaluator or hiring request, acceptance criteria.
|
|
31
36
|
2. Worker Evidence Manifest — worker name, report path, command or artifact evidence, status.
|
|
32
|
-
3. CQO Verdict — PASS, FAIL, or BLOCKED based only on worker evidence.
|
|
37
|
+
3. CQO Verdict — PASS, FAIL, or BLOCKED based only on worker evidence. Must reference Worker Evidence Manifest entries.
|
|
33
38
|
4. Recurrence Notes — accepted gotchas, conventions, memories, or none.
|
package/HR-Resource/cto/SKILL.md
CHANGED
|
@@ -12,22 +12,25 @@ Own engineering execution for the mission.
|
|
|
12
12
|
## Workflow
|
|
13
13
|
|
|
14
14
|
1. Read CEO, COO, and CDO mission documents.
|
|
15
|
-
2. Record decisions in `.harness/documents/{mission_name}/cto.md`.
|
|
15
|
+
2. Record decisions in `.harness/documents/{mission_name}/cto.md`. **This file must be created before any worker is dispatched.**
|
|
16
16
|
3. Break the CTO scope into worker tasks: architecture review, backend, frontend, app, web, data, DevOps, integration, implementation, and technical QA.
|
|
17
|
-
4. Use
|
|
18
|
-
5. Use
|
|
17
|
+
4. Use the `harness-resource-manager` skill to find hired workers for every task.
|
|
18
|
+
5. Use the `harness-hiring` skill before assigning any missing specialty. Do not complete that task yourself.
|
|
19
19
|
6. Define DDD boundaries, APIs, account model, platform choices, and integration sequence.
|
|
20
20
|
7. Read `.env` `HARNESS_BASE_PORT` or `.harness/config.json runtime.ports.base` before assigning any service port.
|
|
21
21
|
8. Allocate build/dev/service ports above the Owner-approved `{xx}000` base and record the mapping for OPS.
|
|
22
22
|
9. Delegate all implementation and technical deliverables to hired workers in fresh sessions.
|
|
23
23
|
10. Collect reports, resolve blockers, and hand completed work to CQO.
|
|
24
24
|
|
|
25
|
-
##
|
|
25
|
+
## Hard Rules
|
|
26
26
|
|
|
27
|
-
Do not collapse architecture, implementation, and evaluation into one generic task.
|
|
28
27
|
CTO must not directly write code, create build scripts, choose detailed implementation content, run technical QA as the evaluator, or produce final implementation artifacts. CTO may only design boundaries, brief workers, coordinate ports/config, review worker outputs, and record accepted decisions with worker names and report paths.
|
|
29
28
|
|
|
30
|
-
|
|
29
|
+
**cto.md is a prerequisite gate.** No worker may be dispatched before `cto.md` exists. A mission where workers appear in `.harness/documents/{mission_name}/workers/` but no `cto.md` exists is a protocol violation — CEO bypassed CTO.
|
|
30
|
+
|
|
31
|
+
Every worker dispatched by CTO must be listed in the Worker Evidence Manifest section of `cto.md` with their report path and status. The report path must be `.harness/documents/{mission_name}/cto/workers/{worker-name}.md`. Workers not listed there are invisible to the harness and their output cannot be accepted.
|
|
32
|
+
|
|
33
|
+
Required output sections in `cto.md`:
|
|
31
34
|
|
|
32
35
|
1. Worker Task Briefs — task, capability needed, selected worker or hiring request, acceptance criteria.
|
|
33
36
|
2. Port And Runtime Contract — `.env` and `.harness/config.json` values that workers must update or use.
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: harness-hiring
|
|
3
|
-
description: "HR hiring. Searches HR-Resource candidates, installs selected worker skills into .claude and .codex, and records roster wiring."
|
|
3
|
+
description: "HR hiring. Searches .harness/shared/HR-Resource candidates, installs selected worker skills into .claude and .codex, and records roster wiring."
|
|
4
4
|
model: sonnet
|
|
5
5
|
disable-model-invocation: false
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Hiring
|
|
9
9
|
|
|
10
|
-
Hire workers from
|
|
10
|
+
Hire workers from `.harness/shared/HR-Resource/`.
|
|
11
11
|
|
|
12
12
|
## Required Inputs
|
|
13
13
|
|
|
@@ -15,14 +15,17 @@ Hire workers from `HR-Resource/`.
|
|
|
15
15
|
- needed capability
|
|
16
16
|
- mission name
|
|
17
17
|
- blocking status
|
|
18
|
+
- owning CXX (`cto`, `cqo`, `coo`, `cdo`, or `ops`)
|
|
18
19
|
|
|
19
20
|
## Workflow
|
|
20
21
|
|
|
21
|
-
1.
|
|
22
|
-
2.
|
|
23
|
-
3.
|
|
24
|
-
4.
|
|
25
|
-
5.
|
|
26
|
-
6.
|
|
22
|
+
1. Reject any request from CEO to hire or brief a specialist worker directly. Tell CEO to route through the owning CXX.
|
|
23
|
+
2. Search `.harness/shared/HR-Resource/*/SKILL.md`.
|
|
24
|
+
3. Select the smallest fitting worker.
|
|
25
|
+
4. Install it to `.claude/skills/{owning-cxx}/{name}/SKILL.md` and `.codex/skills/{owning-cxx}/{name}/SKILL.md`.
|
|
26
|
+
5. Update `.harness/shared/hr-roster.json` without deleting existing hired entries. Record `owner` as the owning CXX, `skillPath` as `.harness/shared/HR-Resource/{name}/SKILL.md`, and `skillPaths.claude` / `skillPaths.codex` as tool-specific hierarchical installed paths.
|
|
27
|
+
6. The owning CXX must write worker reports under `.harness/documents/{mission}/{owning-cxx}/workers/{name}.md`. Do not write flat `.harness/documents/{mission}/workers/{name}.md` except when migrating legacy missions.
|
|
28
|
+
7. Ask the `harness-resource-manager` skill to update trigger wording.
|
|
29
|
+
8. Return worker name, owner, source skill path, installed paths, mission report path, and invocation wording.
|
|
27
30
|
|
|
28
31
|
Never mark a missing worker as available.
|
package/HR-Resource/ops/SKILL.md
CHANGED
|
@@ -28,8 +28,8 @@ OPS must not directly perform DevOps implementation, service fixes, config rewri
|
|
|
28
28
|
## Workflow
|
|
29
29
|
|
|
30
30
|
1. Read `.env` and `.harness/config.json runtime.ports`, `runtime.build`, and `runtime.production`.
|
|
31
|
-
2. Use
|
|
32
|
-
3. Use
|
|
31
|
+
2. Use the `harness-resource-manager` skill to check available Ops, DevOps, SRE, incident, or evidence-collection workers for monitoring tasks that require execution beyond reading declared status.
|
|
32
|
+
3. Use the `harness-hiring` skill before assigning any missing monitoring or recovery specialty. Do not complete that task yourself.
|
|
33
33
|
4. Monitor build environments declared in `runtime.build.commands[]`: command, cwd, expected port, log path, and owner.
|
|
34
34
|
5. Monitor service environments declared in `runtime.production.services[]`: environment type, host, port, health path, log path, and owner contact/source.
|
|
35
35
|
6. Write daily logs under `.harness/logs/YYYY-MM-DD/` and mission decisions in `.harness/documents/{mission_name}/ops.md`.
|
|
@@ -13,11 +13,14 @@ Manage worker availability and invocation wording.
|
|
|
13
13
|
|
|
14
14
|
- Hired roster: `.harness/shared/hr-roster.json`
|
|
15
15
|
- Keyword index: `.harness/shared/resource-index.json`
|
|
16
|
-
- Candidate pool:
|
|
16
|
+
- Candidate pool: `.harness/shared/HR-Resource/*/SKILL.md`
|
|
17
|
+
- Installed hired workers: `.claude/skills/{owning-cxx}/{worker}/SKILL.md` and `.codex/skills/{owning-cxx}/{worker}/SKILL.md`
|
|
18
|
+
- Mission worker reports: `.harness/documents/{mission}/{owning-cxx}/workers/{worker}.md`
|
|
17
19
|
|
|
18
20
|
## Workflow
|
|
19
21
|
|
|
20
|
-
1. Check whether a
|
|
21
|
-
2.
|
|
22
|
-
3. If
|
|
23
|
-
4.
|
|
22
|
+
1. Check whether the requester is a CXX. CEO cannot request specialist worker assignment directly.
|
|
23
|
+
2. Check whether a suitable worker is already hired for that owning CXX.
|
|
24
|
+
3. If hired, return the exact skill name, owning CXX, hierarchical installed paths, and mission report path.
|
|
25
|
+
4. If not hired, suggest `.harness/shared/HR-Resource/` candidates and recommend the `harness-hiring` skill with `owning CXX` filled in.
|
|
26
|
+
5. Keep aliases narrow enough to avoid accidental generic invocation.
|
package/README.md
CHANGED
|
@@ -1,407 +1,159 @@
|
|
|
1
1
|
# @walwal-harness/cli
|
|
2
2
|
|
|
3
|
-
AI
|
|
3
|
+
**v7.1** — Company-mode AI agent harness for Claude Code and Codex.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
핵심 개념은 "하나의 프로젝트 = 하나의 회사" 입니다.
|
|
5
|
+
One project = one company. The Owner speaks only to the CEO. The CEO speaks only to CXX agents. CXX agents hire specialist workers. No one skips a level.
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
- Dispatcher: CEO, 유일한 대화 창구
|
|
10
|
-
- Planner: COO, 기획·가설·HR
|
|
11
|
-
- CTO: 구현 총괄
|
|
12
|
-
- CQO: 품질 총괄
|
|
13
|
-
- Service-Ops: 운영·모니터링·회고
|
|
14
|
-
- Conductor: 자율 라우터
|
|
15
|
-
- Meeting-Manager: 회의 소집기
|
|
7
|
+
---
|
|
16
8
|
|
|
17
|
-
|
|
9
|
+
## Company Structure
|
|
18
10
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
- 에이전트는 대화 기억보다 문서 팩트를 우선합니다.
|
|
22
|
-
- 작업 전환은 항상 `progress.json`, `handoff.json`, `task session` 을 기준으로 이뤄집니다.
|
|
23
|
-
- 회의는 동기화와 의사결정에 쓰고, 단순 런타임 복구는 값싼 상태 기반 로직으로 처리합니다.
|
|
24
|
-
- TokenLimit, retry, drift, handoff 같은 운영 문제를 코드가 아니라 하네스 레벨에서 다룹니다.
|
|
25
|
-
|
|
26
|
-
## 회사 구조
|
|
27
|
-
|
|
28
|
-
```text
|
|
11
|
+
```
|
|
29
12
|
Owner
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
│ ├─ coo-developer
|
|
38
|
-
│ └─ documentationer
|
|
39
|
-
├─ CTO
|
|
40
|
-
│ ├─ generator-backend
|
|
41
|
-
│ ├─ generator-frontend
|
|
42
|
-
│ ├─ generator-designer
|
|
43
|
-
│ └─ generator-devops
|
|
44
|
-
├─ CQO
|
|
45
|
-
│ ├─ evaluator-code-quality
|
|
46
|
-
│ ├─ evaluator-functional
|
|
47
|
-
│ ├─ evaluator-visual
|
|
48
|
-
│ ├─ evaluator-architecture
|
|
49
|
-
│ └─ evaluator-security
|
|
50
|
-
└─ Service-Ops
|
|
13
|
+
└─ /goal · /hot-fix
|
|
14
|
+
└─ harness-ceo orchestrator — Owner's only contact
|
|
15
|
+
├─ harness-coo research, hypothesis, service direction
|
|
16
|
+
├─ harness-cdo branding, UI/UX, design review
|
|
17
|
+
├─ harness-cto architecture, API, platform, implementation
|
|
18
|
+
├─ harness-cqo quality gates, regression, archive, gotcha/convention
|
|
19
|
+
└─ harness-ops build monitoring, log analysis, service events
|
|
51
20
|
```
|
|
52
21
|
|
|
53
|
-
###
|
|
22
|
+
### Hierarchy Rules (non-negotiable)
|
|
54
23
|
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
- `CQO`: 적대적 평가와 회귀 차단
|
|
61
|
-
- `Service-Ops`: cadence, 운영 drift, auto-retro
|
|
62
|
-
- `coo-developer`: 빠른 spike, backdata 검증
|
|
63
|
-
- `documentationer`: 웹 리서치, 실험 보고서, 가설 유효/무효 판정
|
|
24
|
+
- **CEO → CXX only.** CEO never dispatches or hires workers directly. All worker contact goes through the responsible CXX.
|
|
25
|
+
- **CTO → dev workers.** CTO hires and briefs implementation workers. `cto.md` must exist before any worker is dispatched.
|
|
26
|
+
- **CQO → evaluator/tester workers.** CQO hires evaluation workers and bases its verdict entirely on their evidence. Self-inspection by CQO is not valid evidence.
|
|
27
|
+
- **No CXX self-execution.** CXX agents coordinate and manage only. A CXX that produces specialist deliverables without matching worker records has violated its scope.
|
|
28
|
+
- **No verdict without worker evidence.** CQO cannot issue ACCEPTED/REJECTED without a Worker Evidence Manifest referencing at least one evaluator worker.
|
|
64
29
|
|
|
65
|
-
|
|
30
|
+
---
|
|
66
31
|
|
|
67
|
-
|
|
32
|
+
## Install
|
|
68
33
|
|
|
69
34
|
```bash
|
|
70
35
|
npm i @walwal-harness/cli
|
|
71
36
|
```
|
|
72
37
|
|
|
73
|
-
|
|
38
|
+
Restart Claude Code after install.
|
|
74
39
|
|
|
75
|
-
|
|
40
|
+
To initialize a project:
|
|
76
41
|
|
|
77
42
|
```bash
|
|
78
|
-
npx walwal-harness
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
기존 설치를 현재 패키지 버전에 맞게 다시 정리하려면:
|
|
82
|
-
|
|
83
|
-
```bash
|
|
84
|
-
npx walwal-harness --force
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
## 시작 방법
|
|
88
|
-
|
|
89
|
-
새 Claude Code 세션의 첫 메시지:
|
|
90
|
-
|
|
91
|
-
```text
|
|
92
|
-
하네스 엔지니어링 시작
|
|
43
|
+
npx walwal-harness init
|
|
93
44
|
```
|
|
94
45
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
1. `dispatcher` 가 요청을 분류하고 pipeline/runbook 을 정합니다.
|
|
98
|
-
2. 필요하면 `meeting-manager` 가 CEO intake 회의를 엽니다.
|
|
99
|
-
3. `planner` 가 `plan.md`, `feature-list.json`, `api-contract.json` 을 만듭니다.
|
|
100
|
-
4. `conductor` 가 회사 루프에 따라 CTO/CQO/Service-Ops/Meeting 으로 라우팅합니다.
|
|
101
|
-
5. generator / evaluator / cqo / ops 가 문서 기반으로 이어집니다.
|
|
102
|
-
|
|
103
|
-
## 상태 파일
|
|
46
|
+
What `init` installs:
|
|
104
47
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
| 파일 | 역할 |
|
|
48
|
+
| Path | Contents |
|
|
108
49
|
|---|---|
|
|
109
|
-
| `.
|
|
110
|
-
| `.
|
|
111
|
-
| `.harness
|
|
112
|
-
| `.harness/
|
|
113
|
-
|
|
|
114
|
-
|
|
115
|
-
### 중요한 progress 필드
|
|
116
|
-
|
|
117
|
-
- `current_agent`, `agent_status`, `next_agent`
|
|
118
|
-
- `workflow.stage`
|
|
119
|
-
- `meetings.*`
|
|
120
|
-
- `task_sessions.current`
|
|
121
|
-
- `task_stop.*`
|
|
122
|
-
- `goals.*`
|
|
123
|
-
- `conductor.*`, `planner.*`, `cto.*`, `cqo.*`, `service_ops.*`
|
|
124
|
-
|
|
125
|
-
## Task Session
|
|
126
|
-
|
|
127
|
-
각 agent 전환 시 `.harness/actions/task-sessions/<agent>/...md` 가 생성됩니다.
|
|
128
|
-
|
|
129
|
-
목적:
|
|
130
|
-
|
|
131
|
-
- 이전 채팅 문맥을 들고 가지 않기
|
|
132
|
-
- 자기편향적 사고를 줄이기
|
|
133
|
-
- 사실과 추론을 분리하기
|
|
134
|
-
- 재개 시에도 문서 기준으로만 이어가기
|
|
135
|
-
|
|
136
|
-
에이전트는 task session, handoff, progress 를 단일 사실원으로 사용해야 합니다.
|
|
50
|
+
| `.claude/commands/goal.md` | `/goal` Owner command |
|
|
51
|
+
| `.claude/commands/hot-fix.md` | `/hot-fix` Owner command |
|
|
52
|
+
| `.claude/skills/harness-{ceo,coo,cdo,cto,cqo,ops}/` | CXX agent skills |
|
|
53
|
+
| `.harness/shared/HR-Resource/` | Hireable worker skill pool |
|
|
54
|
+
| `AGENTS.md` ← `CLAUDE.md` symlink | Project harness config |
|
|
137
55
|
|
|
138
|
-
|
|
56
|
+
---
|
|
139
57
|
|
|
140
|
-
|
|
58
|
+
## Mission Flow
|
|
141
59
|
|
|
142
|
-
|
|
60
|
+
### Goal
|
|
143
61
|
|
|
144
|
-
- `Standup`
|
|
145
|
-
- `Sprint Review`
|
|
146
|
-
- `Spec Review`
|
|
147
|
-
- `Incident War Room`
|
|
148
|
-
- `All-Hands`
|
|
149
|
-
|
|
150
|
-
역할:
|
|
151
|
-
|
|
152
|
-
- 회의: owner 결정, drift 분류, evidence 집계, action item 생성
|
|
153
|
-
- Conductor: 회의 결과를 읽고 next agent 갱신
|
|
154
|
-
- Service-Ops: cadence 계산
|
|
155
|
-
|
|
156
|
-
기본 cadence:
|
|
157
|
-
|
|
158
|
-
- `light`: 30m
|
|
159
|
-
- `normal`: 1h
|
|
160
|
-
- `heavy`: 4h
|
|
161
|
-
|
|
162
|
-
## TokenLimit Hold / Resume
|
|
163
|
-
|
|
164
|
-
`TokenLimit` 은 회의가 아니라 런타임 중단 복구 문제로 취급합니다.
|
|
165
|
-
|
|
166
|
-
즉:
|
|
167
|
-
|
|
168
|
-
- 회의 시스템은 그대로 유지
|
|
169
|
-
- TokenLimit 은 별도 저비용 복구 레이어로 처리
|
|
170
|
-
|
|
171
|
-
### 동작 방식
|
|
172
|
-
|
|
173
|
-
토큰 한도로 작업이 중단되면:
|
|
174
|
-
|
|
175
|
-
```bash
|
|
176
|
-
bash scripts/harness-token-limit.sh . mark
|
|
177
62
|
```
|
|
178
|
-
|
|
179
|
-
기본 정책:
|
|
180
|
-
|
|
181
|
-
- `TaskStopReason = TokenLimit`
|
|
182
|
-
- 현재 작업은 `paused`
|
|
183
|
-
- `progress.json.task_stop` 에 아래가 기록됨
|
|
184
|
-
- `wake_target`
|
|
185
|
-
- `resume_after`
|
|
186
|
-
- `stopped_agent`
|
|
187
|
-
- `stopped_next_agent`
|
|
188
|
-
- `task_session_path`
|
|
189
|
-
|
|
190
|
-
그 다음:
|
|
191
|
-
|
|
192
|
-
- `SessionStart` 는 별도 모델 probe 없이 시간만 확인
|
|
193
|
-
- 아직 hold 중이면 `retry_after` 와 `wake target` 만 출력
|
|
194
|
-
- 시간이 지나면 `# Harness resume ready` 를 출력하고 원래 CXX/agent 로 복귀
|
|
195
|
-
|
|
196
|
-
테스트용:
|
|
197
|
-
|
|
198
|
-
```bash
|
|
199
|
-
bash scripts/harness-token-limit.sh . mark 300
|
|
63
|
+
Owner /goal → CEO → [COO] → [CDO] → CTO → [dev workers] → CQO → [evaluator workers]
|
|
200
64
|
```
|
|
201
65
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
- TokenLimit checker 는 회의를 대체하지 않습니다.
|
|
206
|
-
- 에이전트는 복귀 시 이전 대화가 아니라 `task_session_path` 와 문서를 보고 이어갑니다.
|
|
207
|
-
|
|
208
|
-
## COO Hypothesis Cell
|
|
209
|
-
|
|
210
|
-
정규 CTO/CQO 라인에 넣기 전, COO 직속으로 빠른 가설 검증 셀을 돌릴 수 있습니다.
|
|
66
|
+
1. CEO reads Owner request, writes `ceo.md`, routes to relevant CXX.
|
|
67
|
+
2. Each CXX writes its own `{cxx}.md`, hires workers, collects evidence.
|
|
68
|
+
3. CEO aggregates CXX outputs and reports to Owner.
|
|
211
69
|
|
|
212
|
-
|
|
70
|
+
### Hot Fix
|
|
213
71
|
|
|
214
|
-
- `coo-developer`
|
|
215
|
-
- `documentationer`
|
|
216
|
-
|
|
217
|
-
흐름:
|
|
218
|
-
|
|
219
|
-
1. `planner.requested_mode = "hypothesis"`
|
|
220
|
-
2. `documentationer` 가 리서치/질문 정리
|
|
221
|
-
3. `coo-developer` 가 spike / backdata 실험
|
|
222
|
-
4. `documentationer` 가 보고서와 verdict 작성
|
|
223
|
-
5. `planner` 가 결과를 정규 sprint artifact 로 승격하거나 폐기
|
|
224
|
-
|
|
225
|
-
핵심은 운영 품질이 아니라 빠른 사실 확인입니다.
|
|
226
|
-
|
|
227
|
-
## 런타임 (회사모드 always-on)
|
|
228
|
-
|
|
229
|
-
회사모드는 유일한 런타임이며 항상 켜져 있습니다. `progress.mode == "company"` 가 항상 참이고, 별도 모드 전환 명령은 없습니다.
|
|
230
|
-
|
|
231
|
-
자율 진행은 두 메커니즘으로 유지됩니다:
|
|
232
|
-
|
|
233
|
-
- **Stop 훅** — Claude 가 한 turn 을 끝내려는 시점에 발화. `conductor.state == "running"` 이고 다음 부서가 있으면 자동으로 turn 을 한 번 더 굴려 끊김 없이 연쇄.
|
|
234
|
-
- **launchd hourly wake (선택)** — 1시간마다 macOS 가 `scripts/harness-wake.sh` 를 호출. idle ≥ 55분이고 `paused/completed/escalated` 가 아닌 프로젝트만 깨움.
|
|
235
|
-
|
|
236
|
-
```bash
|
|
237
|
-
# 1시간 안전망 wake 등록
|
|
238
|
-
bash scripts/harness-wake-install.sh install .
|
|
239
|
-
|
|
240
|
-
# 상태 확인
|
|
241
|
-
bash scripts/harness-wake-install.sh status
|
|
242
|
-
|
|
243
|
-
# 즉시 한 번 발화 (테스트)
|
|
244
|
-
bash scripts/harness-wake-install.sh run-now
|
|
245
72
|
```
|
|
246
|
-
|
|
247
|
-
회의 결정의 `tracks[]` 는 진행 흐름의 fork-join 단위이며 런타임 모드와는 별개입니다 (`tracks.length ≥ 2` 일 때 parallel).
|
|
248
|
-
- Archive prompt
|
|
249
|
-
|
|
250
|
-
Queue 관련 유용한 명령:
|
|
251
|
-
|
|
252
|
-
```bash
|
|
253
|
-
bash scripts/harness-queue-manager.sh status .
|
|
254
|
-
bash scripts/harness-queue-manager.sh auto-dispatch .
|
|
255
|
-
bash scripts/harness-queue-manager.sh idle-slots .
|
|
73
|
+
Owner /hot-fix → CEO → CTO → [dev workers] → CQO → [evaluator workers]
|
|
256
74
|
```
|
|
257
75
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
일반적인 흐름:
|
|
76
|
+
1. CEO summons CTO and CQO immediately.
|
|
77
|
+
2. CTO designs minimum patch, hires implementation workers, writes `cto.md`.
|
|
78
|
+
3. CQO runs regression gate with evaluator workers, registers gotcha/convention, writes `cqo.md`.
|
|
263
79
|
|
|
264
|
-
|
|
265
|
-
2. `generator-frontend`
|
|
266
|
-
3. `evaluator-code-quality`
|
|
267
|
-
4. `evaluator-functional`
|
|
268
|
-
5. `evaluator-visual`
|
|
269
|
-
6. `cqo`
|
|
270
|
-
7. `service-ops`
|
|
80
|
+
**Complete when:** `cto.md` + `cqo.md` + at least one `.harness/gotchas/` or `.harness/conventions/` entry exist.
|
|
271
81
|
|
|
272
|
-
|
|
82
|
+
---
|
|
273
83
|
|
|
274
|
-
|
|
275
|
-
- Evidence 없는 점수는 0
|
|
276
|
-
- regression 1건 이상이면 전체 FAIL
|
|
277
|
-
- evaluator 는 읽기 전용
|
|
84
|
+
## Hard Rules
|
|
278
85
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
하네스는 피드백을 세 저장소로 나눠 누적합니다.
|
|
282
|
-
|
|
283
|
-
| 종류 | 용도 |
|
|
86
|
+
| # | Rule |
|
|
284
87
|
|---|---|
|
|
285
|
-
|
|
|
286
|
-
|
|
|
287
|
-
|
|
|
288
|
-
|
|
289
|
-
|
|
88
|
+
| 1 | No source edit without `{mission}/cto.md` — CTO scope sign-off required |
|
|
89
|
+
| 2 | No CXX impersonation — use installed harness skills in fresh sessions |
|
|
90
|
+
| 3 | No unnamed workers — all work routes through `harness-hiring` → `harness-resource-manager` |
|
|
91
|
+
| 4 | No archive without CQO verdict — `{mission}/cqo.md` with explicit PASS must exist |
|
|
92
|
+
| 5 | No gotcha skip — every hot-fix produces at least one gotcha or convention entry |
|
|
93
|
+
| 6 | CEO routes only to CXX — never directly to workers |
|
|
94
|
+
| 7 | No CXX self-execution — deliverables without matching worker records are rejected |
|
|
95
|
+
| 8 | No verdict without worker evidence — CQO self-inspection is not valid |
|
|
290
96
|
|
|
291
|
-
|
|
292
|
-
2. `.harness/conventions/shared.md`
|
|
293
|
-
3. `.harness/conventions/<self>.md`
|
|
294
|
-
4. `.harness/gotchas/<self>.md`
|
|
295
|
-
5. `.harness/memory.md`
|
|
97
|
+
---
|
|
296
98
|
|
|
297
|
-
##
|
|
99
|
+
## Harness Dashboard
|
|
298
100
|
|
|
299
|
-
|
|
300
|
-
|---|---|
|
|
301
|
-
| `scripts/conductor-tick.sh` | 회사 루프 라우터 — 다음 부서 결정 |
|
|
302
|
-
| `scripts/harness-next.sh` | turn 종료 후 handoff 생성 + gotcha/convention 자동 등록 + audit gate |
|
|
303
|
-
| `scripts/harness-progress-set.sh` | progress.json partial update 헬퍼 |
|
|
304
|
-
| `scripts/harness-session-start.sh` | SessionStart 훅 (+ future-dated 라인 자동 격리) |
|
|
305
|
-
| `scripts/harness-user-prompt-submit.sh` | UserPromptSubmit 훅 |
|
|
306
|
-
| `scripts/harness-stop.sh` | Stop 훅 — turn 종료 시 자동 연쇄 |
|
|
307
|
-
| `scripts/harness-wake.sh` | 1시간 안전망 wake (launchd 가 호출) |
|
|
308
|
-
| `scripts/harness-wake-install.sh` | launchd 등록/관리 CLI |
|
|
309
|
-
| `scripts/harness-statusline.sh` | 1줄 statusLine 렌더 |
|
|
310
|
-
| `scripts/harness-queue-manager.sh` | feature queue 관리 |
|
|
311
|
-
| `scripts/harness-meeting-doc.sh` | 회의 문서 skeleton / decision 처리 |
|
|
312
|
-
| `scripts/harness-task-session.sh` | agent 별 task session (TokenLimit) |
|
|
313
|
-
| `scripts/harness-token-limit.sh` | TokenLimit hold/resume 마킹 |
|
|
314
|
-
| `scripts/harness-archive.sh` | sprint 종료 archive |
|
|
315
|
-
| `scripts/harness-gotcha-register.sh` | evaluator output 의 gotcha_candidates 자동 등록 |
|
|
316
|
-
| `scripts/harness-dashboard-up.sh` | Brick Office (브라우저 3D 대시보드) 기동 |
|
|
317
|
-
|
|
318
|
-
## 디렉토리 구조
|
|
319
|
-
|
|
320
|
-
```text
|
|
321
|
-
.harness/
|
|
322
|
-
├── actions/
|
|
323
|
-
│ ├── plan.md
|
|
324
|
-
│ ├── feature-list.json
|
|
325
|
-
│ ├── api-contract.json
|
|
326
|
-
│ ├── sprint-contract.md
|
|
327
|
-
│ ├── meetings/
|
|
328
|
-
│ ├── incidents/
|
|
329
|
-
│ └── task-sessions/
|
|
330
|
-
├── archive/
|
|
331
|
-
├── progress.json
|
|
332
|
-
├── handoff.json
|
|
333
|
-
├── progress.log
|
|
334
|
-
├── config.json
|
|
335
|
-
└── doctrine/
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
상세 조직 규칙은 다음 문서를 봅니다.
|
|
339
|
-
|
|
340
|
-
- `AGENTS.md`
|
|
341
|
-
- `.harness/doctrine/nexus.md`
|
|
342
|
-
- `.harness/agency-mapping.md`
|
|
343
|
-
- `.harness/HARNESS.md`
|
|
344
|
-
|
|
345
|
-
## Troubleshooting
|
|
346
|
-
|
|
347
|
-
### 다음 agent 가 안 뜸
|
|
101
|
+
The harness ships with a real-time dashboard that reads `.harness/documents/` directly.
|
|
348
102
|
|
|
349
103
|
```bash
|
|
350
|
-
|
|
104
|
+
bash scripts/harness-dashboard-up.sh
|
|
351
105
|
```
|
|
352
106
|
|
|
353
|
-
|
|
107
|
+
Features:
|
|
354
108
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
109
|
+
- **Org Tree** — live status of Owner → CEO → CXX → Workers hierarchy
|
|
110
|
+
- **Mission Timeline** — clickable history of goal/hot-fix missions showing the full dispatch chain
|
|
111
|
+
- **Mission Flow tab** — per-mission flow: Owner prompt → CEO routing → CXX → worker files changed → CQO verdict
|
|
112
|
+
- **History tab** — mission-specific Owner request (from CEO summary + closest progress.log match)
|
|
113
|
+
- **Gotchas tab** — searchable `.harness/gotchas/*.md` knowledge base, click to read full markdown
|
|
114
|
+
- **Document tab** — per-CXX markdown doc viewer
|
|
358
115
|
|
|
359
|
-
|
|
116
|
+
---
|
|
360
117
|
|
|
361
|
-
|
|
362
|
-
bash scripts/harness-session-start.sh
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
### TokenLimit hold 상태 확인
|
|
118
|
+
## Harness Runtime Paths
|
|
366
119
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
120
|
+
| Path | Role |
|
|
121
|
+
|---|---|
|
|
122
|
+
| `.harness/documents/{mission}/` | CXX decisions and worker reports per mission |
|
|
123
|
+
| `.harness/documents/{mission}/{cxx}/workers/` | Worker reports owned by that CXX |
|
|
124
|
+
| `.harness/conventions/` | Durable rules (CQO writes, survives missions) |
|
|
125
|
+
| `.harness/gotchas/` | Recurrence-prevention records (CQO registers per hot-fix) |
|
|
126
|
+
| `.harness/shared/HR-Resource/` | Hireable worker skill pool |
|
|
127
|
+
| `.harness/archive/` | CQO-approved completed missions (immutable) |
|
|
128
|
+
| `.harness/logs/YYYY-MM-DD/` | OPS exception logs |
|
|
370
129
|
|
|
371
|
-
|
|
130
|
+
---
|
|
372
131
|
|
|
373
|
-
|
|
374
|
-
bash scripts/harness-queue-manager.sh status .
|
|
375
|
-
```
|
|
132
|
+
## Hiring
|
|
376
133
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
```bash
|
|
380
|
-
# config 확인 — auto_chain_on_stop 이 true 여야 함
|
|
381
|
-
jq '.behavior.auto_chain_on_stop // true' .harness/config.json
|
|
134
|
+
Any CXX uses `harness-hiring` before assigning work to a specialist not yet on roster.
|
|
382
135
|
|
|
383
|
-
# stop_chain_count 와 sprint 상한 확인
|
|
384
|
-
jq '{count: .conductor.stop_chain_count, max: 200}' .harness/progress.json
|
|
385
136
|
```
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
```bash
|
|
390
|
-
bash scripts/harness-wake-install.sh status
|
|
391
|
-
tail -30 ~/.walwal-harness/logs/wake.log
|
|
137
|
+
harness-resource-manager → find available worker
|
|
138
|
+
harness-hiring → register and onboard worker
|
|
139
|
+
{cxx} → hired worker → deliverable → {cxx} evidence manifest
|
|
392
140
|
```
|
|
393
141
|
|
|
394
|
-
|
|
142
|
+
---
|
|
395
143
|
|
|
396
|
-
|
|
144
|
+
## Version History
|
|
397
145
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
-
|
|
404
|
-
|
|
146
|
+
| Version | Summary |
|
|
147
|
+
|---|---|
|
|
148
|
+
| 7.1.6 | CXX hierarchy enforcement: CEO→CXX-only gate, CTO prerequisite gate, CQO worker-evidence mandate; dashboard gotchas tab, mission-specific history tab, worker file list in flow |
|
|
149
|
+
| 7.1.5 | Dashboard: mission flow timeline, markdown viewer, 50vw drawer |
|
|
150
|
+
| 7.1.4 | Dashboard: org-tree redesign with real `.harness/documents/` data |
|
|
151
|
+
| 7.1.3 | Karpathy-style AGENTS.md rewrite, ko templates, hot-fix harness gate rules |
|
|
152
|
+
| 7.1.2 | v7 CEO routing migration, legacy command removal |
|
|
153
|
+
| 7.1.1 | CEO no-git hiring fix, gotcha/convention migration |
|
|
154
|
+
| 7.1.0 | v7.1 merge: OPS monitoring, CXX hiring enforcement |
|
|
155
|
+
|
|
156
|
+
---
|
|
405
157
|
|
|
406
158
|
## License
|
|
407
159
|
|
|
@@ -104,6 +104,10 @@ Note: A docmeta skip decision on harness documents (ceo.md, cto.md, cqo.md, work
|
|
|
104
104
|
4. **No archive without CQO verdict** — `{mission}/cqo.md` with explicit PASS must exist.
|
|
105
105
|
5. **No gotcha skip** — Every hot-fix produces at least one `.harness/gotchas/` or `.harness/conventions/` entry.
|
|
106
106
|
6. **This file is read-only during missions** — Raise a separate `/goal` to update AGENTS.md.
|
|
107
|
+
7. **CEO routes only to CXX — never to workers** — CEO must not dispatch, hire, or brief specialist workers directly. Implementation workers are hired by CTO. Evaluator/tester workers are hired by CQO.
|
|
108
|
+
8. **No CXX self-execution** — CXX agents coordinate and manage only. A CXX that produces deliverables without matching worker records has violated its scope. CEO must reject such reports.
|
|
109
|
+
9. **No verdict without worker evidence** — CQO cannot issue ACCEPTED/REJECTED without a Worker Evidence Manifest referencing at least one evaluator worker. Self-inspection by CQO is not valid evidence.
|
|
110
|
+
10. **Hierarchical worker ownership** — Hired workers are installed under `.claude/skills/{owning-cxx}/{worker}/` and `.codex/skills/{owning-cxx}/{worker}/`; mission worker reports live under `.harness/documents/{mission}/{owning-cxx}/workers/`. Flat `{mission}/workers/` reports are legacy and signal an ownership violation unless explicitly migrated.
|
|
107
111
|
|
|
108
112
|
---
|
|
109
113
|
|
package/bin/init.js
CHANGED
|
@@ -21,6 +21,17 @@ const isAuto = args.includes('--auto');
|
|
|
21
21
|
const isForce = args.includes('--force');
|
|
22
22
|
const isHelp = args.includes('--help') || args.includes('-h');
|
|
23
23
|
|
|
24
|
+
function getOptionValue(name) {
|
|
25
|
+
const eqPrefix = `${name}=`;
|
|
26
|
+
const eqArg = args.find((a) => a.startsWith(eqPrefix));
|
|
27
|
+
if (eqArg) return eqArg.slice(eqPrefix.length);
|
|
28
|
+
const idx = args.indexOf(name);
|
|
29
|
+
if (idx !== -1 && args[idx + 1] && !args[idx + 1].startsWith('-')) {
|
|
30
|
+
return args[idx + 1];
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
24
35
|
// ─────────────────────────────────────────
|
|
25
36
|
// Resolve project root
|
|
26
37
|
// ─────────────────────────────────────────
|
|
@@ -28,6 +39,9 @@ const isHelp = args.includes('--help') || args.includes('-h');
|
|
|
28
39
|
// inside node_modules, NOT the consumer project root.
|
|
29
40
|
// We detect this and walk up to find the actual project root.
|
|
30
41
|
function resolveProjectRoot() {
|
|
42
|
+
const explicitRoot = getOptionValue('--project-root');
|
|
43
|
+
if (explicitRoot) return path.resolve(explicitRoot);
|
|
44
|
+
|
|
31
45
|
let cwd = process.cwd();
|
|
32
46
|
|
|
33
47
|
// If we're running inside node_modules, walk up to the project root
|
|
@@ -430,12 +444,12 @@ function scaffoldHarness() {
|
|
|
430
444
|
}
|
|
431
445
|
|
|
432
446
|
const rosterPath = path.join(HARNESS_DIR, 'shared', 'hr-roster.json');
|
|
433
|
-
if (!fileExists(rosterPath)
|
|
447
|
+
if (!fileExists(rosterPath)) {
|
|
434
448
|
fs.writeFileSync(rosterPath, JSON.stringify({ hired: [] }, null, 2) + '\n');
|
|
435
449
|
}
|
|
436
450
|
|
|
437
451
|
const resourceIndexPath = path.join(HARNESS_DIR, 'shared', 'resource-index.json');
|
|
438
|
-
if (!fileExists(resourceIndexPath)
|
|
452
|
+
if (!fileExists(resourceIndexPath)) {
|
|
439
453
|
fs.writeFileSync(resourceIndexPath, JSON.stringify({ aliases: {}, keywords: {} }, null, 2) + '\n');
|
|
440
454
|
}
|
|
441
455
|
|
|
@@ -1183,17 +1197,40 @@ function detectMigrationNeeded() {
|
|
|
1183
1197
|
const configPath = path.join(HARNESS_DIR, 'config.json');
|
|
1184
1198
|
const memoryPath = path.join(HARNESS_DIR, 'memory.md');
|
|
1185
1199
|
const memoryTplPath = path.join(PKG_ROOT, 'assets', 'templates', 'memory.md');
|
|
1200
|
+
const rosterPath = path.join(HARNESS_DIR, 'shared', 'hr-roster.json');
|
|
1201
|
+
const resourceIndexPath = path.join(HARNESS_DIR, 'shared', 'resource-index.json');
|
|
1186
1202
|
const flags = {
|
|
1187
1203
|
progressV3toV4: false,
|
|
1188
1204
|
progressLegacyRouting: false,
|
|
1189
1205
|
configMissingCompanyMode: false,
|
|
1190
1206
|
configLegacyRouting: false,
|
|
1207
|
+
coreSkillsStale: false,
|
|
1208
|
+
hrResourcePoolStale: false,
|
|
1209
|
+
rosterCodexPathsMissing: false,
|
|
1210
|
+
resourceIndexCodexWordingMissing: false,
|
|
1191
1211
|
memoryMissingSystemEntries: [],
|
|
1192
1212
|
gotchaMissingEntries: {}, // { "<filename>": [G-IDs...] }
|
|
1193
1213
|
conventionMissingEntries: {}, // { "<filename>": [C-IDs...] }
|
|
1194
1214
|
bundleVersionStale: null, // { current, installed }
|
|
1195
1215
|
};
|
|
1196
1216
|
|
|
1217
|
+
const coreSkills = ['ceo', 'coo', 'cdo', 'cto', 'cqo', 'ops', 'hiring', 'resource-manager', 'brick-office'];
|
|
1218
|
+
for (const skill of coreSkills) {
|
|
1219
|
+
const srcPath = path.join(PKG_ROOT, 'HR-Resource', skill, 'SKILL.md');
|
|
1220
|
+
if (!fs.existsSync(srcPath)) continue;
|
|
1221
|
+
const srcBody = fs.readFileSync(srcPath, 'utf8');
|
|
1222
|
+
for (const root of [CLAUDE_SKILLS_DIR, CODEX_SKILLS_DIR]) {
|
|
1223
|
+
const destPath = path.join(root, `harness-${skill}`, 'SKILL.md');
|
|
1224
|
+
if (!fs.existsSync(destPath) || fs.readFileSync(destPath, 'utf8') !== srcBody) {
|
|
1225
|
+
flags.coreSkillsStale = true;
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
const poolPath = path.join(HARNESS_DIR, 'shared', 'HR-Resource', skill, 'SKILL.md');
|
|
1229
|
+
if (fs.existsSync(path.dirname(poolPath)) && (!fs.existsSync(poolPath) || fs.readFileSync(poolPath, 'utf8') !== srcBody)) {
|
|
1230
|
+
flags.hrResourcePoolStale = true;
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1197
1234
|
// Gotcha entry-level diff: for each bundled gotcha file, compare entry IDs.
|
|
1198
1235
|
// 사용자가 직접 추가한 [G-NNN] 은 절대 건드리지 않으며, 패키지에서 새로
|
|
1199
1236
|
// 도입된 시스템 entry 만 append 대상.
|
|
@@ -1266,6 +1303,27 @@ function detectMigrationNeeded() {
|
|
|
1266
1303
|
) flags.configLegacyRouting = true;
|
|
1267
1304
|
} catch {}
|
|
1268
1305
|
}
|
|
1306
|
+
if (fs.existsSync(rosterPath)) {
|
|
1307
|
+
try {
|
|
1308
|
+
const roster = JSON.parse(fs.readFileSync(rosterPath, 'utf8'));
|
|
1309
|
+
const hired = Array.isArray(roster.hired) ? roster.hired : [];
|
|
1310
|
+
flags.rosterCodexPathsMissing = hired.some((entry) => {
|
|
1311
|
+
if (!entry || typeof entry !== 'object' || !entry.worker) return false;
|
|
1312
|
+
const owner = entry.owner || entry.owningCxx;
|
|
1313
|
+
const flatClaude = /^\.claude\/skills\/[^/]+\/SKILL\.md$/.test(entry.skillPaths?.claude || '');
|
|
1314
|
+
const flatCodex = /^\.codex\/skills\/[^/]+\/SKILL\.md$/.test(entry.skillPaths?.codex || '');
|
|
1315
|
+
return !owner || !entry.skillPaths?.codex || !entry.skillPaths?.claude || /^\.claude\/skills\//.test(entry.skillPath || '') || flatClaude || flatCodex;
|
|
1316
|
+
});
|
|
1317
|
+
} catch {}
|
|
1318
|
+
}
|
|
1319
|
+
if (fs.existsSync(resourceIndexPath)) {
|
|
1320
|
+
try {
|
|
1321
|
+
const idx = JSON.parse(fs.readFileSync(resourceIndexPath, 'utf8'));
|
|
1322
|
+
if (!idx.invocation || !idx.invocation.codex || !idx.invocation.claude) {
|
|
1323
|
+
flags.resourceIndexCodexWordingMissing = true;
|
|
1324
|
+
}
|
|
1325
|
+
} catch {}
|
|
1326
|
+
}
|
|
1269
1327
|
if (fs.existsSync(memoryPath) && fs.existsSync(memoryTplPath)) {
|
|
1270
1328
|
try {
|
|
1271
1329
|
const userMem = fs.readFileSync(memoryPath, 'utf8');
|
|
@@ -1355,6 +1413,18 @@ function showMigrationProposal(flags) {
|
|
|
1355
1413
|
if (flags.configLegacyRouting) {
|
|
1356
1414
|
console.log(' • config.json: legacy dispatcher/conductor wording → v7 CEO/CXX wording');
|
|
1357
1415
|
}
|
|
1416
|
+
if (flags.coreSkillsStale) {
|
|
1417
|
+
console.log(' • .claude/.codex skills: harness-* core skills 최신 패키지로 refresh');
|
|
1418
|
+
}
|
|
1419
|
+
if (flags.hrResourcePoolStale) {
|
|
1420
|
+
console.log(' • .harness/shared/HR-Resource: core HR pool 최신 패키지로 refresh');
|
|
1421
|
+
}
|
|
1422
|
+
if (flags.rosterCodexPathsMissing) {
|
|
1423
|
+
console.log(' • hr-roster.json: 기존 hired worker 보존 + Claude/Codex skillPaths 보강');
|
|
1424
|
+
}
|
|
1425
|
+
if (flags.resourceIndexCodexWordingMissing) {
|
|
1426
|
+
console.log(' • resource-index.json: Claude/Codex skill invocation wording 보강');
|
|
1427
|
+
}
|
|
1358
1428
|
if (flags.memoryMissingSystemEntries && flags.memoryMissingSystemEntries.length) {
|
|
1359
1429
|
console.log(' • memory.md: 시스템 entry 누락 — append 가능');
|
|
1360
1430
|
console.log(' [' + flags.memoryMissingSystemEntries.join(', ') + ']');
|
|
@@ -1397,6 +1467,10 @@ function runMigrate(opts = {}) {
|
|
|
1397
1467
|
!flags.progressLegacyRouting &&
|
|
1398
1468
|
!flags.configMissingCompanyMode &&
|
|
1399
1469
|
!flags.configLegacyRouting &&
|
|
1470
|
+
!flags.coreSkillsStale &&
|
|
1471
|
+
!flags.hrResourcePoolStale &&
|
|
1472
|
+
!flags.rosterCodexPathsMissing &&
|
|
1473
|
+
!flags.resourceIndexCodexWordingMissing &&
|
|
1400
1474
|
(!flags.memoryMissingSystemEntries || flags.memoryMissingSystemEntries.length === 0) &&
|
|
1401
1475
|
gotchaMissingTotal === 0 &&
|
|
1402
1476
|
conventionMissingTotal === 0 &&
|
|
@@ -1405,7 +1479,7 @@ function runMigrate(opts = {}) {
|
|
|
1405
1479
|
console.log('');
|
|
1406
1480
|
let pkgVer = 'unknown';
|
|
1407
1481
|
try { pkgVer = JSON.parse(fs.readFileSync(path.join(PKG_ROOT, 'package.json'), 'utf8')).version; } catch {}
|
|
1408
|
-
log(`이미 최신 — bundle v${pkgVer} 일치, progress v${TARGET_PROGRESS_VERSION} v7 routing, config.company_mode, memory 시스템 entry, gotcha entry 모두 sync.`);
|
|
1482
|
+
log(`이미 최신 — bundle v${pkgVer} 일치, progress v${TARGET_PROGRESS_VERSION} v7 routing, config.company_mode, Codex skill wiring, memory 시스템 entry, gotcha entry 모두 sync.`);
|
|
1409
1483
|
return;
|
|
1410
1484
|
}
|
|
1411
1485
|
|
|
@@ -1474,6 +1548,99 @@ function runMigrate(opts = {}) {
|
|
|
1474
1548
|
}
|
|
1475
1549
|
}
|
|
1476
1550
|
|
|
1551
|
+
// 2a. Refresh installed core harness skills and HR core pool without
|
|
1552
|
+
// touching hired worker skills or roster state.
|
|
1553
|
+
if (flags.hrResourcePoolStale) {
|
|
1554
|
+
const hrResourceSrc = path.join(PKG_ROOT, 'HR-Resource');
|
|
1555
|
+
const hrResourceDest = path.join(HARNESS_DIR, 'shared', 'HR-Resource');
|
|
1556
|
+
if (fs.existsSync(hrResourceSrc)) {
|
|
1557
|
+
log(' .harness/shared/HR-Resource: core pool refresh');
|
|
1558
|
+
if (!dryRun) copyDir(hrResourceSrc, hrResourceDest);
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
if (flags.coreSkillsStale) {
|
|
1562
|
+
log(' .claude/.codex skills: harness-* core skills refresh');
|
|
1563
|
+
if (!dryRun) installSkills();
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
// 2b. hr-roster.json — preserve hired worker history, add tool-specific
|
|
1567
|
+
// paths so Codex can reuse existing hires without relying on .claude.
|
|
1568
|
+
const rosterPath = path.join(HARNESS_DIR, 'shared', 'hr-roster.json');
|
|
1569
|
+
if (flags.rosterCodexPathsMissing && fs.existsSync(rosterPath)) {
|
|
1570
|
+
const original = fs.readFileSync(rosterPath, 'utf8');
|
|
1571
|
+
try {
|
|
1572
|
+
const roster = JSON.parse(original);
|
|
1573
|
+
const hired = Array.isArray(roster.hired) ? roster.hired : [];
|
|
1574
|
+
let changed = false;
|
|
1575
|
+
roster.hired = hired.map((entry) => {
|
|
1576
|
+
if (!entry || typeof entry !== 'object' || !entry.worker) return entry;
|
|
1577
|
+
const worker = entry.worker;
|
|
1578
|
+
const owner = entry.owner || entry.owningCxx || 'unknown';
|
|
1579
|
+
const scopedPrefix = owner ? `${owner}/` : '';
|
|
1580
|
+
const claudePath = entry.skillPaths?.claude || (
|
|
1581
|
+
/^\.claude\/skills\//.test(entry.skillPath || '')
|
|
1582
|
+
? entry.skillPath
|
|
1583
|
+
: `.claude/skills/${scopedPrefix}${worker}/SKILL.md`
|
|
1584
|
+
);
|
|
1585
|
+
const codexPath = entry.skillPaths?.codex || (
|
|
1586
|
+
/^\.codex\/skills\//.test(entry.skillPath || '')
|
|
1587
|
+
? entry.skillPath
|
|
1588
|
+
: `.codex/skills/${scopedPrefix}${worker}/SKILL.md`
|
|
1589
|
+
);
|
|
1590
|
+
const next = {
|
|
1591
|
+
...entry,
|
|
1592
|
+
owner,
|
|
1593
|
+
skillPath: `.harness/shared/HR-Resource/${worker}/SKILL.md`,
|
|
1594
|
+
skillPaths: {
|
|
1595
|
+
...(entry.skillPaths || {}),
|
|
1596
|
+
claude: /^\.claude\/skills\/[^/]+\/SKILL\.md$/.test(claudePath)
|
|
1597
|
+
? `.claude/skills/${scopedPrefix}${worker}/SKILL.md`
|
|
1598
|
+
: claudePath,
|
|
1599
|
+
codex: /^\.codex\/skills\/[^/]+\/SKILL\.md$/.test(codexPath)
|
|
1600
|
+
? `.codex/skills/${scopedPrefix}${worker}/SKILL.md`
|
|
1601
|
+
: codexPath,
|
|
1602
|
+
source: `.harness/shared/HR-Resource/${worker}/SKILL.md`,
|
|
1603
|
+
},
|
|
1604
|
+
};
|
|
1605
|
+
if (JSON.stringify(next) !== JSON.stringify(entry)) changed = true;
|
|
1606
|
+
return next;
|
|
1607
|
+
});
|
|
1608
|
+
if (changed) {
|
|
1609
|
+
log(` hr-roster.json: ${roster.hired.length}개 hired worker에 Codex 경로 보강`);
|
|
1610
|
+
if (!dryRun) {
|
|
1611
|
+
fs.writeFileSync(path.join(backupDir, 'hr-roster.json'), original);
|
|
1612
|
+
fs.writeFileSync(rosterPath, JSON.stringify(roster, null, 2) + '\n');
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
} catch (e) {
|
|
1616
|
+
log(` WARNING: hr-roster.json parse failed, skipped (${e.message})`);
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
// 2c. resource-index.json — keep aliases/keywords, add tool wording.
|
|
1621
|
+
const resourceIndexPath = path.join(HARNESS_DIR, 'shared', 'resource-index.json');
|
|
1622
|
+
if (flags.resourceIndexCodexWordingMissing && fs.existsSync(resourceIndexPath)) {
|
|
1623
|
+
const original = fs.readFileSync(resourceIndexPath, 'utf8');
|
|
1624
|
+
try {
|
|
1625
|
+
const idx = JSON.parse(original);
|
|
1626
|
+
idx.aliases = idx.aliases || {};
|
|
1627
|
+
idx.keywords = idx.keywords || {};
|
|
1628
|
+
idx.invocation = {
|
|
1629
|
+
...(idx.invocation || {}),
|
|
1630
|
+
claude: 'Invoke the installed skill by name from .claude/skills/{owning-cxx}/{worker}/SKILL.md.',
|
|
1631
|
+
codex: 'Use the installed skill by name from .codex/skills/{owning-cxx}/{worker}/SKILL.md.',
|
|
1632
|
+
source: 'Candidate pool lives in .harness/shared/HR-Resource/{worker}/SKILL.md.',
|
|
1633
|
+
};
|
|
1634
|
+
log(' resource-index.json: Claude/Codex invocation wording 보강');
|
|
1635
|
+
if (!dryRun) {
|
|
1636
|
+
fs.writeFileSync(path.join(backupDir, 'resource-index.json'), original);
|
|
1637
|
+
fs.writeFileSync(resourceIndexPath, JSON.stringify(idx, null, 2) + '\n');
|
|
1638
|
+
}
|
|
1639
|
+
} catch (e) {
|
|
1640
|
+
log(` WARNING: resource-index.json parse failed, skipped (${e.message})`);
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1477
1644
|
// 3. memory.md — append missing system entries (M-NEXUS-*, M-SYS-*) only.
|
|
1478
1645
|
// User-added [M-NNN] entries are NEVER touched.
|
|
1479
1646
|
const memoryPath = path.join(HARNESS_DIR, 'memory.md');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@walwal-harness/cli",
|
|
3
|
-
"version": "7.1.
|
|
3
|
+
"version": "7.1.6",
|
|
4
4
|
"description": "Company-style AI agent harness for Claude and Codex. Installs commands, CXX agents, skills, HR-Resource hiring pool, and project-local .harness runtime state.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"walwal-harness": "bin/init.js"
|
|
@@ -11,6 +11,16 @@ mode="${2:-text}"
|
|
|
11
11
|
violations=()
|
|
12
12
|
|
|
13
13
|
has_worker_report() {
|
|
14
|
+
local mission_dir="$1"
|
|
15
|
+
local owner="${2:-}"
|
|
16
|
+
if [ -n "$owner" ]; then
|
|
17
|
+
find "$mission_dir/$owner/workers" -maxdepth 1 -type f -name '*.md' 2>/dev/null | grep -q .
|
|
18
|
+
else
|
|
19
|
+
find "$mission_dir"/{coo,cdo,cto,cqo,ops}/workers -maxdepth 1 -type f -name '*.md' 2>/dev/null | grep -q .
|
|
20
|
+
fi
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
has_legacy_flat_worker_report() {
|
|
14
24
|
local mission_dir="$1"
|
|
15
25
|
find "$mission_dir/workers" -maxdepth 1 -type f -name '*.md' 2>/dev/null | grep -q .
|
|
16
26
|
}
|
|
@@ -19,16 +29,21 @@ for mission_dir in "$DOC_ROOT"/*; do
|
|
|
19
29
|
[ -d "$mission_dir" ] || continue
|
|
20
30
|
mission_name="$(basename "$mission_dir")"
|
|
21
31
|
|
|
22
|
-
|
|
32
|
+
if has_legacy_flat_worker_report "$mission_dir"; then
|
|
33
|
+
violations+=("$mission_name:legacy-flat-workers")
|
|
34
|
+
fi
|
|
35
|
+
|
|
23
36
|
for cxx in coo cdo cto cqo ops; do
|
|
24
37
|
cxx_path="$mission_dir/$cxx.md"
|
|
25
38
|
[ -s "$cxx_path" ] || continue
|
|
26
|
-
|
|
39
|
+
if ! has_worker_report "$mission_dir" "$cxx"; then
|
|
40
|
+
violations+=("$mission_name:$cxx.md")
|
|
41
|
+
fi
|
|
27
42
|
done
|
|
28
43
|
|
|
29
|
-
|
|
30
|
-
if ! has_worker_report "$mission_dir"; then
|
|
31
|
-
violations+=("$mission_name
|
|
44
|
+
cqo_path="$mission_dir/cqo.md"
|
|
45
|
+
if [ -s "$cqo_path" ] && grep -Eq '\b(ACCEPTED|REJECTED|PASS|FAIL)\b' "$cqo_path" && ! has_worker_report "$mission_dir" "cqo"; then
|
|
46
|
+
violations+=("$mission_name:cqo-verdict-without-evaluator")
|
|
32
47
|
fi
|
|
33
48
|
done
|
|
34
49
|
|
|
@@ -51,8 +66,8 @@ else
|
|
|
51
66
|
mission="${violation%%:*}"
|
|
52
67
|
docs="${violation#*:}"
|
|
53
68
|
echo "- mission: $mission"
|
|
54
|
-
echo "
|
|
55
|
-
echo " required:
|
|
69
|
+
echo " issue: $docs"
|
|
70
|
+
echo " required: worker reports under .harness/documents/$mission/{cxx}/workers/{worker-name}.md"
|
|
56
71
|
done
|
|
57
72
|
fi
|
|
58
73
|
|