@event4u/agent-config 15.0.0 → 16.0.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/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +142 -348
- package/dist/agent-src/commands/roadmap/create.md +3 -2
- package/dist/agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +50 -0
- package/dist/agent-src/rules/user-interaction.md +31 -30
- package/dist/agent-src/skills/error-handling-patterns/SKILL.md +9 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/cli-delegate/{chunk-HZ52BRGG.js → chunk-H32DGUJH.js} +14 -89
- package/dist/cli-delegate/chunk-NUHLI2RX.js +80 -0
- package/dist/cli-delegate/{chunk-TYSY33MD.js → chunk-QJWAUMJW.js} +12 -2
- package/dist/cli-delegate/{chunk-2KKXJW25.js → chunk-S3VFXMTM.js} +1 -1
- package/dist/cli-delegate/cmd_conformance.js +831 -272
- package/dist/cli-delegate/cmd_explain.js +4 -2
- package/dist/cli-delegate/cmd_handoff.js +2 -2
- package/dist/cli-delegate/cmd_packs_active.js +2 -1
- package/dist/cli-delegate/cmd_session_recycle.js +2 -2
- package/dist/cli-delegate/cmd_settings_set.js +13 -0
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +5 -5
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +1274 -571
- package/dist/install/install.mjs +1 -0
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +1218 -632
- package/dist/scripts/_lib/installed_lock.js +1 -1
- package/dist/server/io/yamlIO.js +50 -0
- package/package.json +1 -1
- package/src/config/continuity-surface.json +7 -0
- package/src/config/gate-violation-baselines.json +3 -3
- package/src/config/host-injection-effect.json +1 -1
- package/src/config/preamble-payload-budget.json +12 -7
- package/src/config/preamble-payload-exceptions.json +28 -0
- package/src/scripts/_dispatch.bash +3 -1
- package/src/scripts/_lib/base_ref_payload.ts +315 -0
- package/src/scripts/_lib/dropped_decision.ts +142 -0
- package/src/scripts/_lib/installed_lock.ts +1 -1
- package/src/scripts/_lib/measured_payload_ceiling.ts +424 -0
- package/src/scripts/_lib/payload_catalogue_completeness.ts +211 -0
- package/src/scripts/_lib/release_findings_ingest.ts +324 -0
- package/src/scripts/_lib/release_tag_dispatch.ts +63 -0
- package/src/scripts/_lib/review_baseline.ts +254 -0
- package/src/scripts/_lib/review_skipped_record.ts +61 -1
- package/src/scripts/_lib/standing_bound_ratchet.ts +216 -103
- package/src/scripts/_lib/turn_end_refusals.ts +51 -4
- package/src/scripts/check_beta_review_markers.ts +35 -4
- package/src/scripts/check_finding_dispositions.ts +167 -16
- package/src/scripts/check_held_object_arrivals.ts +381 -0
- package/src/scripts/check_preamble_payload_budget.ts +399 -122
- package/src/scripts/check_release_published.ts +1 -1
- package/src/scripts/check_reply_consistency.ts +86 -17
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +39 -3
- package/src/scripts/hooks/block_kernel_rule_writes.ts +12 -2
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/end_review_nudge_hook.ts +101 -21
- package/src/scripts/hooks/review_baseline_hook.ts +130 -0
- package/src/scripts/hooks/turn_end_gate_hook.ts +232 -14
- package/src/scripts/hooks_doctor.ts +4 -1
- package/src/scripts/install.ts +1 -1
- package/src/scripts/interruption_report.ts +8 -2
- package/src/scripts/janitor.ts +8 -1
- package/src/scripts/measure_turn_end_gate.ts +302 -5
- package/src/scripts/release.ts +52 -64
- package/src/scripts/release_drill.ts +193 -14
- package/src/scripts/release_env.ts +1 -1
- package/src/scripts/release_publication.ts +1 -1
- package/src/scripts/report_held_object_arrivals.ts +456 -0
- package/src/scripts/sync_agent_settings.ts +140 -18
- package/src/server/io/yamlIO.ts +48 -0
|
@@ -272,8 +272,9 @@ Ask (in the user's language) exactly one numbered-options question:
|
|
|
272
272
|
|
|
273
273
|
> How should this roadmap be executed later?
|
|
274
274
|
>
|
|
275
|
-
> 1. Fully autonomous — one run-start contract confirmation, then
|
|
276
|
-
>
|
|
275
|
+
> 1. Fully autonomous — one run-start contract confirmation, then the
|
|
276
|
+
> only halts are the safety floors, a quality-red, and a step that
|
|
277
|
+
> reveals out-of-roadmap work
|
|
277
278
|
> 2. Checkpoint at phase boundaries — compact status + continue prompt
|
|
278
279
|
> per phase
|
|
279
280
|
> 3. Interactive — every gate fires as today
|
|
@@ -202,3 +202,53 @@ After completing a batch of actions, provide a summary table:
|
|
|
202
202
|
| 2 | `test.php` | Updated assertion |
|
|
203
203
|
| 3 | `config.php` | Skipped (intentional) |
|
|
204
204
|
```
|
|
205
|
+
|
|
206
|
+
## The trigger is a decision, not a format — the measurement behind it
|
|
207
|
+
|
|
208
|
+
Migrated out of `user-interaction.md` on 2026-09-11 to pay for Iron Law 3
|
|
209
|
+
under the per-spawn preamble budget. The obligation stays in the rule; this
|
|
210
|
+
is the evidence for it.
|
|
211
|
+
|
|
212
|
+
Measured (30-session conformance audit, 2026-08-06): **every** malformed ask
|
|
213
|
+
was a one-line parenthetical or a trailing free-text offer — a German
|
|
214
|
+
"say the word if I should take the three lines along", an English "shall I
|
|
215
|
+
implement it this way?" — while the same sessions formatted their **large**
|
|
216
|
+
asks perfectly. So the rule is being read as *if numbered options, then a
|
|
217
|
+
recommendation line*. It is the other way round, and an ask that feels too
|
|
218
|
+
small for a block is exactly the one that escapes the format.
|
|
219
|
+
|
|
220
|
+
Three further caught shapes: a contentless filler option; an inline
|
|
221
|
+
"(recommended)" tag **beside** the recommendation line (the dual source
|
|
222
|
+
Iron Law 1 forbids); an option set answerable only as `1,3,4`.
|
|
223
|
+
|
|
224
|
+
**No gate ships for this.** `check_reply_consistency` can read a draft on
|
|
225
|
+
stdin, but it inspects *numbered-option blocks* — and every measured failure
|
|
226
|
+
had no block by construction, so it scans exactly the surface that did not
|
|
227
|
+
fail. `conformance:behavior` deliberately does not score ask-shape, so an
|
|
228
|
+
unmoved rate is a finding rather than a silence.
|
|
229
|
+
|
|
230
|
+
## Iron Law 3 — why laws 1 and 2 do not reach across a turn boundary
|
|
231
|
+
|
|
232
|
+
Iron Laws 1 and 2 are discharged by the shape of the reply that carries the
|
|
233
|
+
block. Neither survives a turn boundary, which is the gap Iron Law 3 closes:
|
|
234
|
+
a second assistant execution with no user message between it and the ask is
|
|
235
|
+
not a new conversation, and from the user's side a thread that ends without
|
|
236
|
+
the question ended without the question.
|
|
237
|
+
|
|
238
|
+
**The measured failure.** A turn put three numbered options and a
|
|
239
|
+
recommendation line to the user. A `stop` concern then produced a second
|
|
240
|
+
assistant execution with no intervening user message, and that second reply
|
|
241
|
+
handled the concern while demoting the open question to a subordinate clause.
|
|
242
|
+
The four rules that could have caught it did not, each for a stated reason:
|
|
243
|
+
Iron Law 1 inspects a reply that HAS an options block, `check_reply_consistency`
|
|
244
|
+
receives a draft rather than a transcript, `active-remediation` governs
|
|
245
|
+
findings rather than issued decisions, and `no-cheap-questions` guards the
|
|
246
|
+
opposite direction.
|
|
247
|
+
|
|
248
|
+
**Carrier, stated honestly.** The deterministic half is the
|
|
249
|
+
`pending-decision` detector in `src/scripts/hooks/turn_end_gate_hook.ts` —
|
|
250
|
+
it refuses a turn-end when an earlier reply in the same user turn carried a
|
|
251
|
+
block and the closing reply carries none. It sees one user turn on one host,
|
|
252
|
+
so everything outside that is model-carried, exactly like Iron Law 2's own
|
|
253
|
+
"no gate ships for this" note. `check_reply_consistency` reads a single draft
|
|
254
|
+
and holds no cross-turn state; it cannot see this law at all.
|
|
@@ -19,9 +19,10 @@ obligation_frequency: "per-turn"
|
|
|
19
19
|
|
|
20
20
|
# User Interaction
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
Three Iron Laws govern a decision put to the user — two on the reply that
|
|
23
|
+
carries it, one on what happens if the agent runs again before the answer.
|
|
24
|
+
They override conversation momentum, brevity, and the urge to defer to the
|
|
25
|
+
user. **Missing a recommendation is a rule violation, not a slip.**
|
|
25
26
|
|
|
26
27
|
## Iron Law 1 — Single-Source Recommendation
|
|
27
28
|
|
|
@@ -43,14 +44,28 @@ EVERY REPLY WITH NUMBERED OPTIONS RUNS THE SELF-CHECK. NO EXCEPTIONS.
|
|
|
43
44
|
SKIPPING IT IS A RULE VIOLATION, NOT A SLIP.
|
|
44
45
|
```
|
|
45
46
|
|
|
46
|
-
Mechanical backstop
|
|
47
|
+
Mechanical backstop for Iron Laws 1 and 2 (non-zero exit on either), a safety
|
|
48
|
+
net under the self-scan rather than a replacement for it:
|
|
47
49
|
`./scripts-run src/scripts/check_reply_consistency --stdin < draft.md`
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
It takes a DRAFT, so it cannot see Iron Law 3, which is about a transcript.
|
|
51
|
+
|
|
52
|
+
## Iron Law 3 — A Decision Outlives the Turn
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
A DECISION HANDED TO THE USER STAYS LIVE UNTIL THE USER ANSWERS IT.
|
|
56
|
+
THE AGENT RUNS AGAIN WITHOUT AN ANSWER — HOOK CONTINUATION, NOTIFICATION,
|
|
57
|
+
WAKE, RETRY — AND THE BLOCK PLUS ITS RECOMMENDATION LINE ARE RE-PRESENTED
|
|
58
|
+
IN THE SAME FORM. A SUBORDINATE CLAUSE IS NOT A RE-PRESENTATION.
|
|
59
|
+
A HOOK'S CONCERN MAY BE ADDED TO A PENDING DECISION, NEVER REPLACE ONE.
|
|
60
|
+
ONLY THE USER CLOSES IT — BY ANSWERING, OR BY MAKING IT MOOT.
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Carrier: the `pending-decision` detector on `turn-end-gate`, one user turn on
|
|
64
|
+
one host; the rest is model-carried. Mechanics carries the measured failure.
|
|
50
65
|
|
|
51
66
|
## Question pacing — one decision point per turn
|
|
52
67
|
|
|
53
|
-
[`ask-when-uncertain`](ask-when-uncertain.md)'s Iron Law is canonical: **one question per turn**. What counts as "one question" is **one decision point** —
|
|
68
|
+
[`ask-when-uncertain`](ask-when-uncertain.md)'s Iron Law is canonical: **one question per turn**. What counts as "one question" is **one decision point** — one numbered-options block is ONE question even when its options span several dimensions, provided a single number answers it. Multiple separate asks in one reply, or a block needing a structured reply (`1a, 2b`), violate the kernel rule's self-check.
|
|
54
69
|
|
|
55
70
|
If in doubt, split into serial turns — never a long batched prompt.
|
|
56
71
|
|
|
@@ -62,33 +77,19 @@ NOT ON THE PRESENCE OF A NUMBERED LIST.
|
|
|
62
77
|
A TRAILING FREE-TEXT OFFER IS AN ASK. A BARE YES/NO IS AN ASK.
|
|
63
78
|
```
|
|
64
79
|
|
|
65
|
-
Measured (30-session
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
round, and an ask that feels too small for a block is exactly the one that
|
|
71
|
-
escapes the format. Three further caught shapes: a contentless filler option; an
|
|
72
|
-
inline `(Empfohlen)` tag **beside** the recommendation line (the dual source
|
|
73
|
-
Iron Law 1 forbids); an option set answerable only as `1,3,4`.
|
|
74
|
-
|
|
75
|
-
**No gate ships for this.** `check_reply_consistency` can read a draft on stdin,
|
|
76
|
-
but it inspects *numbered-option blocks* — and every measured failure had no
|
|
77
|
-
block by construction, so it scans exactly the surface that did not fail. `conformance:behavior` deliberately does not score ask-shape,
|
|
78
|
-
so an unmoved rate is a finding rather than a silence.
|
|
80
|
+
Measured (30-session audit, 2026-08-06): **every** malformed ask was a one-line
|
|
81
|
+
parenthetical or a trailing offer, while the same sessions formatted their
|
|
82
|
+
**large** asks perfectly — the ask that feels too small for a block is the one
|
|
83
|
+
that escapes the format. **No gate ships for this**: the backstop inspects
|
|
84
|
+
numbered-option blocks, and every measured failure had none. Detail: mechanics.
|
|
79
85
|
|
|
80
86
|
## Mechanics — rationale, failure modes, format details, examples
|
|
81
87
|
|
|
82
|
-
The
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
menu, trailing-question hedge, no-preference hedge, multi-block reply,
|
|
87
|
-
…), slip-handling protocol, numbered-options rules, format examples,
|
|
88
|
-
progress indicators, and summary-table patterns all live in
|
|
88
|
+
The rule above is the obligation surface. Everything you look up rather than
|
|
89
|
+
obey — why to take a position, the format spec, the five-step self-check, the
|
|
90
|
+
named failure-mode catalog, slip handling, examples, progress indicators and
|
|
91
|
+
summary patterns — is in
|
|
89
92
|
[`contexts/communication/rules-auto/user-interaction-mechanics.md`](../contexts/communication/rules-auto/user-interaction-mechanics.md).
|
|
90
|
-
The rule above is the obligation surface; the mechanics file is the
|
|
91
|
-
lookup material.
|
|
92
93
|
|
|
93
94
|
When the user pastes large tool output, logs, JSON, or API responses,
|
|
94
95
|
keep the reply narrow: extract only the relevant fields with targeted
|
|
@@ -79,6 +79,15 @@ Every produced error must carry: `code` (stable string), `message` (human-readab
|
|
|
79
79
|
|
|
80
80
|
Forbidden: secrets, raw SQL, full stack traces in user-facing surfaces, internal class names leaked through API boundaries.
|
|
81
81
|
|
|
82
|
+
**"User-facing" means PRODUCTION, and the missing half of that sentence cost a real failure.** Read without the qualifier — as it stood until 2026-09-11 — this clause forbids the developer's own diagnostics in their own dev environment, which is the opposite of what it is for. The measured consequence, reported by the maintainer: a feature whose detail view crashed on open and showed a blank region, so neither the developer nor the agent could see *what* was missing, and the failure had to be reconstructed by hand.
|
|
83
|
+
|
|
84
|
+
| Environment | What a failed render or request shows |
|
|
85
|
+
|---|---|
|
|
86
|
+
| local / dev / preview | the **full** diagnostic, visibly: what was expected, what arrived, which field or endpoint, the stack. A toast, an error overlay, an inline panel — anything the developer cannot miss. Silence here is the defect. |
|
|
87
|
+
| production | the sanitized payload above, plus a correlation id the developer can look up. Never the stack. |
|
|
88
|
+
|
|
89
|
+
**A blank page is never an acceptable failure mode in dev.** If a component cannot render because data is missing or a contract changed, it says so on screen in dev and degrades to a stated empty/error state in production — never to nothing. That is the same obligation the four completeness rows in [`ai-code-blindspots`](../ai-code-blindspots/SKILL.md) put on the render surface, stated here for the error path that reaches it.
|
|
90
|
+
|
|
82
91
|
### Step 5 — Define the boundary
|
|
83
92
|
|
|
84
93
|
Exactly **one** layer translates internal errors to the egress format (HTTP status + body, queue requeue policy, CLI exit code). Anywhere else doing this duplication is the bug.
|
|
@@ -39,7 +39,7 @@ schema_version: 1
|
|
|
39
39
|
# CI guard: a release bump of `package.json` must update this value
|
|
40
40
|
# in lockstep — see scripts/check_template_pin_drift.ts (road-to-
|
|
41
41
|
# portable-runtime-and-update-check P3.3).
|
|
42
|
-
agent_config_version: "
|
|
42
|
+
agent_config_version: "16.0.0"
|
|
43
43
|
|
|
44
44
|
# --- Project identity ---
|
|
45
45
|
project:
|
|
@@ -1,90 +1,16 @@
|
|
|
1
1
|
import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
artefact_roots
|
|
4
|
+
} from "./chunk-NUHLI2RX.js";
|
|
2
5
|
import {
|
|
3
6
|
DEFAULT_PROJECT_FILE,
|
|
4
7
|
logger
|
|
5
8
|
} from "./chunk-2XY7ILBT.js";
|
|
6
9
|
|
|
7
10
|
// src/scripts/config/profiles.ts
|
|
8
|
-
import * as fs2 from "node:fs";
|
|
9
|
-
import { createRequire } from "node:module";
|
|
10
|
-
import * as path3 from "node:path";
|
|
11
|
-
|
|
12
|
-
// src/scripts/_lib/agent_src.ts
|
|
13
11
|
import * as fs from "node:fs";
|
|
14
|
-
import
|
|
15
|
-
import { fileURLToPath } from "node:url";
|
|
16
|
-
|
|
17
|
-
// src/scripts/_lib/guidelines_lane.ts
|
|
12
|
+
import { createRequire } from "node:module";
|
|
18
13
|
import * as path from "node:path";
|
|
19
|
-
var GUIDELINES_SOURCE_REL = path.join("docs", "guidelines");
|
|
20
|
-
|
|
21
|
-
// src/scripts/_lib/agent_src.ts
|
|
22
|
-
var _HERE = path2.dirname(fileURLToPath(import.meta.url));
|
|
23
|
-
var _DEFAULT_ROOT = path2.resolve(_HERE, "..", "..", "..");
|
|
24
|
-
function _deriveRoots(root) {
|
|
25
|
-
const packages = path2.join(root, "packages");
|
|
26
|
-
const src = path2.join(root, "src");
|
|
27
|
-
return {
|
|
28
|
-
ROOT: root,
|
|
29
|
-
LEGACY_SRC: path2.join(root, ".agent-src.uncondensed"),
|
|
30
|
-
PACKAGES: packages,
|
|
31
|
-
PACKAGE_CORE: path2.join(packages, "core"),
|
|
32
|
-
SRC: src,
|
|
33
|
-
SRC_SKILLS: path2.join(src, "skills"),
|
|
34
|
-
SRC_RULES: path2.join(src, "rules"),
|
|
35
|
-
SRC_AGENT: path2.join(src, "agent-src"),
|
|
36
|
-
SRC_DOMAINS: path2.join(src, "domains")
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
var _roots = _deriveRoots(_DEFAULT_ROOT);
|
|
40
|
-
function _isDir(p) {
|
|
41
|
-
try {
|
|
42
|
-
return fs.statSync(p).isDirectory();
|
|
43
|
-
} catch {
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
function _exists(p) {
|
|
48
|
-
try {
|
|
49
|
-
fs.statSync(p);
|
|
50
|
-
return true;
|
|
51
|
-
} catch {
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
function _iterdirSorted(p) {
|
|
56
|
-
let names;
|
|
57
|
-
try {
|
|
58
|
-
names = fs.readdirSync(p);
|
|
59
|
-
} catch {
|
|
60
|
-
return [];
|
|
61
|
-
}
|
|
62
|
-
names.sort();
|
|
63
|
-
return names.map((name) => path2.join(p, name));
|
|
64
|
-
}
|
|
65
|
-
function artefact_roots() {
|
|
66
|
-
const roots = [];
|
|
67
|
-
if (_exists(_roots.LEGACY_SRC)) {
|
|
68
|
-
roots.push(_roots.LEGACY_SRC);
|
|
69
|
-
}
|
|
70
|
-
if (_exists(_roots.PACKAGES)) {
|
|
71
|
-
for (const pkg of _iterdirSorted(_roots.PACKAGES)) {
|
|
72
|
-
const sub = path2.join(pkg, ".agent-src.uncondensed");
|
|
73
|
-
if (_isDir(sub)) {
|
|
74
|
-
roots.push(sub);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
if (_isDir(_roots.SRC_AGENT)) {
|
|
79
|
-
roots.push(_roots.SRC_AGENT);
|
|
80
|
-
}
|
|
81
|
-
if (_isDir(_roots.SRC_SKILLS) || _isDir(_roots.SRC_RULES)) {
|
|
82
|
-
roots.push(_roots.SRC);
|
|
83
|
-
}
|
|
84
|
-
return roots;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// src/scripts/config/profiles.ts
|
|
88
14
|
var _require = createRequire(import.meta.url);
|
|
89
15
|
var PROFILE_ID_ENV = "AGENT_CONFIG_PROFILE_ID";
|
|
90
16
|
var DEFAULT_PROFILE_ID = "developer";
|
|
@@ -135,7 +61,7 @@ function _load_yaml(p) {
|
|
|
135
61
|
}
|
|
136
62
|
let text;
|
|
137
63
|
try {
|
|
138
|
-
text =
|
|
64
|
+
text = fs.readFileSync(p, "utf-8");
|
|
139
65
|
} catch (exc) {
|
|
140
66
|
logger.warning("profile read failed for %s: %s", p, String(exc));
|
|
141
67
|
return {};
|
|
@@ -153,8 +79,8 @@ function _load_yaml(p) {
|
|
|
153
79
|
return _isPlainDict(data) ? data : {};
|
|
154
80
|
}
|
|
155
81
|
function profile_file(project_root, profile_id) {
|
|
156
|
-
const legacy =
|
|
157
|
-
if (
|
|
82
|
+
const legacy = path.join(project_root, PROFILES_DIRNAME, `${profile_id}.yml`);
|
|
83
|
+
if (_exists(legacy)) {
|
|
158
84
|
return legacy;
|
|
159
85
|
}
|
|
160
86
|
let roots;
|
|
@@ -164,8 +90,8 @@ function profile_file(project_root, profile_id) {
|
|
|
164
90
|
return legacy;
|
|
165
91
|
}
|
|
166
92
|
for (const root of roots) {
|
|
167
|
-
const candidate =
|
|
168
|
-
if (
|
|
93
|
+
const candidate = path.join(root, "profiles", `${profile_id}.yml`);
|
|
94
|
+
if (_exists(candidate)) {
|
|
169
95
|
return candidate;
|
|
170
96
|
}
|
|
171
97
|
}
|
|
@@ -217,14 +143,14 @@ function _pick_id(pack_profile_id, user_settings, runtime_id) {
|
|
|
217
143
|
}
|
|
218
144
|
function resolve_profile(params) {
|
|
219
145
|
const settings = params.user_settings ?? {};
|
|
220
|
-
const settings_file =
|
|
146
|
+
const settings_file = path.join(params.project_root, DEFAULT_PROJECT_FILE);
|
|
221
147
|
const [profile_id, source] = _pick_id(
|
|
222
148
|
params.pack_profile_id ?? null,
|
|
223
149
|
settings,
|
|
224
150
|
params.runtime_id ?? null
|
|
225
151
|
);
|
|
226
152
|
if (profile_id === null) {
|
|
227
|
-
if (
|
|
153
|
+
if (_exists(settings_file)) {
|
|
228
154
|
return new ResolvedProfile({
|
|
229
155
|
id: DEFAULT_PROFILE_ID,
|
|
230
156
|
source: SOURCE_MISSING,
|
|
@@ -238,16 +164,16 @@ function resolve_profile(params) {
|
|
|
238
164
|
);
|
|
239
165
|
}
|
|
240
166
|
const yaml_path = profile_file(params.project_root, profile_id);
|
|
241
|
-
if (!
|
|
167
|
+
if (!_exists(yaml_path)) {
|
|
242
168
|
throw new ProfileError(
|
|
243
169
|
`profile.id=${_repr(profile_id)} (${source}) but ${yaml_path} not found`
|
|
244
170
|
);
|
|
245
171
|
}
|
|
246
172
|
return _build_resolved(profile_id, _load_yaml(yaml_path), { source });
|
|
247
173
|
}
|
|
248
|
-
function
|
|
174
|
+
function _exists(p) {
|
|
249
175
|
try {
|
|
250
|
-
|
|
176
|
+
fs.statSync(p);
|
|
251
177
|
return true;
|
|
252
178
|
} catch {
|
|
253
179
|
return false;
|
|
@@ -267,7 +193,6 @@ function _repr(s) {
|
|
|
267
193
|
}
|
|
268
194
|
|
|
269
195
|
export {
|
|
270
|
-
artefact_roots,
|
|
271
196
|
PROFILE_ID_ENV,
|
|
272
197
|
SOURCE_MISSING,
|
|
273
198
|
ProfileError,
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
|
|
2
|
+
|
|
3
|
+
// src/scripts/_lib/agent_src.ts
|
|
4
|
+
import * as fs from "node:fs";
|
|
5
|
+
import * as path2 from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
|
|
8
|
+
// src/scripts/_lib/guidelines_lane.ts
|
|
9
|
+
import * as path from "node:path";
|
|
10
|
+
var GUIDELINES_SOURCE_REL = path.join("docs", "guidelines");
|
|
11
|
+
|
|
12
|
+
// src/scripts/_lib/agent_src.ts
|
|
13
|
+
var _HERE = path2.dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
var _DEFAULT_ROOT = path2.resolve(_HERE, "..", "..", "..");
|
|
15
|
+
function _deriveRoots(root) {
|
|
16
|
+
const packages = path2.join(root, "packages");
|
|
17
|
+
const src = path2.join(root, "src");
|
|
18
|
+
return {
|
|
19
|
+
ROOT: root,
|
|
20
|
+
LEGACY_SRC: path2.join(root, ".agent-src.uncondensed"),
|
|
21
|
+
PACKAGES: packages,
|
|
22
|
+
PACKAGE_CORE: path2.join(packages, "core"),
|
|
23
|
+
SRC: src,
|
|
24
|
+
SRC_SKILLS: path2.join(src, "skills"),
|
|
25
|
+
SRC_RULES: path2.join(src, "rules"),
|
|
26
|
+
SRC_AGENT: path2.join(src, "agent-src"),
|
|
27
|
+
SRC_DOMAINS: path2.join(src, "domains")
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
var _roots = _deriveRoots(_DEFAULT_ROOT);
|
|
31
|
+
function _isDir(p) {
|
|
32
|
+
try {
|
|
33
|
+
return fs.statSync(p).isDirectory();
|
|
34
|
+
} catch {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function _exists(p) {
|
|
39
|
+
try {
|
|
40
|
+
fs.statSync(p);
|
|
41
|
+
return true;
|
|
42
|
+
} catch {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function _iterdirSorted(p) {
|
|
47
|
+
let names;
|
|
48
|
+
try {
|
|
49
|
+
names = fs.readdirSync(p);
|
|
50
|
+
} catch {
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
names.sort();
|
|
54
|
+
return names.map((name) => path2.join(p, name));
|
|
55
|
+
}
|
|
56
|
+
function artefact_roots() {
|
|
57
|
+
const roots = [];
|
|
58
|
+
if (_exists(_roots.LEGACY_SRC)) {
|
|
59
|
+
roots.push(_roots.LEGACY_SRC);
|
|
60
|
+
}
|
|
61
|
+
if (_exists(_roots.PACKAGES)) {
|
|
62
|
+
for (const pkg of _iterdirSorted(_roots.PACKAGES)) {
|
|
63
|
+
const sub = path2.join(pkg, ".agent-src.uncondensed");
|
|
64
|
+
if (_isDir(sub)) {
|
|
65
|
+
roots.push(sub);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (_isDir(_roots.SRC_AGENT)) {
|
|
70
|
+
roots.push(_roots.SRC_AGENT);
|
|
71
|
+
}
|
|
72
|
+
if (_isDir(_roots.SRC_SKILLS) || _isDir(_roots.SRC_RULES)) {
|
|
73
|
+
roots.push(_roots.SRC);
|
|
74
|
+
}
|
|
75
|
+
return roots;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export {
|
|
79
|
+
artefact_roots
|
|
80
|
+
};
|
|
@@ -891,7 +891,9 @@ var DETECTOR_IDS = [
|
|
|
891
891
|
"promissory",
|
|
892
892
|
"language",
|
|
893
893
|
"verification",
|
|
894
|
-
"completion"
|
|
894
|
+
"completion",
|
|
895
|
+
"pending-decision",
|
|
896
|
+
"untested"
|
|
895
897
|
];
|
|
896
898
|
var REFUSAL_STATE_REL = path2.join("agents", "runtime", "state", "turn-end-gate");
|
|
897
899
|
function refusalStateDir(workspaceRoot) {
|
|
@@ -916,7 +918,9 @@ function readSessionCounts(workspaceRoot, sessionId) {
|
|
|
916
918
|
}
|
|
917
919
|
}
|
|
918
920
|
function emptyCounts() {
|
|
919
|
-
|
|
921
|
+
const out = {};
|
|
922
|
+
for (const id of DETECTOR_IDS) out[id] = 0;
|
|
923
|
+
return out;
|
|
920
924
|
}
|
|
921
925
|
function isDetector(v) {
|
|
922
926
|
return typeof v === "string" && DETECTOR_IDS.includes(v);
|
|
@@ -942,6 +946,9 @@ function parseRecord(raw) {
|
|
|
942
946
|
if (typeof o["agent_config_version"] === "string") {
|
|
943
947
|
rec.agent_config_version = o["agent_config_version"];
|
|
944
948
|
}
|
|
949
|
+
if (typeof o["refused_prompt_id"] === "string") {
|
|
950
|
+
rec.refused_prompt_id = o["refused_prompt_id"];
|
|
951
|
+
}
|
|
945
952
|
const counts = o["counts"];
|
|
946
953
|
if (typeof counts === "object" && counts !== null && !Array.isArray(counts)) {
|
|
947
954
|
const parsed = {};
|
|
@@ -985,6 +992,9 @@ function foldRefusal(prev, input) {
|
|
|
985
992
|
else if (prev?.agent_config_version !== void 0) {
|
|
986
993
|
rec.agent_config_version = prev.agent_config_version;
|
|
987
994
|
}
|
|
995
|
+
if (input.promptId !== void 0 && input.promptId !== "") {
|
|
996
|
+
rec.refused_prompt_id = input.promptId;
|
|
997
|
+
}
|
|
988
998
|
return rec;
|
|
989
999
|
}
|
|
990
1000
|
function readInstallBoundary() {
|