instar 1.3.228 → 1.3.230
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/cli.js +11 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/devProfileNode.d.ts +62 -0
- package/dist/commands/devProfileNode.d.ts.map +1 -0
- package/dist/commands/devProfileNode.js +179 -0
- package/dist/commands/devProfileNode.js.map +1 -0
- package/dist/commands/server.js +3 -2
- package/dist/commands/server.js.map +1 -1
- package/dist/core/CoherenceReviewer.d.ts.map +1 -1
- package/dist/core/CoherenceReviewer.js +1 -0
- package/dist/core/CoherenceReviewer.js.map +1 -1
- package/dist/core/ContextualEvaluator.d.ts.map +1 -1
- package/dist/core/ContextualEvaluator.js +3 -0
- package/dist/core/ContextualEvaluator.js.map +1 -1
- package/dist/core/DiscoveryEvaluator.d.ts.map +1 -1
- package/dist/core/DiscoveryEvaluator.js +1 -0
- package/dist/core/DiscoveryEvaluator.js.map +1 -1
- package/dist/core/ExternalOperationGate.d.ts.map +1 -1
- package/dist/core/ExternalOperationGate.js +1 -0
- package/dist/core/ExternalOperationGate.js.map +1 -1
- package/dist/core/JobReflector.d.ts.map +1 -1
- package/dist/core/JobReflector.js +1 -0
- package/dist/core/JobReflector.js.map +1 -1
- package/dist/core/LLMConflictResolver.d.ts.map +1 -1
- package/dist/core/LLMConflictResolver.js +1 -0
- package/dist/core/LLMConflictResolver.js.map +1 -1
- package/dist/core/MessageSentinel.d.ts.map +1 -1
- package/dist/core/MessageSentinel.js +1 -0
- package/dist/core/MessageSentinel.js.map +1 -1
- package/dist/core/MessagingToneGate.d.ts.map +1 -1
- package/dist/core/MessagingToneGate.js +1 -0
- package/dist/core/MessagingToneGate.js.map +1 -1
- package/dist/core/PreCompactionFlush.js +1 -1
- package/dist/core/PreCompactionFlush.js.map +1 -1
- package/dist/core/ProjectDriftChecker.d.ts.map +1 -1
- package/dist/core/ProjectDriftChecker.js +1 -0
- package/dist/core/ProjectDriftChecker.js.map +1 -1
- package/dist/core/RelationshipManager.js +2 -2
- package/dist/core/RelationshipManager.js.map +1 -1
- package/dist/core/ResumeValidator.js +1 -1
- package/dist/core/ResumeValidator.js.map +1 -1
- package/dist/core/TemporalCoherenceChecker.d.ts.map +1 -1
- package/dist/core/TemporalCoherenceChecker.js +1 -0
- package/dist/core/TemporalCoherenceChecker.js.map +1 -1
- package/dist/core/UnjustifiedStopGate.d.ts.map +1 -1
- package/dist/core/UnjustifiedStopGate.js +1 -0
- package/dist/core/UnjustifiedStopGate.js.map +1 -1
- package/dist/core/crossModelReviewer.d.ts.map +1 -1
- package/dist/core/crossModelReviewer.js +1 -0
- package/dist/core/crossModelReviewer.js.map +1 -1
- package/dist/knowledge/TreeSynthesis.d.ts.map +1 -1
- package/dist/knowledge/TreeSynthesis.js +1 -0
- package/dist/knowledge/TreeSynthesis.js.map +1 -1
- package/dist/knowledge/TreeTriage.d.ts.map +1 -1
- package/dist/knowledge/TreeTriage.js +2 -0
- package/dist/knowledge/TreeTriage.js.map +1 -1
- package/dist/memory/TopicSummarizer.d.ts.map +1 -1
- package/dist/memory/TopicSummarizer.js +1 -0
- package/dist/memory/TopicSummarizer.js.map +1 -1
- package/dist/messaging/SessionSummarySentinel.js +1 -1
- package/dist/messaging/SessionSummarySentinel.js.map +1 -1
- package/dist/messaging/TelegramAdapter.d.ts.map +1 -1
- package/dist/messaging/TelegramAdapter.js +1 -0
- package/dist/messaging/TelegramAdapter.js.map +1 -1
- package/dist/monitoring/CommitmentSentinel.d.ts.map +1 -1
- package/dist/monitoring/CommitmentSentinel.js +1 -0
- package/dist/monitoring/CommitmentSentinel.js.map +1 -1
- package/dist/monitoring/InputClassifier.d.ts.map +1 -1
- package/dist/monitoring/InputClassifier.js +1 -0
- package/dist/monitoring/InputClassifier.js.map +1 -1
- package/dist/monitoring/PromptGate.d.ts.map +1 -1
- package/dist/monitoring/PromptGate.js +1 -0
- package/dist/monitoring/PromptGate.js.map +1 -1
- package/dist/monitoring/SessionActivitySentinel.d.ts.map +1 -1
- package/dist/monitoring/SessionActivitySentinel.js +3 -0
- package/dist/monitoring/SessionActivitySentinel.js.map +1 -1
- package/dist/monitoring/SessionWatchdog.d.ts.map +1 -1
- package/dist/monitoring/SessionWatchdog.js +1 -0
- package/dist/monitoring/SessionWatchdog.js.map +1 -1
- package/dist/monitoring/StallTriageNurse.d.ts.map +1 -1
- package/dist/monitoring/StallTriageNurse.js +1 -0
- package/dist/monitoring/StallTriageNurse.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +2 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/package.json +1 -1
- package/scripts/docs-coverage.mjs +14 -4
- package/scripts/generate-builtin-manifest.cjs +1 -0
- package/src/data/builtin-manifest.json +42 -34
- package/src/scaffold/templates.ts +2 -0
- package/upgrades/1.3.229.md +47 -0
- package/upgrades/1.3.230.md +66 -0
- package/upgrades/dev-profile-node-tool.eli16.md +42 -0
- package/upgrades/side-effects/attribute-remaining-llm-callers.md +82 -0
- package/upgrades/side-effects/dev-profile-node-tool.md +85 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# A stethoscope for a node process that's running hot
|
|
2
|
+
|
|
3
|
+
## The one-sentence version
|
|
4
|
+
When one of our programs is burning the CPU for no obvious reason, the usual tools can tell you *that* it's busy but not *what line of code* is doing it. This new command — `instar dev:profile-node` — presses a stethoscope to the running program and prints the exact function that's hogging the CPU.
|
|
5
|
+
|
|
6
|
+
## The problem it solves
|
|
7
|
+
Picture a car idling in the driveway but somehow guzzling gas. You pop the hood with your usual gauge — it says "engine's working hard" but won't tell you *which part*. That's macOS's built-in profiler on a Node.js program: it sees the engine block (the low-level machinery) but can't read the actual code, so the real culprit stays hidden.
|
|
8
|
+
|
|
9
|
+
This bit us for real: three of our agent servers were each burning ~50–60% CPU, bouncing them never helped, and four different tools all came back "busy, but I can't tell you why."
|
|
10
|
+
|
|
11
|
+
## The trick that worked (now a one-liner)
|
|
12
|
+
Node programs have a hidden superpower: send them a specific nudge (the SIGUSR1 signal) and they open a little diagnostic port on themselves. Connect to that port, record a few seconds of "what function is running right now," and it tells you — in plain code terms — exactly where the time goes.
|
|
13
|
+
|
|
14
|
+
That's how we finally caught it: **30% of the CPU was in `readFileUtf8`, inside `listSessions`** — a function re-reading every session file off the disk, over and over. Invisible to everything else; obvious once we looked through the right lens.
|
|
15
|
+
|
|
16
|
+
`instar dev:profile-node` bakes that whole trick into one command:
|
|
17
|
+
- Point it at a process (or let it auto-find the hottest one).
|
|
18
|
+
- It nudges the process, records ~5 seconds, and prints the hottest functions with their percentages.
|
|
19
|
+
- The biggest non-idle line is your culprit.
|
|
20
|
+
|
|
21
|
+
## What it looks like
|
|
22
|
+
```
|
|
23
|
+
Hottest JS frames (self-time) for pid 12673:
|
|
24
|
+
87.6% listOnTimeout node:internal/timers:546
|
|
25
|
+
9.9% (program)
|
|
26
|
+
2.5% (garbage collector)
|
|
27
|
+
```
|
|
28
|
+
(That's from a test process running a busy loop inside a timer — and it correctly fingered the timer callback.)
|
|
29
|
+
|
|
30
|
+
## The safety notes
|
|
31
|
+
1. The only thing it changes is opening that diagnostic port — and only on **localhost** (your own machine), only until the process next restarts. The command tells you it did this.
|
|
32
|
+
2. It **samples** the process — it never kills it, restarts it, or edits anything.
|
|
33
|
+
3. It's a developer tool, run on demand — nothing in the running system uses it.
|
|
34
|
+
|
|
35
|
+
## Why it matters
|
|
36
|
+
The hard part of fixing a mystery slowdown isn't the fix — it's *finding* the cause. This turns a clever, hard-won debugging trick into a reusable one-liner, so the next time any node process runs hot, the answer is one command away instead of an afternoon of dead ends. (Same spirit as our `dev:ci-failures` tool: when a workaround saves the day, make it permanent.)
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
**Rendered (verified HTTP 200):** https://echo.dawn-tunnel.dev/view/e5433071-bf6f-4cf0-b97a-5e16d9f7b160?sig=2c015aaeedc96ebb20d57b326f44d88eaa93dd2bcba0b4e8347a33d23f4d2b4b
|
|
41
|
+
|
|
42
|
+
*See also: the full success-story + meta-insights writeup for this run.*
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Side-Effects Review — Attribute the remaining internal LLM callers
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `attribute-remaining-llm-callers`
|
|
4
|
+
**Date:** `2026-06-03`
|
|
5
|
+
**Author:** `Echo (instar-dev agent)`
|
|
6
|
+
**Second-pass reviewer:** `not required`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Completes the `llm-feature-metrics-spec` goal that "every caller gets tagged."
|
|
11
|
+
PR #719 labeled the two highest-volume callers (InputGuard, PresenceProxy); this
|
|
12
|
+
adds `attribution: { component: '<ClassName>' }` to the remaining ~33 internal
|
|
13
|
+
`IntelligenceProvider.evaluate()` call sites across 28 files, so
|
|
14
|
+
`/metrics/features` attributes nearly 100% of real calls instead of bucketing
|
|
15
|
+
them under `unlabeled`. Each edit adds only the attribution label to the call's
|
|
16
|
+
existing options object (or widens one narrow local provider type — SlackAdapter
|
|
17
|
+
— to carry the optional field). No prompts, models, or logic changed.
|
|
18
|
+
|
|
19
|
+
Files: CoherenceReviewer, ContextualEvaluator (×3), DiscoveryEvaluator,
|
|
20
|
+
ExternalOperationGate, LLMConflictResolver, MessageSentinel, MessagingToneGate,
|
|
21
|
+
JobReflector, PreCompactionFlush, ProjectDriftChecker, RelationshipManager (×2),
|
|
22
|
+
ResumeValidator, TemporalCoherenceChecker, UnjustifiedStopGate, crossModelReviewer,
|
|
23
|
+
TreeSynthesis, TreeTriage (×2), TopicSummarizer, SessionSummarySentinel,
|
|
24
|
+
TelegramAdapter, SlackAdapter, CommitmentSentinel, InputClassifier, PromptGate,
|
|
25
|
+
SessionActivitySentinel (×3), SessionWatchdog, StallTriageNurse, and two
|
|
26
|
+
server.ts wiring sites (correction-learning distill, a2a-checkin summarize).
|
|
27
|
+
|
|
28
|
+
## Decision-point inventory
|
|
29
|
+
|
|
30
|
+
- N internal `evaluate()` call sites — **modify (additive label only)** — pass
|
|
31
|
+
`attribution.component`. No decision logic touched.
|
|
32
|
+
- `SlackAdapter.intelligence` local type — **modify** — widened opts to include
|
|
33
|
+
`attribution?: { component: string }` so the label typechecks.
|
|
34
|
+
|
|
35
|
+
No block/allow surface — this is observability metadata, never gates.
|
|
36
|
+
|
|
37
|
+
## 1. Over-block
|
|
38
|
+
No block/allow surface — not applicable.
|
|
39
|
+
|
|
40
|
+
## 2. Under-block
|
|
41
|
+
No block/allow surface — not applicable. (A few genuinely non-funnel `.evaluate`
|
|
42
|
+
sites were deliberately NOT touched: provider-internal `inner.evaluate`, the
|
|
43
|
+
provider adapter, and passthrough wrappers like TopicIntentCapture whose real
|
|
44
|
+
call — TopicIntentExtractor — is already labeled. Mislabeling those would
|
|
45
|
+
*reduce* attribution accuracy.)
|
|
46
|
+
|
|
47
|
+
## 3. Level-of-abstraction fit
|
|
48
|
+
Correct layer — the label is set by the caller (who knows its own identity) and
|
|
49
|
+
read at the single funnel chokepoint, exactly as the spec designs. No new logic.
|
|
50
|
+
|
|
51
|
+
## 4. Signal vs authority compliance
|
|
52
|
+
Required reference: docs/signal-vs-authority.md
|
|
53
|
+
- [x] No — this change has no block/allow surface. Pure observability signal.
|
|
54
|
+
|
|
55
|
+
## 5. Interactions
|
|
56
|
+
- **Shadowing / double-fire / races:** none. Each edit only adds a property to an
|
|
57
|
+
options object passed to an existing call; call count and control flow unchanged.
|
|
58
|
+
- **Feedback loops:** none — metrics are observe-only.
|
|
59
|
+
|
|
60
|
+
## 6. External surfaces
|
|
61
|
+
- `/metrics/features` now shows these ~30 systems by name instead of `unlabeled`
|
|
62
|
+
(additive; no field shape change). No external systems, no persistent-state
|
|
63
|
+
schema change (`feature_metrics.feature` is free-text TEXT).
|
|
64
|
+
|
|
65
|
+
## 7. Rollback cost
|
|
66
|
+
Pure additive code change — revert and ship a patch. No data migration, no
|
|
67
|
+
agent-state repair, no user-visible regression.
|
|
68
|
+
|
|
69
|
+
## Conclusion
|
|
70
|
+
Uniform, low-risk, additive labeling that completes the spec's attribution goal.
|
|
71
|
+
Build clean; 337 tests across the edited modules' suites green (additive options
|
|
72
|
+
didn't break any exact-match assertions). A structural lint guard against future
|
|
73
|
+
unlabeled callers is a sensible fast-follow (it needs an allowlist for the
|
|
74
|
+
legitimate non-funnel/passthrough exceptions, so it's scoped separately). Clear
|
|
75
|
+
to ship.
|
|
76
|
+
|
|
77
|
+
## Evidence pointers
|
|
78
|
+
- `tsc --noEmit` clean; `vitest run` green on MessagingToneGate, MessageSentinel,
|
|
79
|
+
PromptGate, CoherenceReviewer, RelationshipManager, StallTriageNurse,
|
|
80
|
+
JobReflector, CommitmentSentinel, TreeTriage, SessionActivitySentinel,
|
|
81
|
+
SessionWatchdog, InputClassifier, ExternalOperationGate, ContextualEvaluator
|
|
82
|
+
(2026-06-03).
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Side-Effects Review — `instar dev:profile-node`
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `dev-profile-node-tool`
|
|
4
|
+
**Date:** `2026-06-03`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `not required (dev-only CLI; read-only sampling; no server/runtime surface)`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
A new dev CLI command that CPU-profiles a running node process via SIGUSR1 + the
|
|
11
|
+
node inspector + a CDP CPU profile, and prints the hottest JS frames. New file
|
|
12
|
+
`src/commands/devProfileNode.ts` + a cli.ts registration + a manifest entry +
|
|
13
|
+
awareness lines. No server, route, config, or runtime-behavior change.
|
|
14
|
+
|
|
15
|
+
## Decision-point inventory
|
|
16
|
+
|
|
17
|
+
1. **pid resolution** — explicit `[pid]` digits win; otherwise auto-pick the
|
|
18
|
+
hottest `node` process (`ps -Aceo pcpu,pid,comm`). No node found → exit 1.
|
|
19
|
+
2. **Inspector discovery** — probe ports 9229–9235 (node's default + increments
|
|
20
|
+
when the default is taken); first target with a `webSocketDebuggerUrl` wins;
|
|
21
|
+
none → exit 1 with a clear message.
|
|
22
|
+
3. **Profile aggregation** — `aggregateHotFrames` sums per-node `hitCount` by call
|
|
23
|
+
frame, normalizes the path to `dist/…`/`src/…`, +1 to the 0-based line, and
|
|
24
|
+
returns top-N by self-time. Idle/native frames are kept on purpose (seeing
|
|
25
|
+
"48% idle, 30% readFileUtf8" is the signal).
|
|
26
|
+
4. **Exit codes** — 0 on a successful print (even "no samples"); 1 only on an
|
|
27
|
+
operational failure (no node, signal failed, no inspector, capture threw).
|
|
28
|
+
|
|
29
|
+
## 1. The one real side effect — SIGUSR1 opens the inspector
|
|
30
|
+
|
|
31
|
+
SIGUSR1 tells node to start its inspector on `127.0.0.1` (localhost-only) for the
|
|
32
|
+
life of the process. Implications, all bounded:
|
|
33
|
+
- **Localhost-only** — the inspector binds 127.0.0.1, not a public interface; it is
|
|
34
|
+
not remotely reachable.
|
|
35
|
+
- **Transient** — it closes when the process restarts; it does not persist.
|
|
36
|
+
- **Disclosed** — the command prints that it left the inspector open on the pid.
|
|
37
|
+
- **No state mutation** — profiling samples the process; it does not change its
|
|
38
|
+
behavior, memory, or files.
|
|
39
|
+
|
|
40
|
+
This is the same standard procedure node documents for live debugging; it is the
|
|
41
|
+
*only* way to symbolicate JS frames on a running process. The benefit (pinning a
|
|
42
|
+
hot loop that no other tool can see) outweighs a transient localhost debug port on
|
|
43
|
+
a dev box. Operators who object can simply not run the command.
|
|
44
|
+
|
|
45
|
+
## 2. Over/under-block
|
|
46
|
+
|
|
47
|
+
Not applicable — it gates nothing and changes no behavior. A wrong pid or a
|
|
48
|
+
non-node target fails cleanly with exit 1; it never acts on the target beyond
|
|
49
|
+
SIGUSR1 + reading the profile.
|
|
50
|
+
|
|
51
|
+
## 3. Blast radius
|
|
52
|
+
|
|
53
|
+
Zero runtime surface. The command runs only when a contributor/agent invokes it.
|
|
54
|
+
No server code path imports it; it is a leaf CLI command behind a dynamic import
|
|
55
|
+
(like `dev:ci-failures`). The `ws` dependency is already present (`^8.19.0`).
|
|
56
|
+
|
|
57
|
+
## 4. Migration parity
|
|
58
|
+
|
|
59
|
+
CLAUDE.md template (`generateClaudeMd`) + `site/.../cli.md` + the builtin-manifest
|
|
60
|
+
(`cli:dev-profile-node`) are updated in lockstep so the awareness + discoverability
|
|
61
|
+
checks stay green. No config/hook/skill migration — it is a pure CLI addition
|
|
62
|
+
(same shape as `dev:ci-failures`, which needed none).
|
|
63
|
+
|
|
64
|
+
## 5. Testability
|
|
65
|
+
|
|
66
|
+
`aggregateHotFrames` and `findInspectorTarget` are pure/dep-injected; the
|
|
67
|
+
SIGUSR1 / inspector-http / ws-CDP boundary is behind `ProfileNodeDeps` so the
|
|
68
|
+
orchestration is unit-tested without a real process. A live end-to-end smoke
|
|
69
|
+
(profiling a spawned busy node) confirmed the real path.
|
|
70
|
+
|
|
71
|
+
## 6. What it does NOT do
|
|
72
|
+
|
|
73
|
+
- Does not kill, restart, or modify the target (only SIGUSR1 + sample).
|
|
74
|
+
- Does not run as part of the server or any job — invoked on demand only.
|
|
75
|
+
- Does not expose a remote/public debug port (inspector is localhost).
|
|
76
|
+
|
|
77
|
+
## 7. Collateral fix — docs-coverage matcher
|
|
78
|
+
|
|
79
|
+
Adding the command surfaced a false-negative in `scripts/docs-coverage.mjs`: it
|
|
80
|
+
matched a command by its camelCase file name, so colon-commands (`dev:*`) never
|
|
81
|
+
matched their documented form and read as undocumented (the floor was sitting
|
|
82
|
+
right at the limit, so the new command tipped it). The matcher now also tries a
|
|
83
|
+
kebab form and normalizes `:`↔`-`. Audit-only script (the weekly docs-coverage
|
|
84
|
+
report); no runtime/behavior effect. It re-classifies the three `dev:*` commands
|
|
85
|
+
as documented, which is correct (they ARE in cli.md + the CLAUDE.md template).
|