@walwal-harness/cli 7.1.31 → 7.1.33
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 +4 -0
- package/HR-Resource/coo/SKILL.md +4 -0
- package/HR-Resource/cqo/SKILL.md +4 -0
- package/HR-Resource/cto/SKILL.md +4 -0
- package/HR-Resource/ops/SKILL.md +4 -0
- package/README.md +1 -0
- package/apps/harness-dashboard/components/Scene.tsx +4 -8
- package/apps/harness-dashboard/lib/__tests__/harness-state.test.ts +26 -0
- package/apps/harness-dashboard/lib/harness-state.ts +13 -11
- package/package.json +1 -1
- package/scripts/harness-activity-record.js +2 -2
package/HR-Resource/cdo/SKILL.md
CHANGED
|
@@ -25,6 +25,10 @@ Before design work, read `.harness/conventions/shared.md`, `.harness/conventions
|
|
|
25
25
|
8. Select the final direction and write a CDO preview artifact at `.harness/documents/{mission_name}/cdo/preview.html`.
|
|
26
26
|
9. Report to CEO and CTO with a concise preview summary and mention that the visual sample is available in the dashboard by clicking harness-cdo.
|
|
27
27
|
|
|
28
|
+
## Worker Activity Telemetry
|
|
29
|
+
|
|
30
|
+
Before launching any fresh worker session, update `.harness/progress.json` with `scripts/harness-progress-set.sh` so dashboards can show the worker as active. Record the worker name, owning CXX, report path, and `status:"running"` under `company_state.workers`, increment `company_state.active_workers`, and set `conductor.current_action` to `spawn:{worker-name}`. After the worker report is accepted, update that worker to `status:"complete"` and decrement `active_workers`. Do not leave `active_workers:0` while a worker session is running.
|
|
31
|
+
|
|
28
32
|
## Rule
|
|
29
33
|
|
|
30
34
|
Design output must be usable by implementation teams, not just descriptive.
|
package/HR-Resource/coo/SKILL.md
CHANGED
|
@@ -35,6 +35,10 @@ During planning, COO must determine whether the active runtime exposes MCP serve
|
|
|
35
35
|
7. Review worker reports against the goal.
|
|
36
36
|
8. Reassign work or report to CEO.
|
|
37
37
|
|
|
38
|
+
## Worker Activity Telemetry
|
|
39
|
+
|
|
40
|
+
Before launching any fresh worker session, update `.harness/progress.json` with `scripts/harness-progress-set.sh` so dashboards can show the worker as active. Record the worker name, owning CXX, report path, and `status:"running"` under `company_state.workers`, increment `company_state.active_workers`, and set `conductor.current_action` to `spawn:{worker-name}`. After the worker report is accepted, update that worker to `status:"complete"` and decrement `active_workers`. Do not leave `active_workers:0` while a worker session is running.
|
|
41
|
+
|
|
38
42
|
## Non-Execution Rule
|
|
39
43
|
|
|
40
44
|
COO must not directly produce research findings, sprint plans, feed lists, market conclusions, backtest scripts, or documentation deliverables. COO may only frame the question, select and brief workers, evaluate worker output, and record the accepted decision.
|
package/HR-Resource/cqo/SKILL.md
CHANGED
|
@@ -24,6 +24,10 @@ Before quality work, read `.harness/conventions/shared.md`, `.harness/convention
|
|
|
24
24
|
7. Monitor repeated issues and promote verified lessons to `.harness/conventions`, `.harness/gotchas`, `.harness/memories`, or `.harness/shared`.
|
|
25
25
|
8. Approve or reject archive based solely on worker-provided evidence and OPS runtime/watch evidence when the mission uses a runnable environment.
|
|
26
26
|
|
|
27
|
+
## Worker Activity Telemetry
|
|
28
|
+
|
|
29
|
+
Before launching any fresh worker session, update `.harness/progress.json` with `scripts/harness-progress-set.sh` so dashboards can show the worker as active. Record the worker name, owning CXX, report path, and `status:"running"` under `company_state.workers`, increment `company_state.active_workers`, and set `conductor.current_action` to `spawn:{worker-name}`. After the worker report is accepted, update that worker to `status:"complete"` and decrement `active_workers`. Do not leave `active_workers:0` while a worker session is running.
|
|
30
|
+
|
|
27
31
|
## Hard Rules
|
|
28
32
|
|
|
29
33
|
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.
|
package/HR-Resource/cto/SKILL.md
CHANGED
|
@@ -26,6 +26,10 @@ Before engineering work, read `.harness/conventions/shared.md`, `.harness/conven
|
|
|
26
26
|
9. Delegate all implementation and technical deliverables to hired workers in fresh sessions.
|
|
27
27
|
10. Collect reports, resolve blockers, and hand completed work to CQO.
|
|
28
28
|
|
|
29
|
+
## Worker Activity Telemetry
|
|
30
|
+
|
|
31
|
+
Before launching any fresh worker session, update `.harness/progress.json` with `scripts/harness-progress-set.sh` so dashboards can show the worker as active. Record the worker name, owning CXX, report path, and `status:"running"` under `company_state.workers`, increment `company_state.active_workers`, and set `conductor.current_action` to `spawn:{worker-name}`. After the worker report is accepted, update that worker to `status:"complete"` and decrement `active_workers`. Do not leave `active_workers:0` while a worker session is running.
|
|
32
|
+
|
|
29
33
|
## Hard Rules
|
|
30
34
|
|
|
31
35
|
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.
|
package/HR-Resource/ops/SKILL.md
CHANGED
|
@@ -66,6 +66,10 @@ After service launch, OPS continues the same monitoring duty against `runtime.pr
|
|
|
66
66
|
10. Classify exceptions as verification, build, backend, frontend, platform, external API, infrastructure, owner-config, production, or unknown.
|
|
67
67
|
11. Raise emergency events to CEO/CTO/CQO with evidence and the mapped environment record.
|
|
68
68
|
|
|
69
|
+
## Worker Activity Telemetry
|
|
70
|
+
|
|
71
|
+
Before launching any fresh worker session, update `.harness/progress.json` with `scripts/harness-progress-set.sh` so dashboards can show the worker as active. Record the worker name, owning CXX, report path, and `status:"running"` under `company_state.workers`, increment `company_state.active_workers`, and set `conductor.current_action` to `spawn:{worker-name}`. After the worker report is accepted, update that worker to `status:"complete"` and decrement `active_workers`. Do not leave `active_workers:0` while a worker session is running.
|
|
72
|
+
|
|
69
73
|
## Required Output Sections
|
|
70
74
|
|
|
71
75
|
1. Worker Task Briefs — monitoring/recovery task, capability needed, selected worker or hiring request, acceptance criteria.
|
package/README.md
CHANGED
|
@@ -283,6 +283,7 @@ harness-hiring → register and onboard worker
|
|
|
283
283
|
|
|
284
284
|
| Version | Summary |
|
|
285
285
|
|---|---|
|
|
286
|
+
| 7.1.33 | Dashboard keeps recently written worker reports active even when docmeta is present, and CXX skills now record worker activity telemetry for live dashboard state |
|
|
286
287
|
| 7.1.31 | Persist dashboard heatmap activity to 7-day JSONL logs, load persisted samples in the dashboard, and backfill activity during migrate from existing mission docs/progress logs |
|
|
287
288
|
| 7.1.29 | Idempotent AGENTS/CLAUDE doc merge with marked harness sections, mission lifecycle backfill for init/migrate, completion closes todos and mission-state, and Layer Activity now lists CXX/worker rows sorted by remaining work |
|
|
288
289
|
| 7.1.28 | Dashboard APM rewrite: top header consolidation, Knowledge Base panel (gotchas/conventions), Layer Activity (CEO/CXX/Worker TODO·DONE·Remain via goal-scope inference), Recent Report list (worker mtime desc), Cadence strip with click-to-prompt tooltip in local timezone, heatmap click-tooltip with empty-cell guard, Document Viewer expand-to-50vw with docmeta hidden, Command Log bubble popover |
|
|
@@ -159,20 +159,16 @@ export function Scene({ snapshot: initial, lang = "ko" }: SceneProps) {
|
|
|
159
159
|
const activeMission = selectedMission ?? snapshot.missions[0] ?? null;
|
|
160
160
|
const next: HeatSample[] = [];
|
|
161
161
|
for (const lane of lanes) {
|
|
162
|
-
//
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
// 2 = in-progress (actively running right now)
|
|
162
|
+
// Live overlay records active work only. Historical participation is
|
|
163
|
+
// backfilled from persisted activity logs; completed reports must not
|
|
164
|
+
// keep repainting the current minute forever.
|
|
166
165
|
let activity = 0;
|
|
167
166
|
if (lane.kind === "worker") {
|
|
168
167
|
const w = lane.worker;
|
|
169
168
|
if (w) {
|
|
170
169
|
if (w.active || w.status === "IN_PROGRESS") activity = 2;
|
|
171
|
-
else if (w.content || w.status === "COMPLETE") activity = 1;
|
|
172
170
|
}
|
|
173
171
|
} else {
|
|
174
|
-
const presentInMission =
|
|
175
|
-
lane.mission?.cxxPresent.includes(lane.role) ?? false;
|
|
176
172
|
const liveTodos = snapshot.todos.filter(
|
|
177
173
|
(t) =>
|
|
178
174
|
t.owner === lane.role &&
|
|
@@ -183,7 +179,7 @@ export function Scene({ snapshot: initial, lang = "ko" }: SceneProps) {
|
|
|
183
179
|
(w) => w.active || w.status === "IN_PROGRESS"
|
|
184
180
|
).length;
|
|
185
181
|
if (liveTodos > 0 && runningWorkers === 0) activity = 2;
|
|
186
|
-
else if (
|
|
182
|
+
else if (runningWorkers > 0) activity = 2;
|
|
187
183
|
}
|
|
188
184
|
if (activity <= 0) continue;
|
|
189
185
|
next.push({
|
|
@@ -381,4 +381,30 @@ describe("readHarnessState", () => {
|
|
|
381
381
|
active: false,
|
|
382
382
|
});
|
|
383
383
|
});
|
|
384
|
+
|
|
385
|
+
it("keeps recently written docmeta worker reports active without an explicit COMPLETE marker", () => {
|
|
386
|
+
const harnessDir = path.join(dir, ".harness");
|
|
387
|
+
const missionDir = path.join(harnessDir, "documents", "goal-1-dashboard");
|
|
388
|
+
mkdirSync(path.join(missionDir, "cto", "workers"), { recursive: true });
|
|
389
|
+
writeFileSync(path.join(missionDir, "ceo.md"), "# Dashboard\n");
|
|
390
|
+
writeFileSync(
|
|
391
|
+
path.join(missionDir, "cto", "workers", "frontend-worker.md"),
|
|
392
|
+
"---\ndocmeta:\n id: frontend-worker\n---\n\n# Worker Report\n\nEvidence is still being appended.\n"
|
|
393
|
+
);
|
|
394
|
+
writeFileSync(
|
|
395
|
+
path.join(harnessDir, "progress.json"),
|
|
396
|
+
JSON.stringify({
|
|
397
|
+
current_agent: "ceo",
|
|
398
|
+
agent_status: "running",
|
|
399
|
+
company_state: { active_workers: 0, workers: [] },
|
|
400
|
+
})
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
const workers = readHarnessState(dir).missions[0].workers;
|
|
404
|
+
expect(workers[0]).toMatchObject({
|
|
405
|
+
name: "frontend-worker",
|
|
406
|
+
status: "IN_PROGRESS",
|
|
407
|
+
active: true,
|
|
408
|
+
});
|
|
409
|
+
});
|
|
384
410
|
});
|
|
@@ -1220,16 +1220,6 @@ function readMissions(rootDir: string, progress: RawProgress | null = null, limi
|
|
|
1220
1220
|
if (!f.endsWith(".md")) continue;
|
|
1221
1221
|
const reportAbs = path.join(missionPath, relDir, f);
|
|
1222
1222
|
const content = readMd(`${relDir}/${f}`) ?? "";
|
|
1223
|
-
const statusMatch = content.match(/##\s*Status\s*\n+([A-Z_]+)/);
|
|
1224
|
-
// Worker docs sometimes omit the "## Status" block but always carry a
|
|
1225
|
-
// docmeta frontmatter when the worker submitted its output. Treat the
|
|
1226
|
-
// presence of a docmeta block (or a non-empty body) as COMPLETE.
|
|
1227
|
-
const hasDocmeta = /^---[\s\S]*?docmeta:[\s\S]*?---/.test(content);
|
|
1228
|
-
const status: WorkerDocEntry["status"] = statusMatch
|
|
1229
|
-
? (statusMatch[1] as WorkerDocEntry["status"])
|
|
1230
|
-
: hasDocmeta
|
|
1231
|
-
? "COMPLETE"
|
|
1232
|
-
: "unknown";
|
|
1233
1223
|
const name = normalizeWorkerName(f);
|
|
1234
1224
|
const hired = hiredForMission(hiredWorkers, name, owner, rel);
|
|
1235
1225
|
let updatedAt: string | null = null;
|
|
@@ -1239,6 +1229,18 @@ function readMissions(rootDir: string, progress: RawProgress | null = null, limi
|
|
|
1239
1229
|
updatedAt = mtime.toISOString();
|
|
1240
1230
|
recentlyTouched = Date.now() - mtime.getTime() < RECENT_WORKER_ACTIVE_MS;
|
|
1241
1231
|
} catch { /* ignore */ }
|
|
1232
|
+
const statusMatch = content.match(/##\s*Status\s*\n+([A-Z_]+)/);
|
|
1233
|
+
const hasDocmeta = /^---[\s\S]*?docmeta:[\s\S]*?---/.test(content);
|
|
1234
|
+
// Worker docs often write docmeta before appending final evidence.
|
|
1235
|
+
// Without an explicit COMPLETE marker, keep recent writes visible as
|
|
1236
|
+
// active; after the activity window they become historical reports.
|
|
1237
|
+
const status: WorkerDocEntry["status"] = statusMatch
|
|
1238
|
+
? (statusMatch[1] as WorkerDocEntry["status"])
|
|
1239
|
+
: hasDocmeta && recentlyTouched && !runtimeIdle
|
|
1240
|
+
? "IN_PROGRESS"
|
|
1241
|
+
: hasDocmeta
|
|
1242
|
+
? "COMPLETE"
|
|
1243
|
+
: "unknown";
|
|
1242
1244
|
const entry: WorkerDocEntry = {
|
|
1243
1245
|
name,
|
|
1244
1246
|
displayName: workerDisplayName(content, hired, name),
|
|
@@ -1246,7 +1248,7 @@ function readMissions(rootDir: string, progress: RawProgress | null = null, limi
|
|
|
1246
1248
|
status,
|
|
1247
1249
|
owner: hired?.owner ?? owner,
|
|
1248
1250
|
hired: !!hired,
|
|
1249
|
-
active: !runtimeIdle && (activeWorkers.has(name) ||
|
|
1251
|
+
active: !runtimeIdle && (activeWorkers.has(name) || status === "IN_PROGRESS"),
|
|
1250
1252
|
sourcePath: hired?.sourcePath ?? null,
|
|
1251
1253
|
reportPath: path.relative(rootDir, reportAbs),
|
|
1252
1254
|
updatedAt,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@walwal-harness/cli",
|
|
3
|
-
"version": "7.1.
|
|
3
|
+
"version": "7.1.33",
|
|
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"
|
|
@@ -141,11 +141,11 @@ function currentSamples(root, now = Date.now()) {
|
|
|
141
141
|
const liveTodos = todos.filter((t) => t.owner === role && !["done", "completed"].includes(String(t.status)));
|
|
142
142
|
let count = 0;
|
|
143
143
|
if (!idle && liveTodos.length > 0 && runningWorkers.length === 0) count = 2;
|
|
144
|
-
else if (
|
|
144
|
+
else if (runningWorkers.length > 0) count = 2;
|
|
145
145
|
if (count > 0) samples.push({ ts: new Date(now).toISOString(), laneId: role, count, hotfix: active.missionId.includes("hotfix"), missionId: active.missionId });
|
|
146
146
|
}
|
|
147
147
|
for (const worker of active.workers) {
|
|
148
|
-
const count = !idle && !worker.complete && now - worker.updatedAt < RECENT_MS ? 2 :
|
|
148
|
+
const count = !idle && !worker.complete && now - worker.updatedAt < RECENT_MS ? 2 : 0;
|
|
149
149
|
if (count > 0) samples.push({ ts: new Date(now).toISOString(), laneId: worker.laneId, count, hotfix: active.missionId.includes("hotfix"), missionId: active.missionId });
|
|
150
150
|
}
|
|
151
151
|
return samples;
|