harnery 0.34.1 → 0.35.0
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/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +2 -0
- package/dist/commands/agents.d.ts +15 -4
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +89 -175
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +26 -2
- package/dist/commands/decision.d.ts.map +1 -1
- package/dist/commands/decision.js +2 -2
- package/dist/commands/events.d.ts.map +1 -1
- package/dist/commands/events.js +18 -1
- package/dist/commands/presence.d.ts.map +1 -1
- package/dist/commands/presence.js +2 -2
- package/dist/commands/semantic.d.ts +4 -0
- package/dist/commands/semantic.d.ts.map +1 -0
- package/dist/commands/semantic.js +147 -0
- package/dist/commands/web.d.ts.map +1 -1
- package/dist/commands/web.js +17 -0
- package/dist/core/agents/canonical-emit.d.ts +3 -0
- package/dist/core/agents/canonical-emit.d.ts.map +1 -1
- package/dist/core/agents/canonical-emit.js +12 -0
- package/dist/core/agents/claim-path.d.ts +11 -0
- package/dist/core/agents/claim-path.d.ts.map +1 -0
- package/dist/core/agents/claim-path.js +22 -0
- package/dist/core/agents/coord-client.d.ts +29 -3
- package/dist/core/agents/coord-client.d.ts.map +1 -1
- package/dist/core/agents/coord-client.js +88 -9
- package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
- package/dist/core/agents/live-authority-v3.js +1 -3
- package/dist/core/agents/live-lifecycle-v3.js +3 -3
- package/dist/core/agents/live-observation-v3.d.ts.map +1 -1
- package/dist/core/agents/live-observation-v3.js +2 -2
- package/dist/core/agents/render/prompt-context.js +12 -10
- package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
- package/dist/core/agents/rules/stop-hook.js +23 -11
- package/dist/core/agents/session-name-display.d.ts +1 -0
- package/dist/core/agents/session-name-display.d.ts.map +1 -1
- package/dist/core/agents/session-name-display.js +8 -1
- package/dist/core/agents/state/heartbeat-reader.d.ts +46 -0
- package/dist/core/agents/state/heartbeat-reader.d.ts.map +1 -0
- package/dist/core/agents/state/heartbeat-reader.js +25 -0
- package/dist/core/agents/state/heartbeat-writer.d.ts +3 -48
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +16 -34
- package/dist/core/agents/state/live-coordination-view.d.ts +1 -1
- package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.js +25 -1
- package/dist/core/agents/state/names.d.ts +9 -1
- package/dist/core/agents/state/names.d.ts.map +1 -1
- package/dist/core/agents/state/names.js +190 -182
- package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
- package/dist/core/agents/state/stale-sweep.js +23 -5
- package/dist/core/artifacts/constants.d.ts +5 -0
- package/dist/core/artifacts/constants.d.ts.map +1 -0
- package/dist/core/artifacts/constants.js +4 -0
- package/dist/core/artifacts/index.d.ts +3 -3
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +50 -7
- package/dist/core/events/v3/base-contract.d.ts +795 -0
- package/dist/core/events/v3/base-contract.d.ts.map +1 -1
- package/dist/core/events/v3/base-contract.js +33 -0
- package/dist/core/events/v3/capabilities.d.ts +11 -0
- package/dist/core/events/v3/capabilities.d.ts.map +1 -1
- package/dist/core/events/v3/capabilities.js +23 -0
- package/dist/core/events/v3/generated.d.ts +1 -1
- package/dist/core/events/v3/generated.js +1 -1
- package/dist/core/events/v3/index.d.ts +4 -3
- package/dist/core/events/v3/index.d.ts.map +1 -1
- package/dist/core/events/v3/index.js +4 -3
- package/dist/core/events/v3/latency.d.ts +31 -1
- package/dist/core/events/v3/latency.d.ts.map +1 -1
- package/dist/core/events/v3/latency.js +127 -3
- package/dist/core/events/v3/live-routing.d.ts +30 -0
- package/dist/core/events/v3/live-routing.d.ts.map +1 -1
- package/dist/core/events/v3/live-routing.js +109 -1
- package/dist/core/events/v3/producers/command-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/command-recorder.js +10 -1
- package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/coordination-recorder.js +14 -3
- package/dist/core/events/v3/producers/hook-base.d.ts +17 -1
- package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -1
- package/dist/core/events/v3/producers/hook-base.js +82 -1
- package/dist/core/events/v3/producers/intake.d.ts +6 -0
- package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
- package/dist/core/events/v3/producers/intake.js +11 -0
- package/dist/core/events/v3/producers/recorder.d.ts +62 -0
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +654 -18
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts +51 -0
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts.map +1 -0
- package/dist/core/events/v3/runtime-telemetry-capabilities.js +54 -0
- package/dist/core/events/v3/turn-telemetry.d.ts +9 -0
- package/dist/core/events/v3/turn-telemetry.d.ts.map +1 -1
- package/dist/core/hooks/adapter/parse.d.ts +3 -0
- package/dist/core/hooks/adapter/parse.d.ts.map +1 -1
- package/dist/core/hooks/adapter/parse.js +14 -0
- package/dist/core/hooks/adapter/runtime-telemetry.d.ts +119 -0
- package/dist/core/hooks/adapter/runtime-telemetry.d.ts.map +1 -0
- package/dist/core/hooks/adapter/runtime-telemetry.js +568 -0
- package/dist/core/hooks/cli.js +111 -36
- package/dist/core/hooks/remediation-cap.d.ts +34 -0
- package/dist/core/hooks/remediation-cap.d.ts.map +1 -0
- package/dist/core/hooks/remediation-cap.js +71 -0
- package/dist/core/hooks/resolve/transcript.d.ts +25 -9
- package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
- package/dist/core/hooks/resolve/transcript.js +22 -10
- package/dist/core/semantic/adapters.d.ts +34 -0
- package/dist/core/semantic/adapters.d.ts.map +1 -0
- package/dist/core/semantic/adapters.js +222 -0
- package/dist/core/semantic/contract.d.ts +588 -0
- package/dist/core/semantic/contract.d.ts.map +1 -0
- package/dist/core/semantic/contract.js +230 -0
- package/dist/core/semantic/evidence.d.ts +11 -0
- package/dist/core/semantic/evidence.d.ts.map +1 -0
- package/dist/core/semantic/evidence.js +262 -0
- package/dist/core/semantic/index.d.ts +10 -0
- package/dist/core/semantic/index.d.ts.map +1 -0
- package/dist/core/semantic/index.js +9 -0
- package/dist/core/semantic/once.d.ts +33 -0
- package/dist/core/semantic/once.d.ts.map +1 -0
- package/dist/core/semantic/once.js +293 -0
- package/dist/core/semantic/prompt.d.ts +12 -0
- package/dist/core/semantic/prompt.d.ts.map +1 -0
- package/dist/core/semantic/prompt.js +70 -0
- package/dist/core/semantic/scheduler.d.ts +16 -0
- package/dist/core/semantic/scheduler.d.ts.map +1 -0
- package/dist/core/semantic/scheduler.js +67 -0
- package/dist/core/semantic/service-status.d.ts +31 -0
- package/dist/core/semantic/service-status.d.ts.map +1 -0
- package/dist/core/semantic/service-status.js +84 -0
- package/dist/core/semantic/service.d.ts +51 -0
- package/dist/core/semantic/service.d.ts.map +1 -0
- package/dist/core/semantic/service.js +470 -0
- package/dist/core/semantic/storage.d.ts +71 -0
- package/dist/core/semantic/storage.d.ts.map +1 -0
- package/dist/core/semantic/storage.js +179 -0
- package/dist/core/semantic/validate.d.ts +16 -0
- package/dist/core/semantic/validate.d.ts.map +1 -0
- package/dist/core/semantic/validate.js +174 -0
- package/dist/lib/browser/client.d.ts +11 -0
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +13 -0
- package/dist/lib/browser/index.d.ts +1 -0
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/standalone-html.d.ts +25 -0
- package/dist/lib/browser/standalone-html.d.ts.map +1 -0
- package/dist/lib/browser/standalone-html.js +284 -0
- package/dist/lib/instructions/apply.d.ts.map +1 -1
- package/dist/lib/instructions/apply.js +1 -0
- package/dist/lib/instructions/templates.d.ts +2 -0
- package/dist/lib/instructions/templates.d.ts.map +1 -1
- package/dist/lib/instructions/templates.js +144 -4
- package/package.json +6 -1
- package/schemas/event-v3.schema.json +2758 -478
- package/src/commander.ts +2 -0
- package/src/commands/agents.ts +102 -167
- package/src/commands/browse.ts +25 -2
- package/src/commands/decision.ts +8 -2
- package/src/commands/events.ts +21 -1
- package/src/commands/presence.ts +7 -2
- package/src/commands/semantic.ts +179 -0
- package/src/commands/web.ts +15 -0
- package/src/core/agents/canonical-emit.ts +15 -0
- package/src/core/agents/claim-path.ts +23 -0
- package/src/core/agents/coord-client.ts +92 -8
- package/src/core/agents/live-authority-v3.ts +1 -4
- package/src/core/agents/live-lifecycle-v3.ts +8 -3
- package/src/core/agents/live-observation-v3.ts +7 -2
- package/src/core/agents/render/prompt-context.ts +13 -10
- package/src/core/agents/rules/stop-hook.ts +24 -11
- package/src/core/agents/session-name-display.ts +9 -1
- package/src/core/agents/state/heartbeat-reader.ts +69 -0
- package/src/core/agents/state/heartbeat-writer.ts +20 -84
- package/src/core/agents/state/live-coordination-view.ts +26 -1
- package/src/core/agents/state/names.ts +190 -182
- package/src/core/agents/state/stale-sweep.ts +25 -5
- package/src/core/artifacts/constants.ts +4 -0
- package/src/core/artifacts/index.ts +49 -7
- package/src/core/events/v3/base-contract.ts +39 -0
- package/src/core/events/v3/capabilities.ts +34 -0
- package/src/core/events/v3/generated.ts +1 -1
- package/src/core/events/v3/index.ts +21 -0
- package/src/core/events/v3/latency.ts +213 -2
- package/src/core/events/v3/live-routing.ts +120 -1
- package/src/core/events/v3/producers/command-recorder.ts +10 -1
- package/src/core/events/v3/producers/coordination-recorder.ts +17 -5
- package/src/core/events/v3/producers/hook-base.ts +115 -1
- package/src/core/events/v3/producers/intake.ts +18 -0
- package/src/core/events/v3/producers/recorder.ts +856 -21
- package/src/core/events/v3/runtime-telemetry-capabilities.ts +137 -0
- package/src/core/events/v3/turn-telemetry.ts +10 -0
- package/src/core/hooks/adapter/parse.ts +16 -0
- package/src/core/hooks/adapter/runtime-telemetry.ts +805 -0
- package/src/core/hooks/cli.ts +123 -39
- package/src/core/hooks/remediation-cap.ts +77 -0
- package/src/core/hooks/resolve/transcript.ts +37 -11
- package/src/core/semantic/adapters.ts +293 -0
- package/src/core/semantic/contract.ts +298 -0
- package/src/core/semantic/evidence.ts +336 -0
- package/src/core/semantic/index.ts +127 -0
- package/src/core/semantic/once.ts +410 -0
- package/src/core/semantic/prompt.ts +84 -0
- package/src/core/semantic/scheduler.ts +107 -0
- package/src/core/semantic/service-status.ts +118 -0
- package/src/core/semantic/service.ts +580 -0
- package/src/core/semantic/storage.ts +286 -0
- package/src/core/semantic/validate.ts +212 -0
- package/src/lib/browser/client.ts +21 -0
- package/src/lib/browser/index.ts +4 -0
- package/src/lib/browser/standalone-html.ts +312 -0
- package/src/lib/instructions/apply.ts +1 -0
- package/src/lib/instructions/templates.ts +149 -4
|
@@ -5,6 +5,14 @@
|
|
|
5
5
|
* Layout invariant: 260 entries (10 per starting letter A..Z). Counter N
|
|
6
6
|
* picks COORD_NAMES[N % 260]; wraps to A at N=260.
|
|
7
7
|
*
|
|
8
|
+
* Gender invariant: within each 26-name pass the names alternate female/male
|
|
9
|
+
* letter by letter, so every pass is 13 female and 13 male. Five passes start
|
|
10
|
+
* female at A (1, 3, 5, 7, 9) and five start male (2, 4, 6, 8, 10), which gives
|
|
11
|
+
* each letter exactly five names of each gender and the pool 130/130 overall.
|
|
12
|
+
* This exists so a fixed set of 13 female and 13 male portraits can dress one
|
|
13
|
+
* whole pass. Adding or reordering a name must preserve it; the expected
|
|
14
|
+
* pattern is pinned in tests/unit/names-pool.test.ts.
|
|
15
|
+
*
|
|
8
16
|
* Durable persistence: `.harnery/.name-history` (JSONL, one row per assignment)
|
|
9
17
|
* + `.harnery/.name-counter` (current counter, atomic temp+rename).
|
|
10
18
|
*
|
|
@@ -24,274 +32,274 @@ import { dirname, join } from "node:path";
|
|
|
24
32
|
|
|
25
33
|
/** All 260 names. */
|
|
26
34
|
export const COORD_NAMES = [
|
|
27
|
-
// Pass 1
|
|
35
|
+
// Pass 1 — female-first (A=female), alternating to Z
|
|
28
36
|
"Anna",
|
|
29
37
|
"Bob",
|
|
30
|
-
"
|
|
31
|
-
"
|
|
38
|
+
"Carmen",
|
|
39
|
+
"Dorian",
|
|
32
40
|
"Erika",
|
|
33
41
|
"Fred",
|
|
34
42
|
"Gemma",
|
|
35
43
|
"Hank",
|
|
36
44
|
"Imelda",
|
|
37
45
|
"Jerry",
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
46
|
+
"Karen",
|
|
47
|
+
"Lorenzo",
|
|
48
|
+
"Mindy",
|
|
41
49
|
"Nate",
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
50
|
+
"Odette",
|
|
51
|
+
"Peter",
|
|
52
|
+
"Quinn",
|
|
45
53
|
"Rafael",
|
|
46
54
|
"Sara",
|
|
47
55
|
"Tony",
|
|
48
|
-
"
|
|
49
|
-
"
|
|
56
|
+
"Ursula",
|
|
57
|
+
"Vinson",
|
|
50
58
|
"Whitney",
|
|
51
59
|
"Xander",
|
|
52
60
|
"Yara",
|
|
53
|
-
"
|
|
54
|
-
// Pass 2
|
|
55
|
-
"
|
|
61
|
+
"Zane",
|
|
62
|
+
// Pass 2 — male-first (A=male), alternating to Z
|
|
63
|
+
"Alex",
|
|
56
64
|
"Bertha",
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
65
|
+
"Carlos",
|
|
66
|
+
"Dalia",
|
|
67
|
+
"Ernesto",
|
|
60
68
|
"Francine",
|
|
61
|
-
"
|
|
69
|
+
"Gordon",
|
|
62
70
|
"Helene",
|
|
63
|
-
"
|
|
71
|
+
"Isaias",
|
|
64
72
|
"Joyce",
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
73
|
+
"Kirk",
|
|
74
|
+
"Lucia",
|
|
75
|
+
"Milton",
|
|
68
76
|
"Nadine",
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
77
|
+
"Oscar",
|
|
78
|
+
"Patty",
|
|
79
|
+
"Quentin",
|
|
72
80
|
"Rebekah",
|
|
73
81
|
"Sean",
|
|
74
82
|
"Tammy",
|
|
75
|
-
"
|
|
76
|
-
"
|
|
83
|
+
"Ulrik",
|
|
84
|
+
"Valerie",
|
|
77
85
|
"Wallace",
|
|
78
86
|
"Xanthe",
|
|
79
87
|
"Yusuf",
|
|
80
|
-
"
|
|
81
|
-
// Pass 3
|
|
82
|
-
"
|
|
88
|
+
"Zara",
|
|
89
|
+
// Pass 3 — female-first (A=female), alternating to Z
|
|
90
|
+
"Adelaide",
|
|
91
|
+
"Bruno",
|
|
92
|
+
"Cora",
|
|
93
|
+
"Damon",
|
|
94
|
+
"Edna",
|
|
95
|
+
"Felix",
|
|
96
|
+
"Greta",
|
|
97
|
+
"Hugo",
|
|
98
|
+
"Ines",
|
|
99
|
+
"Jasper",
|
|
100
|
+
"Kaia",
|
|
101
|
+
"Larry",
|
|
102
|
+
"Maxine",
|
|
103
|
+
"Nicholas",
|
|
104
|
+
"Olive",
|
|
105
|
+
"Paxton",
|
|
106
|
+
"Querida",
|
|
107
|
+
"Roman",
|
|
108
|
+
"Stella",
|
|
109
|
+
"Tobias",
|
|
110
|
+
"Una",
|
|
111
|
+
"Virgil",
|
|
112
|
+
"Willow",
|
|
113
|
+
"Xavier",
|
|
114
|
+
"Yolanda",
|
|
115
|
+
"Zephyr",
|
|
116
|
+
// Pass 4 — male-first (A=male), alternating to Z
|
|
117
|
+
"Aaron",
|
|
83
118
|
"Beatrice",
|
|
84
119
|
"Cyrus",
|
|
85
120
|
"Delia",
|
|
86
|
-
"
|
|
121
|
+
"Elias",
|
|
87
122
|
"Florence",
|
|
88
|
-
"
|
|
123
|
+
"Galileo",
|
|
89
124
|
"Hester",
|
|
90
|
-
"
|
|
125
|
+
"Ian",
|
|
91
126
|
"Jenna",
|
|
92
127
|
"Klaus",
|
|
93
|
-
"
|
|
94
|
-
"
|
|
95
|
-
"
|
|
128
|
+
"Linda",
|
|
129
|
+
"Marco",
|
|
130
|
+
"Nora",
|
|
96
131
|
"Otto",
|
|
97
|
-
"
|
|
132
|
+
"Paulette",
|
|
98
133
|
"Quill",
|
|
99
134
|
"Renee",
|
|
100
|
-
"
|
|
135
|
+
"Sebastian",
|
|
101
136
|
"Theresa",
|
|
102
137
|
"Umberto",
|
|
103
|
-
"
|
|
104
|
-
"
|
|
105
|
-
"
|
|
106
|
-
"
|
|
107
|
-
"
|
|
108
|
-
// Pass
|
|
138
|
+
"Vera",
|
|
139
|
+
"Walter",
|
|
140
|
+
"Xena",
|
|
141
|
+
"Yves",
|
|
142
|
+
"Zoe",
|
|
143
|
+
// Pass 5 — female-first (A=female), alternating to Z
|
|
109
144
|
"Anita",
|
|
110
|
-
"
|
|
111
|
-
"
|
|
112
|
-
"
|
|
145
|
+
"Beau",
|
|
146
|
+
"Celeste",
|
|
147
|
+
"Dexter",
|
|
113
148
|
"Edith",
|
|
114
|
-
"
|
|
149
|
+
"Fitz",
|
|
115
150
|
"Gloria",
|
|
116
|
-
"
|
|
151
|
+
"Hadley",
|
|
117
152
|
"Iris",
|
|
118
|
-
"Jasper",
|
|
119
|
-
"Kaia",
|
|
120
|
-
"Linda",
|
|
121
|
-
"Marco",
|
|
122
|
-
"Nora",
|
|
123
|
-
"Olive",
|
|
124
|
-
"Petra",
|
|
125
|
-
"Querida",
|
|
126
|
-
"Roman",
|
|
127
|
-
"Sebastian",
|
|
128
|
-
"Tobias",
|
|
129
|
-
"Una",
|
|
130
|
-
"Vera",
|
|
131
|
-
"Walter",
|
|
132
|
-
"Xena",
|
|
133
|
-
"Yusra",
|
|
134
|
-
"Zelda",
|
|
135
|
-
// Pass 5
|
|
136
|
-
"Aaron",
|
|
137
|
-
"Bonnie",
|
|
138
|
-
"Caleb",
|
|
139
|
-
"Daphne",
|
|
140
|
-
"Elias",
|
|
141
|
-
"Fiona",
|
|
142
|
-
"Galileo",
|
|
143
|
-
"Hugo",
|
|
144
|
-
"Ian",
|
|
145
153
|
"Jude",
|
|
146
|
-
"
|
|
154
|
+
"Kira",
|
|
147
155
|
"Leo",
|
|
148
156
|
"Maya",
|
|
149
157
|
"Nash",
|
|
150
|
-
"
|
|
151
|
-
"
|
|
158
|
+
"Olga",
|
|
159
|
+
"Phillip",
|
|
152
160
|
"Quetzal",
|
|
153
|
-
"
|
|
161
|
+
"Royce",
|
|
154
162
|
"Sage",
|
|
155
|
-
"
|
|
156
|
-
"
|
|
163
|
+
"Trent",
|
|
164
|
+
"Uma",
|
|
157
165
|
"Vincent",
|
|
158
|
-
"
|
|
159
|
-
"
|
|
166
|
+
"Wynne",
|
|
167
|
+
"Xerxes",
|
|
160
168
|
"Yvette",
|
|
161
|
-
"
|
|
162
|
-
// Pass 6
|
|
163
|
-
"
|
|
164
|
-
"
|
|
165
|
-
"
|
|
166
|
-
"
|
|
169
|
+
"Zoltan",
|
|
170
|
+
// Pass 6 — male-first (A=male), alternating to Z
|
|
171
|
+
"Andre",
|
|
172
|
+
"Bonnie",
|
|
173
|
+
"Caleb",
|
|
174
|
+
"Daphne",
|
|
167
175
|
"Ezra",
|
|
168
|
-
"
|
|
169
|
-
"
|
|
170
|
-
"
|
|
171
|
-
"
|
|
172
|
-
"
|
|
173
|
-
"
|
|
176
|
+
"Fiona",
|
|
177
|
+
"Gibson",
|
|
178
|
+
"Holly",
|
|
179
|
+
"Ivan",
|
|
180
|
+
"Juno",
|
|
181
|
+
"Knox",
|
|
174
182
|
"Lila",
|
|
175
183
|
"Mason",
|
|
176
184
|
"Nila",
|
|
177
|
-
"
|
|
178
|
-
"
|
|
185
|
+
"Owen",
|
|
186
|
+
"Petra",
|
|
179
187
|
"Quincy",
|
|
180
|
-
"
|
|
188
|
+
"Rosa",
|
|
181
189
|
"Sterling",
|
|
182
|
-
"
|
|
183
|
-
"
|
|
190
|
+
"Talia",
|
|
191
|
+
"Uri",
|
|
184
192
|
"Violet",
|
|
185
|
-
"
|
|
186
|
-
"
|
|
187
|
-
"
|
|
188
|
-
"
|
|
189
|
-
// Pass 7
|
|
190
|
-
"
|
|
191
|
-
"
|
|
192
|
-
"
|
|
193
|
-
"
|
|
193
|
+
"Wesley",
|
|
194
|
+
"Ximena",
|
|
195
|
+
"Yuri",
|
|
196
|
+
"Zelda",
|
|
197
|
+
// Pass 7 — female-first (A=female), alternating to Z
|
|
198
|
+
"Astrid",
|
|
199
|
+
"Boris",
|
|
200
|
+
"Cassidy",
|
|
201
|
+
"Davis",
|
|
194
202
|
"Esme",
|
|
195
|
-
"
|
|
196
|
-
"
|
|
197
|
-
"
|
|
198
|
-
"
|
|
199
|
-
"
|
|
200
|
-
"
|
|
203
|
+
"Forrest",
|
|
204
|
+
"Genevieve",
|
|
205
|
+
"Henry",
|
|
206
|
+
"Imogen",
|
|
207
|
+
"Joaquin",
|
|
208
|
+
"Kestrel",
|
|
201
209
|
"Luther",
|
|
202
210
|
"Margot",
|
|
203
211
|
"Nigel",
|
|
204
|
-
"
|
|
205
|
-
"
|
|
212
|
+
"Ophelia",
|
|
213
|
+
"Percy",
|
|
206
214
|
"Quenby",
|
|
207
215
|
"Reagan",
|
|
208
216
|
"Sienna",
|
|
209
|
-
"
|
|
210
|
-
"
|
|
211
|
-
"
|
|
212
|
-
"
|
|
213
|
-
"
|
|
214
|
-
"
|
|
215
|
-
"
|
|
216
|
-
// Pass 8
|
|
217
|
-
"
|
|
218
|
-
"
|
|
219
|
-
"
|
|
220
|
-
"
|
|
217
|
+
"Truman",
|
|
218
|
+
"Undine",
|
|
219
|
+
"Voss",
|
|
220
|
+
"Wren",
|
|
221
|
+
"Xan",
|
|
222
|
+
"Yael",
|
|
223
|
+
"Zia",
|
|
224
|
+
// Pass 8 — male-first (A=male), alternating to Z
|
|
225
|
+
"Arthur",
|
|
226
|
+
"Bianca",
|
|
227
|
+
"Cody",
|
|
228
|
+
"Dahlia",
|
|
221
229
|
"Evander",
|
|
222
|
-
"
|
|
223
|
-
"
|
|
224
|
-
"
|
|
225
|
-
"
|
|
226
|
-
"
|
|
227
|
-
"
|
|
230
|
+
"Fern",
|
|
231
|
+
"Gustavo",
|
|
232
|
+
"Harriet",
|
|
233
|
+
"Ira",
|
|
234
|
+
"Josephine",
|
|
235
|
+
"Kendrick",
|
|
228
236
|
"Lainey",
|
|
229
237
|
"Miles",
|
|
230
238
|
"Naomi",
|
|
231
|
-
"
|
|
232
|
-
"
|
|
239
|
+
"Orion",
|
|
240
|
+
"Pearl",
|
|
233
241
|
"Quark",
|
|
234
242
|
"Rylie",
|
|
235
243
|
"Saul",
|
|
236
|
-
"
|
|
237
|
-
"
|
|
238
|
-
"
|
|
239
|
-
"
|
|
240
|
-
"
|
|
241
|
-
"
|
|
242
|
-
"
|
|
243
|
-
// Pass 9
|
|
244
|
-
"
|
|
245
|
-
"
|
|
246
|
-
"
|
|
247
|
-
"
|
|
244
|
+
"Tessa",
|
|
245
|
+
"Ulysses",
|
|
246
|
+
"Vesper",
|
|
247
|
+
"Wyatt",
|
|
248
|
+
"Xiomara",
|
|
249
|
+
"Yancy",
|
|
250
|
+
"Zinnia",
|
|
251
|
+
// Pass 9 — female-first (A=female), alternating to Z
|
|
252
|
+
"Amelia",
|
|
253
|
+
"Barnaby",
|
|
254
|
+
"Calliope",
|
|
255
|
+
"Drake",
|
|
248
256
|
"Estelle",
|
|
249
|
-
"
|
|
250
|
-
"
|
|
251
|
-
"
|
|
252
|
-
"
|
|
253
|
-
"
|
|
254
|
-
"
|
|
255
|
-
"
|
|
257
|
+
"Foster",
|
|
258
|
+
"Greer",
|
|
259
|
+
"Hollis",
|
|
260
|
+
"Irene",
|
|
261
|
+
"Jericho",
|
|
262
|
+
"Klara",
|
|
263
|
+
"Logan",
|
|
256
264
|
"Mavis",
|
|
257
265
|
"Nico",
|
|
258
|
-
"
|
|
259
|
-
"
|
|
260
|
-
"
|
|
266
|
+
"Oakley",
|
|
267
|
+
"Pascal",
|
|
268
|
+
"Quito",
|
|
261
269
|
"Rhett",
|
|
262
270
|
"Scout",
|
|
263
|
-
"
|
|
271
|
+
"Theron",
|
|
264
272
|
"Unity",
|
|
265
|
-
"
|
|
266
|
-
"
|
|
267
|
-
"
|
|
268
|
-
"
|
|
273
|
+
"Vance",
|
|
274
|
+
"Winifred",
|
|
275
|
+
"Xola",
|
|
276
|
+
"Yvonne",
|
|
269
277
|
"Zev",
|
|
270
|
-
// Pass 10
|
|
278
|
+
// Pass 10 — male-first (A=male), alternating to Z
|
|
271
279
|
"Atticus",
|
|
272
|
-
"
|
|
273
|
-
"
|
|
274
|
-
"
|
|
280
|
+
"Brenda",
|
|
281
|
+
"Crispin",
|
|
282
|
+
"Dolores",
|
|
275
283
|
"Eustace",
|
|
276
|
-
"
|
|
284
|
+
"Felicity",
|
|
277
285
|
"Granger",
|
|
278
|
-
"
|
|
279
|
-
"
|
|
280
|
-
"
|
|
281
|
-
"
|
|
282
|
-
"
|
|
286
|
+
"Hazel",
|
|
287
|
+
"Idris",
|
|
288
|
+
"Jovi",
|
|
289
|
+
"Kasper",
|
|
290
|
+
"Lyric",
|
|
283
291
|
"Magnus",
|
|
284
292
|
"Noor",
|
|
285
|
-
"
|
|
286
|
-
"
|
|
287
|
-
"
|
|
293
|
+
"Otis",
|
|
294
|
+
"Phoebe",
|
|
295
|
+
"Querubin",
|
|
288
296
|
"Rosalind",
|
|
289
|
-
"
|
|
290
|
-
"
|
|
297
|
+
"Silas",
|
|
298
|
+
"Tatum",
|
|
291
299
|
"Upton",
|
|
292
|
-
"
|
|
300
|
+
"Vivian",
|
|
293
301
|
"Wendell",
|
|
294
|
-
"
|
|
302
|
+
"Xuxa",
|
|
295
303
|
"Yann",
|
|
296
304
|
"Zora",
|
|
297
305
|
] as const;
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import { existsSync, readdirSync, readFileSync, statSync, unlinkSync } from "node:fs";
|
|
14
14
|
import { join } from "node:path";
|
|
15
15
|
import { coordFreshnessSeconds } from "../../config.ts";
|
|
16
|
+
import { writeProducerDiagnosticV3 } from "../../events/v3/producers/intake.ts";
|
|
16
17
|
import { recordLiveSweepObservationV3 } from "../live-lifecycle-v3.ts";
|
|
17
18
|
|
|
18
19
|
/** platform → adapter, for the swept-event envelope (mirrors heartbeat-writer's adapterOf). */
|
|
@@ -22,7 +23,15 @@ function adapterFromPlatform(platform: unknown): "claude-code" | "cursor" | "cod
|
|
|
22
23
|
return "claude-code";
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Record the sweep before deleting disposable cache state.
|
|
28
|
+
*
|
|
29
|
+
* A joinable generation owns the canonical provisional observation. Once that
|
|
30
|
+
* generation is terminal or unavailable, it must not be reopened merely to
|
|
31
|
+
* authorize cache housekeeping. Preserve the failed observation in the V3
|
|
32
|
+
* diagnostics spool instead. If neither durable record can be written, fail
|
|
33
|
+
* closed and keep the file.
|
|
34
|
+
*/
|
|
26
35
|
function emitSwept(
|
|
27
36
|
coordRoot: string,
|
|
28
37
|
instanceId: string,
|
|
@@ -46,8 +55,18 @@ function emitSwept(
|
|
|
46
55
|
ageMs: Math.max(0, (ageSecs ?? 0) * 1_000),
|
|
47
56
|
});
|
|
48
57
|
return true;
|
|
49
|
-
} catch {
|
|
50
|
-
return
|
|
58
|
+
} catch (error) {
|
|
59
|
+
return Boolean(
|
|
60
|
+
writeProducerDiagnosticV3(coordRoot, "heartbeat_sweep_unrecorded", {
|
|
61
|
+
adapter,
|
|
62
|
+
instance_id: instanceId,
|
|
63
|
+
signal: "lifecycle.sweep_observed",
|
|
64
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
65
|
+
state: "cache_cleanup_pending",
|
|
66
|
+
observation: reason,
|
|
67
|
+
age_ms: Math.max(0, (ageSecs ?? 0) * 1_000),
|
|
68
|
+
}),
|
|
69
|
+
);
|
|
51
70
|
}
|
|
52
71
|
}
|
|
53
72
|
|
|
@@ -85,8 +104,9 @@ export function staleSweep(coordRoot: string): {
|
|
|
85
104
|
// a transient (mid-write / partial read), and deleting it would nuke a
|
|
86
105
|
// LIVE agent's heartbeat, the worst possible outcome. So: never reap a
|
|
87
106
|
// fresh file on a content failure.
|
|
88
|
-
// Every deletion
|
|
89
|
-
//
|
|
107
|
+
// Every deletion leaves durable audit evidence. A joinable generation gets
|
|
108
|
+
// lifecycle.sweep_observed; a terminal or unavailable generation gets a
|
|
109
|
+
// heartbeat_sweep_unrecorded producer diagnostic without being resurrected.
|
|
90
110
|
const liveInstanceIds = new Set<string>();
|
|
91
111
|
const d = join(coordRoot, ".harnery", "active");
|
|
92
112
|
if (existsSync(d)) {
|
|
@@ -24,10 +24,9 @@ import {
|
|
|
24
24
|
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
25
25
|
import { readLiveCoordinationRow } from "../agents/state/live-coordination-view.ts";
|
|
26
26
|
import { artifactDefaultRetentionDays } from "../config.ts";
|
|
27
|
+
import { ARTIFACT_MANIFEST, ARTIFACT_SCHEMA_VERSION, ARTIFACTS_DIR } from "./constants.ts";
|
|
27
28
|
|
|
28
|
-
export
|
|
29
|
-
export const ARTIFACT_MANIFEST = ".harnery-artifact.json";
|
|
30
|
-
export const ARTIFACT_SCHEMA_VERSION = 1 as const;
|
|
29
|
+
export { ARTIFACT_MANIFEST, ARTIFACT_SCHEMA_VERSION, ARTIFACTS_DIR } from "./constants.ts";
|
|
31
30
|
|
|
32
31
|
export interface ArtifactActor {
|
|
33
32
|
instance_id: string;
|
|
@@ -72,6 +71,7 @@ export interface ArtifactInventoryEntry {
|
|
|
72
71
|
artifact_id: string | null;
|
|
73
72
|
slug: string | null;
|
|
74
73
|
created_at: string | null;
|
|
74
|
+
last_modified_at: string | null;
|
|
75
75
|
expires_at: string | null;
|
|
76
76
|
owner_instance_id: string | null;
|
|
77
77
|
}
|
|
@@ -328,16 +328,22 @@ function classifyArtifactPath(
|
|
|
328
328
|
}
|
|
329
329
|
const manifest = parsed.manifest;
|
|
330
330
|
const bytes = safeTreeSize(path);
|
|
331
|
+
const lastModifiedMs = safeTreeLastModified(path, now);
|
|
332
|
+
const retentionAnchorMs = Date.parse(manifest.retention.renewed_at ?? manifest.created_at);
|
|
333
|
+
const retentionWindowMs = Date.parse(manifest.retention.expires_at) - retentionAnchorMs;
|
|
334
|
+
const effectiveLastModifiedMs = Math.max(retentionAnchorMs, lastModifiedMs ?? 0);
|
|
335
|
+
const effectiveExpiresAt = new Date(effectiveLastModifiedMs + retentionWindowMs).toISOString();
|
|
331
336
|
const base = rowFor(path, name, repoRoot, "managed-current", "retention has not expired", bytes);
|
|
332
337
|
Object.assign(base, {
|
|
333
338
|
artifact_id: manifest.artifact_id,
|
|
334
339
|
slug: manifest.slug,
|
|
335
340
|
created_at: manifest.created_at,
|
|
336
|
-
|
|
341
|
+
last_modified_at: new Date(effectiveLastModifiedMs).toISOString(),
|
|
342
|
+
expires_at: effectiveExpiresAt,
|
|
337
343
|
owner_instance_id: manifest.created_by?.instance_id ?? null,
|
|
338
344
|
});
|
|
339
345
|
|
|
340
|
-
if (base.bytes === null) {
|
|
346
|
+
if (base.bytes === null || lastModifiedMs === null) {
|
|
341
347
|
return {
|
|
342
348
|
...base,
|
|
343
349
|
classification: "unknown",
|
|
@@ -372,11 +378,11 @@ function classifyArtifactPath(
|
|
|
372
378
|
};
|
|
373
379
|
}
|
|
374
380
|
}
|
|
375
|
-
if (Date.parse(
|
|
381
|
+
if (Date.parse(effectiveExpiresAt) > now.getTime()) return base;
|
|
376
382
|
return {
|
|
377
383
|
...base,
|
|
378
384
|
classification: "managed-expired",
|
|
379
|
-
reason: `retention expired at ${
|
|
385
|
+
reason: `retention expired at ${effectiveExpiresAt}`,
|
|
380
386
|
action: "would-delete",
|
|
381
387
|
};
|
|
382
388
|
}
|
|
@@ -410,6 +416,13 @@ function readManifest(path: string): ParsedManifest | ManifestError {
|
|
|
410
416
|
if (!m.retention || typeof m.retention !== "object" || !validIso(m.retention.expires_at)) {
|
|
411
417
|
return { ok: false, reason: "invalid retention.expires_at" };
|
|
412
418
|
}
|
|
419
|
+
if (m.retention.renewed_at !== undefined && !validIso(m.retention.renewed_at)) {
|
|
420
|
+
return { ok: false, reason: "invalid retention.renewed_at" };
|
|
421
|
+
}
|
|
422
|
+
const retentionAnchor = Date.parse(m.retention.renewed_at ?? m.created_at);
|
|
423
|
+
if (Date.parse(m.retention.expires_at) <= retentionAnchor) {
|
|
424
|
+
return { ok: false, reason: "retention.expires_at must follow its retention anchor" };
|
|
425
|
+
}
|
|
413
426
|
if (m.released_at !== undefined && !validIso(m.released_at)) {
|
|
414
427
|
return { ok: false, reason: "invalid released_at" };
|
|
415
428
|
}
|
|
@@ -478,6 +491,34 @@ function safeTreeSize(path: string): number | null {
|
|
|
478
491
|
}
|
|
479
492
|
}
|
|
480
493
|
|
|
494
|
+
/**
|
|
495
|
+
* Return the newest filesystem change in a managed tree without following
|
|
496
|
+
* symlinks. A small future tolerance protects a write racing the inventory
|
|
497
|
+
* scan; timestamps farther ahead are ignored as clock-skewed metadata.
|
|
498
|
+
*/
|
|
499
|
+
function safeTreeLastModified(path: string, now: Date): number | null {
|
|
500
|
+
const nowMs = now.getTime();
|
|
501
|
+
const futureToleranceMs = 5 * 60 * 1000;
|
|
502
|
+
try {
|
|
503
|
+
const st = lstatSync(path);
|
|
504
|
+
let latest = 0;
|
|
505
|
+
for (const timestamp of [st.mtimeMs, st.ctimeMs]) {
|
|
506
|
+
if (Number.isFinite(timestamp) && timestamp <= nowMs + futureToleranceMs) {
|
|
507
|
+
latest = Math.max(latest, Math.min(timestamp, nowMs));
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
if (st.isSymbolicLink() || !st.isDirectory()) return latest;
|
|
511
|
+
for (const child of readdirSync(path)) {
|
|
512
|
+
const childLatest = safeTreeLastModified(join(path, child), now);
|
|
513
|
+
if (childLatest === null) return null;
|
|
514
|
+
latest = Math.max(latest, childLatest);
|
|
515
|
+
}
|
|
516
|
+
return latest;
|
|
517
|
+
} catch {
|
|
518
|
+
return null;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
481
522
|
function rowFor(
|
|
482
523
|
path: string,
|
|
483
524
|
name: string,
|
|
@@ -497,6 +538,7 @@ function rowFor(
|
|
|
497
538
|
artifact_id: null,
|
|
498
539
|
slug: null,
|
|
499
540
|
created_at: null,
|
|
541
|
+
last_modified_at: null,
|
|
500
542
|
expires_at: null,
|
|
501
543
|
owner_instance_id: null,
|
|
502
544
|
};
|