johns-harness 2026.9.25 → 2026.9.27
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/CHANGELOG.md +10 -0
- package/README.md +6 -6
- package/dist/compact-B247y5Qt.js +31 -20
- package/dist/pi-embedded-C6ITuRXf.js +31 -20
- package/dist/pi-embedded-DoQsYfIY.js +31 -20
- package/dist/reply-C5LKjXcC.js +31 -20
- package/docs/PATCHES.md +35 -8
- package/package.json +1 -1
- package/scripts/check-packed-artifact.mjs +0 -3
- package/skills/cold-outreach/SKILL.md +0 -99
- package/skills/content-story/SKILL.md +0 -77
- package/skills/dashboard/SKILL.md +0 -129
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2026.9.27
|
|
4
|
+
|
|
5
|
+
- Family 74: the local active-session pressure guard compacts on exactly one trigger, estimated active-context tokens against the active model's declared context window (`ceil(0.7 x window)`, floored at `max(compaction.reserveTokensFloor, 50000)`; undeclared windows fall back to the runtime default, `DEFAULT_CONTEXT_TOKENS`). The fixed 1 MB transcript-bytes, 220-message and 3 GiB heap backstops are removed as triggers, so a session with 221 small messages and 528 KB no longer compacts early while a large context still compacts on real token pressure. The 5-minute cooldown, the 24-message floor and the failed-attempt growth gate remain as anti-thrash throttles, and the emergency compaction path is untouched. `contextRatio`, `minIntervalMs` and `minMessagesAfterCompaction` are the config surface; legacy `transcriptBytes`/`messageCount`/`heapUsedBytes` keys are accepted and ignored.
|
|
6
|
+
- Roll back with `npm i -g johns-harness@2026.9.26`.
|
|
7
|
+
|
|
8
|
+
## 2026.9.26
|
|
9
|
+
|
|
10
|
+
- Family 73: the `content-story`, `dashboard` and `cold-outreach` skills are removed from the bundled set on request, leaving eight generic bundled skills (`code-ops`, `web-research`, `plan-archival`, `todos`, `arch-viz`, `gcp-logs`, `activity-logging`, `outlook`). They load by description match exactly as before, workspace copies override them, and `enabled: false` and `allowBundled` still apply. Nothing else changes from 2026.9.25.
|
|
11
|
+
- Roll back with `npm i -g johns-harness@2026.9.25`.
|
|
12
|
+
|
|
3
13
|
## 2026.9.25
|
|
4
14
|
|
|
5
15
|
- Family 72: eleven generic skills from the author's workspace ship as bundled skills (`code-ops`, `web-research`, `plan-archival`, `todos`, `dashboard`, `arch-viz`, `content-story`, `cold-outreach`, `gcp-logs`, `activity-logging`, `outlook`), converted to fully generic wording first: no owner names, paths, repos, accounts, or products. They load by description match like every other bundled skill (none is always-on), workspace copies override them, and `enabled: false` and `allowBundled` still apply. `RULES.md` lists all of them.
|
package/README.md
CHANGED
|
@@ -85,8 +85,8 @@ node johnness.mjs --help
|
|
|
85
85
|
### Verify
|
|
86
86
|
|
|
87
87
|
```bash
|
|
88
|
-
npm test #
|
|
89
|
-
bash scripts/verify-patches.sh #
|
|
88
|
+
npm test # 915 tests against the installed dependency tree
|
|
89
|
+
bash scripts/verify-patches.sh # 459 checks across every patch family
|
|
90
90
|
```
|
|
91
91
|
|
|
92
92
|
## Launch a swarm with one command
|
|
@@ -132,7 +132,7 @@ Coding agents today run as isolated processes. Two agents on the same repository
|
|
|
132
132
|
- **Memory built for production.** Tiered recall that traces from consolidated reflections down to the verbatim record, surviving compaction and shared across the swarm. Installed and enabled by default.
|
|
133
133
|
- **Production authority per commit.** Promotion is granted to an exact SHA, never to a branch name, so one worker's authorization never covers another worker's commits.
|
|
134
134
|
- **An append-only action log.** Agents record every consequential action to `ACTION_LOG.md` and read it before acting.
|
|
135
|
-
- **A fixed runtime surface.** The core does not grow on a schedule. New mechanisms enter only to solve a demonstrated production failure, one narrow, tested, reversible patch at a time:
|
|
135
|
+
- **A fixed runtime surface.** The core does not grow on a schedule. New mechanisms enter only to solve a demonstrated production failure, one narrow, tested, reversible patch at a time: 74 patch families, each with a regression test and a rollback path.
|
|
136
136
|
- **Reliability with a definition.** Bounded retries, explicit failure states, exact-once continuation, context-pressure recovery, durable delivery, and supervised gateway recovery.
|
|
137
137
|
- **Coding first, phone optional.** Direct the work at a high level from a chat channel while agents plan, implement, test, coordinate, and stage releases unattended.
|
|
138
138
|
- **Local voice.** Optional native Whisper transcription of inbound audio, entirely on your machine. Off by default. [Setup](docs/NATIVE-WHISPER-MUSE.md).
|
|
@@ -199,7 +199,7 @@ The log is a [`RULES.md`](RULES.md) workspace convention enforced through the ac
|
|
|
199
199
|
|
|
200
200
|
## Patch families
|
|
201
201
|
|
|
202
|
-
The runtime carries
|
|
202
|
+
The runtime carries 74 patch families plus the 65.1 safe-update amendment. Each is a production fix applied at the source with a regression test, a durable patch marker, and a rollback path. A verifier runs 459 checks against the package tree and installed dependencies, and 915 tests run against the installed dependency tree.
|
|
203
203
|
|
|
204
204
|
Every family follows the same six steps: reproduce the failure, trace the exact runtime path, make the smallest source-level change that restores the invariant, add a regression test and a patch marker, run the verifier, and retain rollback artifacts. The full index: [`docs/PATCHES.md`](docs/PATCHES.md).
|
|
205
205
|
|
|
@@ -213,12 +213,12 @@ Every family follows the same six steps: reproduce the failure, trace the exact
|
|
|
213
213
|
| `--dev` | Dev profile under `~/.johnness-dev` with its own gateway port and shifted derived ports |
|
|
214
214
|
| Rules | [`RULES.md`](RULES.md) ships 19 operating-policy sections injected on every call. Fill in the placeholders; keep long procedures in skills. |
|
|
215
215
|
| Orchestrator skill | Bundled and loaded implicitly on every install. Decide whether to pass the user's words through or expand them, then keep the briefing brief. Override with a workspace `skills/orchestrator/SKILL.md`. |
|
|
216
|
-
| Bundled generic skills |
|
|
216
|
+
| Bundled generic skills | Eight generic skills ship in `skills/` and load by description match: `code-ops`, `web-research`, `plan-archival`, `todos`, `arch-viz`, `gcp-logs`, `activity-logging`, `outlook`. Workspace copies override; `enabled: false` and `allowBundled` still apply. |
|
|
217
217
|
|
|
218
218
|
## Documentation
|
|
219
219
|
|
|
220
220
|
- [`docs/index.md`](docs/index.md): runtime docs, from gateway and channels to plugins, nodes, and CLI reference.
|
|
221
|
-
- [`docs/PATCHES.md`](docs/PATCHES.md): the
|
|
221
|
+
- [`docs/PATCHES.md`](docs/PATCHES.md): the 74 patch families, one record each.
|
|
222
222
|
- [`docs/NATIVE-WHISPER-MUSE.md`](docs/NATIVE-WHISPER-MUSE.md): local Whisper transcription setup.
|
|
223
223
|
- [`RULES.md`](RULES.md): the default operating rules, including Rule Zero on production authorization.
|
|
224
224
|
|
package/dist/compact-B247y5Qt.js
CHANGED
|
@@ -7894,9 +7894,7 @@ function resolveTranscriptPolicy(params) {
|
|
|
7894
7894
|
|
|
7895
7895
|
//#region johnness local active-session pressure guard
|
|
7896
7896
|
const LOCAL_PRESSURE_GUARD_DEFAULTS = {
|
|
7897
|
-
|
|
7898
|
-
messageCount: 220,
|
|
7899
|
-
heapUsedBytes: 3221225472,
|
|
7897
|
+
contextRatio: 0.7,
|
|
7900
7898
|
minIntervalMs: 300000,
|
|
7901
7899
|
minMessagesAfterCompaction: 24
|
|
7902
7900
|
};
|
|
@@ -7907,14 +7905,24 @@ function localPressureGuardNumber(value, fallback) {
|
|
|
7907
7905
|
function localPressureGuardSettings(cfg) {
|
|
7908
7906
|
const raw = cfg?.agents?.defaults?.activeSessionPressure ?? cfg?.session?.activePressure ?? {};
|
|
7909
7907
|
if (raw?.enabled === false) return null;
|
|
7908
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: legacy transcriptBytes/messageCount/heapUsedBytes keys are accepted without error and ignored. Config surface: enabled, contextRatio, minIntervalMs, minMessagesAfterCompaction. */
|
|
7909
|
+
const contextRatio = localPressureGuardNumber(raw.contextRatio, LOCAL_PRESSURE_GUARD_DEFAULTS.contextRatio);
|
|
7910
7910
|
return {
|
|
7911
|
-
|
|
7912
|
-
messageCount: localPressureGuardNumber(raw.messageCount ?? raw.maxMessages, LOCAL_PRESSURE_GUARD_DEFAULTS.messageCount),
|
|
7913
|
-
heapUsedBytes: localPressureGuardNumber(raw.heapUsedBytes ?? raw.maxHeapUsedBytes, LOCAL_PRESSURE_GUARD_DEFAULTS.heapUsedBytes),
|
|
7911
|
+
contextRatio: contextRatio > 0 ? contextRatio : LOCAL_PRESSURE_GUARD_DEFAULTS.contextRatio,
|
|
7914
7912
|
minIntervalMs: localPressureGuardNumber(raw.minIntervalMs, LOCAL_PRESSURE_GUARD_DEFAULTS.minIntervalMs),
|
|
7915
7913
|
minMessagesAfterCompaction: localPressureGuardNumber(raw.minMessagesAfterCompaction, LOCAL_PRESSURE_GUARD_DEFAULTS.minMessagesAfterCompaction)
|
|
7916
7914
|
};
|
|
7917
7915
|
}
|
|
7916
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: single pressure trigger — estimated active-context tokens vs the active model's declared context window; the window falls back to DEFAULT_CONTEXT_TOKENS when undeclared. See docs/PATCHES.md family 74. */
|
|
7917
|
+
function localPressureGuardContextWindowTokens(model) {
|
|
7918
|
+
const declared = typeof model?.contextWindow === "number" && Number.isFinite(model.contextWindow) ? Math.floor(model.contextWindow) : 0;
|
|
7919
|
+
return declared > 0 ? declared : DEFAULT_CONTEXT_TOKENS;
|
|
7920
|
+
}
|
|
7921
|
+
function localPressureGuardContextThreshold(settings, contextWindowTokens, cfg) {
|
|
7922
|
+
const reserveTokensFloor = localPressureGuardNumber(cfg?.agents?.defaults?.compaction?.reserveTokensFloor, 2e4);
|
|
7923
|
+
const floor = Math.max(reserveTokensFloor, 50000);
|
|
7924
|
+
return Math.max(Math.ceil(settings.contextRatio * contextWindowTokens), floor);
|
|
7925
|
+
}
|
|
7918
7926
|
/* JOHNNESS_PATCH_APPEND_ONLY_PRESSURE_BASELINE: derive a restart-safe byte baseline from the append-only JSONL so transcriptBytes pressure measures NEW growth since the last successful compaction rather than total (never-shrinking) file size. See docs/PATCHES.md family 22. Scans getEntries() newest->oldest for the newest SUCCESSFUL johnness.active-pressure-refresh marker (failed !== true) and returns its recorded post-compaction size (postCompactionBytes, else transcriptBytes). Returns 0 for legacy sessions with no such marker, so a first over-limit session still compacts once. */
|
|
7919
7927
|
function computeActivePressureBaselineBytes(sessionManager) {
|
|
7920
7928
|
try {
|
|
@@ -8072,12 +8080,12 @@ function compactionRotationNumber(value, fallback) {
|
|
|
8072
8080
|
return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
|
|
8073
8081
|
}
|
|
8074
8082
|
function compactionRotationSettings(cfg) {
|
|
8075
|
-
const pressure = localPressureGuardSettings(cfg) ?? { transcriptBytes: 1048576 };
|
|
8076
8083
|
const raw = cfg?.agents?.defaults?.activeSessionPressure ?? cfg?.session?.activePressure ?? {};
|
|
8077
8084
|
if (raw?.rotateAfterCompaction === false) return null;
|
|
8078
|
-
|
|
8085
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: the legacy transcriptBytes threshold no longer exists; the rotation size budget keeps its historical 1 MiB-derived default so default rotation behavior is unchanged. */
|
|
8086
|
+
const threshold = 1048576;
|
|
8079
8087
|
const configuredMax = compactionRotationNumber(raw.rotationMaxBytes, 0);
|
|
8080
|
-
const maxBytes = configuredMax > 0 ? configuredMax :
|
|
8088
|
+
const maxBytes = configuredMax > 0 ? configuredMax : Math.max(131072, Math.min(524288, Math.floor(threshold * .45)));
|
|
8081
8089
|
return {
|
|
8082
8090
|
maxBytes,
|
|
8083
8091
|
maxMessages: Math.max(4, Math.floor(compactionRotationNumber(raw.rotationMaxMessages, 80))),
|
|
@@ -8213,18 +8221,20 @@ async function maybeRefreshActiveSessionForPressure(params) {
|
|
|
8213
8221
|
const heapUsedBytes = typeof process?.memoryUsage === "function" ? process.memoryUsage().heapUsed : 0;
|
|
8214
8222
|
const __hasCompactedContext = Array.isArray(params.session.messages) && params.session.messages.some((message) => message?.role === "compactionSummary");
|
|
8215
8223
|
const __alreadyRotated = params.sessionManager.getEntries?.().some((entry) => entry?.type === "custom" && entry?.customType === "johnness.compaction-session-rotation");
|
|
8216
|
-
|
|
8224
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: the existing-compacted-lineage rotation follows the same single context-token trigger; the byte gate is gone (family 74). */
|
|
8225
|
+
const __cwcWindowTokens = localPressureGuardContextWindowTokens(params.session?.model);
|
|
8226
|
+
const __cwcThresholdTokens = localPressureGuardContextThreshold(settings, __cwcWindowTokens, params.config);
|
|
8227
|
+
const __cwcEstimatedTokens = estimateMessagesTokens(messages);
|
|
8228
|
+
if (__cwcEstimatedTokens >= __cwcThresholdTokens && __hasCompactedContext && !__alreadyRotated) {
|
|
8217
8229
|
const __existingRotation = await rotateCompactedSessionLineage({ config: params.config, session: params.session, sessionManager: params.sessionManager, sessionFile: params.sessionFile, sessionKey: params.sessionKey, sessionId: params.sessionId, reason: "existing-compacted-lineage" });
|
|
8218
8230
|
if (__existingRotation.rotated) return { refreshed: true, rotated: true, reasons: ["existing-compacted-lineage"], transcriptBytes: __existingRotation.transcriptBytes, messageCount: __existingRotation.messageCount, heapUsedBytes, sessionId: __existingRotation.sessionId, sessionFile: __existingRotation.sessionFile, oldSessionId: __existingRotation.oldSessionId, oldSessionFile: __existingRotation.oldSessionFile };
|
|
8219
8231
|
}
|
|
8220
8232
|
const reasons = [];
|
|
8221
|
-
/*
|
|
8233
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: single trigger — estimated active-context tokens vs the context-window threshold (family 74). Legacy byte/message/heap heuristics no longer gate; the family 22 append-only baseline below is computed and recorded for observability only. */
|
|
8222
8234
|
const __aopBaselineBytes = computeActivePressureBaselineBytes(params.sessionManager);
|
|
8223
8235
|
const __aopEffectiveBytes = effectiveTranscriptPressureBytes(transcriptBytes, __aopBaselineBytes);
|
|
8224
|
-
if (
|
|
8225
|
-
if (
|
|
8226
|
-
if (settings.heapUsedBytes > 0 && heapUsedBytes >= settings.heapUsedBytes) reasons.push("heapUsed=" + heapUsedBytes + "/" + settings.heapUsedBytes);
|
|
8227
|
-
if (reasons.length === 0) return { refreshed: false, reason: "below threshold", transcriptBytes, messageCount, heapUsedBytes };
|
|
8236
|
+
if (__cwcEstimatedTokens >= __cwcThresholdTokens) reasons.push("contextTokens=" + __cwcEstimatedTokens + "/" + __cwcThresholdTokens);
|
|
8237
|
+
if (reasons.length === 0) return { refreshed: false, reason: "below threshold", contextTokens: __cwcEstimatedTokens, contextThreshold: __cwcThresholdTokens, baselineBytes: __aopBaselineBytes, effectiveTranscriptBytes: __aopEffectiveBytes, transcriptBytes, messageCount, heapUsedBytes };
|
|
8228
8238
|
let last = 0;
|
|
8229
8239
|
let lastFailed = false;
|
|
8230
8240
|
let lastBytes = 0;
|
|
@@ -16150,13 +16160,14 @@ async function maybeCompactActiveRunForPressure(params) {
|
|
|
16150
16160
|
} catch {}
|
|
16151
16161
|
const heapUsedBytes = typeof process?.memoryUsage === "function" ? process.memoryUsage().heapUsed : 0;
|
|
16152
16162
|
const reasons = [];
|
|
16153
|
-
/*
|
|
16163
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: single trigger — estimated active-context tokens vs the context-window threshold (family 74). Legacy byte/message/heap heuristics no longer gate; the family 22 append-only baseline below is computed and recorded for observability only. */
|
|
16154
16164
|
const __aopBaselineBytes = computeActivePressureBaselineBytes(params.sessionManager);
|
|
16155
16165
|
const __aopEffectiveBytes = effectiveTranscriptPressureBytes(transcriptBytes, __aopBaselineBytes);
|
|
16156
|
-
|
|
16157
|
-
|
|
16158
|
-
|
|
16159
|
-
if (
|
|
16166
|
+
const __cwcWindowTokens = localPressureGuardContextWindowTokens(params.session?.model);
|
|
16167
|
+
const __cwcThresholdTokens = localPressureGuardContextThreshold(settings, __cwcWindowTokens, params.config);
|
|
16168
|
+
const __cwcEstimatedTokens = estimateMessagesTokens(messages);
|
|
16169
|
+
if (__cwcEstimatedTokens >= __cwcThresholdTokens) reasons.push("contextTokens=" + __cwcEstimatedTokens + "/" + __cwcThresholdTokens);
|
|
16170
|
+
if (reasons.length === 0) return { refreshed: false, reason: "below threshold", contextTokens: __cwcEstimatedTokens, contextThreshold: __cwcThresholdTokens, baselineBytes: __aopBaselineBytes, effectiveTranscriptBytes: __aopEffectiveBytes, transcriptBytes, messageCount, heapUsedBytes };
|
|
16160
16171
|
let last = 0;
|
|
16161
16172
|
let lastFailed = false;
|
|
16162
16173
|
let lastBytes = 0;
|
|
@@ -96130,9 +96130,7 @@ function buildEmbeddedExtensionFactories(params) {
|
|
|
96130
96130
|
|
|
96131
96131
|
//#region johnness local active-session pressure guard
|
|
96132
96132
|
const LOCAL_PRESSURE_GUARD_DEFAULTS = {
|
|
96133
|
-
|
|
96134
|
-
messageCount: 220,
|
|
96135
|
-
heapUsedBytes: 3221225472,
|
|
96133
|
+
contextRatio: 0.7,
|
|
96136
96134
|
minIntervalMs: 300000,
|
|
96137
96135
|
minMessagesAfterCompaction: 24
|
|
96138
96136
|
};
|
|
@@ -96143,14 +96141,24 @@ function localPressureGuardNumber(value, fallback) {
|
|
|
96143
96141
|
function localPressureGuardSettings(cfg) {
|
|
96144
96142
|
const raw = cfg?.agents?.defaults?.activeSessionPressure ?? cfg?.session?.activePressure ?? {};
|
|
96145
96143
|
if (raw?.enabled === false) return null;
|
|
96144
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: legacy transcriptBytes/messageCount/heapUsedBytes keys are accepted without error and ignored. Config surface: enabled, contextRatio, minIntervalMs, minMessagesAfterCompaction. */
|
|
96145
|
+
const contextRatio = localPressureGuardNumber(raw.contextRatio, LOCAL_PRESSURE_GUARD_DEFAULTS.contextRatio);
|
|
96146
96146
|
return {
|
|
96147
|
-
|
|
96148
|
-
messageCount: localPressureGuardNumber(raw.messageCount ?? raw.maxMessages, LOCAL_PRESSURE_GUARD_DEFAULTS.messageCount),
|
|
96149
|
-
heapUsedBytes: localPressureGuardNumber(raw.heapUsedBytes ?? raw.maxHeapUsedBytes, LOCAL_PRESSURE_GUARD_DEFAULTS.heapUsedBytes),
|
|
96147
|
+
contextRatio: contextRatio > 0 ? contextRatio : LOCAL_PRESSURE_GUARD_DEFAULTS.contextRatio,
|
|
96150
96148
|
minIntervalMs: localPressureGuardNumber(raw.minIntervalMs, LOCAL_PRESSURE_GUARD_DEFAULTS.minIntervalMs),
|
|
96151
96149
|
minMessagesAfterCompaction: localPressureGuardNumber(raw.minMessagesAfterCompaction, LOCAL_PRESSURE_GUARD_DEFAULTS.minMessagesAfterCompaction)
|
|
96152
96150
|
};
|
|
96153
96151
|
}
|
|
96152
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: single pressure trigger — estimated active-context tokens vs the active model's declared context window; the window falls back to DEFAULT_CONTEXT_TOKENS when undeclared. See docs/PATCHES.md family 74. */
|
|
96153
|
+
function localPressureGuardContextWindowTokens(model) {
|
|
96154
|
+
const declared = typeof model?.contextWindow === "number" && Number.isFinite(model.contextWindow) ? Math.floor(model.contextWindow) : 0;
|
|
96155
|
+
return declared > 0 ? declared : DEFAULT_CONTEXT_TOKENS;
|
|
96156
|
+
}
|
|
96157
|
+
function localPressureGuardContextThreshold(settings, contextWindowTokens, cfg) {
|
|
96158
|
+
const reserveTokensFloor = localPressureGuardNumber(cfg?.agents?.defaults?.compaction?.reserveTokensFloor, 2e4);
|
|
96159
|
+
const floor = Math.max(reserveTokensFloor, 50000);
|
|
96160
|
+
return Math.max(Math.ceil(settings.contextRatio * contextWindowTokens), floor);
|
|
96161
|
+
}
|
|
96154
96162
|
/* JOHNNESS_PATCH_APPEND_ONLY_PRESSURE_BASELINE: derive a restart-safe byte baseline from the append-only JSONL so transcriptBytes pressure measures NEW growth since the last successful compaction rather than total (never-shrinking) file size. See docs/PATCHES.md family 22. Scans getEntries() newest->oldest for the newest SUCCESSFUL johnness.active-pressure-refresh marker (failed !== true) and returns its recorded post-compaction size (postCompactionBytes, else transcriptBytes). Returns 0 for legacy sessions with no such marker, so a first over-limit session still compacts once. */
|
|
96155
96163
|
function computeActivePressureBaselineBytes(sessionManager) {
|
|
96156
96164
|
try {
|
|
@@ -96308,12 +96316,12 @@ function compactionRotationNumber(value, fallback) {
|
|
|
96308
96316
|
return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
|
|
96309
96317
|
}
|
|
96310
96318
|
function compactionRotationSettings(cfg) {
|
|
96311
|
-
const pressure = localPressureGuardSettings(cfg) ?? { transcriptBytes: 1048576 };
|
|
96312
96319
|
const raw = cfg?.agents?.defaults?.activeSessionPressure ?? cfg?.session?.activePressure ?? {};
|
|
96313
96320
|
if (raw?.rotateAfterCompaction === false) return null;
|
|
96314
|
-
|
|
96321
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: the legacy transcriptBytes threshold no longer exists; the rotation size budget keeps its historical 1 MiB-derived default so default rotation behavior is unchanged. */
|
|
96322
|
+
const threshold = 1048576;
|
|
96315
96323
|
const configuredMax = compactionRotationNumber(raw.rotationMaxBytes, 0);
|
|
96316
|
-
const maxBytes = configuredMax > 0 ? configuredMax :
|
|
96324
|
+
const maxBytes = configuredMax > 0 ? configuredMax : Math.max(131072, Math.min(524288, Math.floor(threshold * .45)));
|
|
96317
96325
|
return {
|
|
96318
96326
|
maxBytes,
|
|
96319
96327
|
maxMessages: Math.max(4, Math.floor(compactionRotationNumber(raw.rotationMaxMessages, 80))),
|
|
@@ -96449,18 +96457,20 @@ async function maybeRefreshActiveSessionForPressure(params) {
|
|
|
96449
96457
|
const heapUsedBytes = typeof process?.memoryUsage === "function" ? process.memoryUsage().heapUsed : 0;
|
|
96450
96458
|
const __hasCompactedContext = Array.isArray(params.session.messages) && params.session.messages.some((message) => message?.role === "compactionSummary");
|
|
96451
96459
|
const __alreadyRotated = params.sessionManager.getEntries?.().some((entry) => entry?.type === "custom" && entry?.customType === "johnness.compaction-session-rotation");
|
|
96452
|
-
|
|
96460
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: the existing-compacted-lineage rotation follows the same single context-token trigger; the byte gate is gone (family 74). */
|
|
96461
|
+
const __cwcWindowTokens = localPressureGuardContextWindowTokens(params.session?.model);
|
|
96462
|
+
const __cwcThresholdTokens = localPressureGuardContextThreshold(settings, __cwcWindowTokens, params.config);
|
|
96463
|
+
const __cwcEstimatedTokens = estimateMessagesTokens(messages);
|
|
96464
|
+
if (__cwcEstimatedTokens >= __cwcThresholdTokens && __hasCompactedContext && !__alreadyRotated) {
|
|
96453
96465
|
const __existingRotation = await rotateCompactedSessionLineage({ config: params.config, session: params.session, sessionManager: params.sessionManager, sessionFile: params.sessionFile, sessionKey: params.sessionKey, sessionId: params.sessionId, reason: "existing-compacted-lineage" });
|
|
96454
96466
|
if (__existingRotation.rotated) return { refreshed: true, rotated: true, reasons: ["existing-compacted-lineage"], transcriptBytes: __existingRotation.transcriptBytes, messageCount: __existingRotation.messageCount, heapUsedBytes, sessionId: __existingRotation.sessionId, sessionFile: __existingRotation.sessionFile, oldSessionId: __existingRotation.oldSessionId, oldSessionFile: __existingRotation.oldSessionFile };
|
|
96455
96467
|
}
|
|
96456
96468
|
const reasons = [];
|
|
96457
|
-
/*
|
|
96469
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: single trigger — estimated active-context tokens vs the context-window threshold (family 74). Legacy byte/message/heap heuristics no longer gate; the family 22 append-only baseline below is computed and recorded for observability only. */
|
|
96458
96470
|
const __aopBaselineBytes = computeActivePressureBaselineBytes(params.sessionManager);
|
|
96459
96471
|
const __aopEffectiveBytes = effectiveTranscriptPressureBytes(transcriptBytes, __aopBaselineBytes);
|
|
96460
|
-
if (
|
|
96461
|
-
if (
|
|
96462
|
-
if (settings.heapUsedBytes > 0 && heapUsedBytes >= settings.heapUsedBytes) reasons.push("heapUsed=" + heapUsedBytes + "/" + settings.heapUsedBytes);
|
|
96463
|
-
if (reasons.length === 0) return { refreshed: false, reason: "below threshold", transcriptBytes, messageCount, heapUsedBytes };
|
|
96472
|
+
if (__cwcEstimatedTokens >= __cwcThresholdTokens) reasons.push("contextTokens=" + __cwcEstimatedTokens + "/" + __cwcThresholdTokens);
|
|
96473
|
+
if (reasons.length === 0) return { refreshed: false, reason: "below threshold", contextTokens: __cwcEstimatedTokens, contextThreshold: __cwcThresholdTokens, baselineBytes: __aopBaselineBytes, effectiveTranscriptBytes: __aopEffectiveBytes, transcriptBytes, messageCount, heapUsedBytes };
|
|
96464
96474
|
let last = 0;
|
|
96465
96475
|
let lastFailed = false;
|
|
96466
96476
|
let lastBytes = 0;
|
|
@@ -101878,13 +101888,14 @@ async function maybeCompactActiveRunForPressure(params) {
|
|
|
101878
101888
|
} catch {}
|
|
101879
101889
|
const heapUsedBytes = typeof process?.memoryUsage === "function" ? process.memoryUsage().heapUsed : 0;
|
|
101880
101890
|
const reasons = [];
|
|
101881
|
-
/*
|
|
101891
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: single trigger — estimated active-context tokens vs the context-window threshold (family 74). Legacy byte/message/heap heuristics no longer gate; the family 22 append-only baseline below is computed and recorded for observability only. */
|
|
101882
101892
|
const __aopBaselineBytes = computeActivePressureBaselineBytes(params.sessionManager);
|
|
101883
101893
|
const __aopEffectiveBytes = effectiveTranscriptPressureBytes(transcriptBytes, __aopBaselineBytes);
|
|
101884
|
-
|
|
101885
|
-
|
|
101886
|
-
|
|
101887
|
-
if (
|
|
101894
|
+
const __cwcWindowTokens = localPressureGuardContextWindowTokens(params.session?.model);
|
|
101895
|
+
const __cwcThresholdTokens = localPressureGuardContextThreshold(settings, __cwcWindowTokens, params.config);
|
|
101896
|
+
const __cwcEstimatedTokens = estimateMessagesTokens(messages);
|
|
101897
|
+
if (__cwcEstimatedTokens >= __cwcThresholdTokens) reasons.push("contextTokens=" + __cwcEstimatedTokens + "/" + __cwcThresholdTokens);
|
|
101898
|
+
if (reasons.length === 0) return { refreshed: false, reason: "below threshold", contextTokens: __cwcEstimatedTokens, contextThreshold: __cwcThresholdTokens, baselineBytes: __aopBaselineBytes, effectiveTranscriptBytes: __aopEffectiveBytes, transcriptBytes, messageCount, heapUsedBytes };
|
|
101888
101899
|
let last = 0;
|
|
101889
101900
|
let lastFailed = false;
|
|
101890
101901
|
let lastBytes = 0;
|
|
@@ -96120,9 +96120,7 @@ function buildEmbeddedExtensionFactories(params) {
|
|
|
96120
96120
|
|
|
96121
96121
|
//#region johnness local active-session pressure guard
|
|
96122
96122
|
const LOCAL_PRESSURE_GUARD_DEFAULTS = {
|
|
96123
|
-
|
|
96124
|
-
messageCount: 220,
|
|
96125
|
-
heapUsedBytes: 3221225472,
|
|
96123
|
+
contextRatio: 0.7,
|
|
96126
96124
|
minIntervalMs: 300000,
|
|
96127
96125
|
minMessagesAfterCompaction: 24
|
|
96128
96126
|
};
|
|
@@ -96133,14 +96131,24 @@ function localPressureGuardNumber(value, fallback) {
|
|
|
96133
96131
|
function localPressureGuardSettings(cfg) {
|
|
96134
96132
|
const raw = cfg?.agents?.defaults?.activeSessionPressure ?? cfg?.session?.activePressure ?? {};
|
|
96135
96133
|
if (raw?.enabled === false) return null;
|
|
96134
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: legacy transcriptBytes/messageCount/heapUsedBytes keys are accepted without error and ignored. Config surface: enabled, contextRatio, minIntervalMs, minMessagesAfterCompaction. */
|
|
96135
|
+
const contextRatio = localPressureGuardNumber(raw.contextRatio, LOCAL_PRESSURE_GUARD_DEFAULTS.contextRatio);
|
|
96136
96136
|
return {
|
|
96137
|
-
|
|
96138
|
-
messageCount: localPressureGuardNumber(raw.messageCount ?? raw.maxMessages, LOCAL_PRESSURE_GUARD_DEFAULTS.messageCount),
|
|
96139
|
-
heapUsedBytes: localPressureGuardNumber(raw.heapUsedBytes ?? raw.maxHeapUsedBytes, LOCAL_PRESSURE_GUARD_DEFAULTS.heapUsedBytes),
|
|
96137
|
+
contextRatio: contextRatio > 0 ? contextRatio : LOCAL_PRESSURE_GUARD_DEFAULTS.contextRatio,
|
|
96140
96138
|
minIntervalMs: localPressureGuardNumber(raw.minIntervalMs, LOCAL_PRESSURE_GUARD_DEFAULTS.minIntervalMs),
|
|
96141
96139
|
minMessagesAfterCompaction: localPressureGuardNumber(raw.minMessagesAfterCompaction, LOCAL_PRESSURE_GUARD_DEFAULTS.minMessagesAfterCompaction)
|
|
96142
96140
|
};
|
|
96143
96141
|
}
|
|
96142
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: single pressure trigger — estimated active-context tokens vs the active model's declared context window; the window falls back to DEFAULT_CONTEXT_TOKENS when undeclared. See docs/PATCHES.md family 74. */
|
|
96143
|
+
function localPressureGuardContextWindowTokens(model) {
|
|
96144
|
+
const declared = typeof model?.contextWindow === "number" && Number.isFinite(model.contextWindow) ? Math.floor(model.contextWindow) : 0;
|
|
96145
|
+
return declared > 0 ? declared : DEFAULT_CONTEXT_TOKENS;
|
|
96146
|
+
}
|
|
96147
|
+
function localPressureGuardContextThreshold(settings, contextWindowTokens, cfg) {
|
|
96148
|
+
const reserveTokensFloor = localPressureGuardNumber(cfg?.agents?.defaults?.compaction?.reserveTokensFloor, 2e4);
|
|
96149
|
+
const floor = Math.max(reserveTokensFloor, 50000);
|
|
96150
|
+
return Math.max(Math.ceil(settings.contextRatio * contextWindowTokens), floor);
|
|
96151
|
+
}
|
|
96144
96152
|
/* JOHNNESS_PATCH_APPEND_ONLY_PRESSURE_BASELINE: derive a restart-safe byte baseline from the append-only JSONL so transcriptBytes pressure measures NEW growth since the last successful compaction rather than total (never-shrinking) file size. See docs/PATCHES.md family 22. Scans getEntries() newest->oldest for the newest SUCCESSFUL johnness.active-pressure-refresh marker (failed !== true) and returns its recorded post-compaction size (postCompactionBytes, else transcriptBytes). Returns 0 for legacy sessions with no such marker, so a first over-limit session still compacts once. */
|
|
96145
96153
|
function computeActivePressureBaselineBytes(sessionManager) {
|
|
96146
96154
|
try {
|
|
@@ -96298,12 +96306,12 @@ function compactionRotationNumber(value, fallback) {
|
|
|
96298
96306
|
return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
|
|
96299
96307
|
}
|
|
96300
96308
|
function compactionRotationSettings(cfg) {
|
|
96301
|
-
const pressure = localPressureGuardSettings(cfg) ?? { transcriptBytes: 1048576 };
|
|
96302
96309
|
const raw = cfg?.agents?.defaults?.activeSessionPressure ?? cfg?.session?.activePressure ?? {};
|
|
96303
96310
|
if (raw?.rotateAfterCompaction === false) return null;
|
|
96304
|
-
|
|
96311
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: the legacy transcriptBytes threshold no longer exists; the rotation size budget keeps its historical 1 MiB-derived default so default rotation behavior is unchanged. */
|
|
96312
|
+
const threshold = 1048576;
|
|
96305
96313
|
const configuredMax = compactionRotationNumber(raw.rotationMaxBytes, 0);
|
|
96306
|
-
const maxBytes = configuredMax > 0 ? configuredMax :
|
|
96314
|
+
const maxBytes = configuredMax > 0 ? configuredMax : Math.max(131072, Math.min(524288, Math.floor(threshold * .45)));
|
|
96307
96315
|
return {
|
|
96308
96316
|
maxBytes,
|
|
96309
96317
|
maxMessages: Math.max(4, Math.floor(compactionRotationNumber(raw.rotationMaxMessages, 80))),
|
|
@@ -96439,18 +96447,20 @@ async function maybeRefreshActiveSessionForPressure(params) {
|
|
|
96439
96447
|
const heapUsedBytes = typeof process?.memoryUsage === "function" ? process.memoryUsage().heapUsed : 0;
|
|
96440
96448
|
const __hasCompactedContext = Array.isArray(params.session.messages) && params.session.messages.some((message) => message?.role === "compactionSummary");
|
|
96441
96449
|
const __alreadyRotated = params.sessionManager.getEntries?.().some((entry) => entry?.type === "custom" && entry?.customType === "johnness.compaction-session-rotation");
|
|
96442
|
-
|
|
96450
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: the existing-compacted-lineage rotation follows the same single context-token trigger; the byte gate is gone (family 74). */
|
|
96451
|
+
const __cwcWindowTokens = localPressureGuardContextWindowTokens(params.session?.model);
|
|
96452
|
+
const __cwcThresholdTokens = localPressureGuardContextThreshold(settings, __cwcWindowTokens, params.config);
|
|
96453
|
+
const __cwcEstimatedTokens = estimateMessagesTokens(messages);
|
|
96454
|
+
if (__cwcEstimatedTokens >= __cwcThresholdTokens && __hasCompactedContext && !__alreadyRotated) {
|
|
96443
96455
|
const __existingRotation = await rotateCompactedSessionLineage({ config: params.config, session: params.session, sessionManager: params.sessionManager, sessionFile: params.sessionFile, sessionKey: params.sessionKey, sessionId: params.sessionId, reason: "existing-compacted-lineage" });
|
|
96444
96456
|
if (__existingRotation.rotated) return { refreshed: true, rotated: true, reasons: ["existing-compacted-lineage"], transcriptBytes: __existingRotation.transcriptBytes, messageCount: __existingRotation.messageCount, heapUsedBytes, sessionId: __existingRotation.sessionId, sessionFile: __existingRotation.sessionFile, oldSessionId: __existingRotation.oldSessionId, oldSessionFile: __existingRotation.oldSessionFile };
|
|
96445
96457
|
}
|
|
96446
96458
|
const reasons = [];
|
|
96447
|
-
/*
|
|
96459
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: single trigger — estimated active-context tokens vs the context-window threshold (family 74). Legacy byte/message/heap heuristics no longer gate; the family 22 append-only baseline below is computed and recorded for observability only. */
|
|
96448
96460
|
const __aopBaselineBytes = computeActivePressureBaselineBytes(params.sessionManager);
|
|
96449
96461
|
const __aopEffectiveBytes = effectiveTranscriptPressureBytes(transcriptBytes, __aopBaselineBytes);
|
|
96450
|
-
if (
|
|
96451
|
-
if (
|
|
96452
|
-
if (settings.heapUsedBytes > 0 && heapUsedBytes >= settings.heapUsedBytes) reasons.push("heapUsed=" + heapUsedBytes + "/" + settings.heapUsedBytes);
|
|
96453
|
-
if (reasons.length === 0) return { refreshed: false, reason: "below threshold", transcriptBytes, messageCount, heapUsedBytes };
|
|
96462
|
+
if (__cwcEstimatedTokens >= __cwcThresholdTokens) reasons.push("contextTokens=" + __cwcEstimatedTokens + "/" + __cwcThresholdTokens);
|
|
96463
|
+
if (reasons.length === 0) return { refreshed: false, reason: "below threshold", contextTokens: __cwcEstimatedTokens, contextThreshold: __cwcThresholdTokens, baselineBytes: __aopBaselineBytes, effectiveTranscriptBytes: __aopEffectiveBytes, transcriptBytes, messageCount, heapUsedBytes };
|
|
96454
96464
|
let last = 0;
|
|
96455
96465
|
let lastFailed = false;
|
|
96456
96466
|
let lastBytes = 0;
|
|
@@ -101868,13 +101878,14 @@ async function maybeCompactActiveRunForPressure(params) {
|
|
|
101868
101878
|
} catch {}
|
|
101869
101879
|
const heapUsedBytes = typeof process?.memoryUsage === "function" ? process.memoryUsage().heapUsed : 0;
|
|
101870
101880
|
const reasons = [];
|
|
101871
|
-
/*
|
|
101881
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: single trigger — estimated active-context tokens vs the context-window threshold (family 74). Legacy byte/message/heap heuristics no longer gate; the family 22 append-only baseline below is computed and recorded for observability only. */
|
|
101872
101882
|
const __aopBaselineBytes = computeActivePressureBaselineBytes(params.sessionManager);
|
|
101873
101883
|
const __aopEffectiveBytes = effectiveTranscriptPressureBytes(transcriptBytes, __aopBaselineBytes);
|
|
101874
|
-
|
|
101875
|
-
|
|
101876
|
-
|
|
101877
|
-
if (
|
|
101884
|
+
const __cwcWindowTokens = localPressureGuardContextWindowTokens(params.session?.model);
|
|
101885
|
+
const __cwcThresholdTokens = localPressureGuardContextThreshold(settings, __cwcWindowTokens, params.config);
|
|
101886
|
+
const __cwcEstimatedTokens = estimateMessagesTokens(messages);
|
|
101887
|
+
if (__cwcEstimatedTokens >= __cwcThresholdTokens) reasons.push("contextTokens=" + __cwcEstimatedTokens + "/" + __cwcThresholdTokens);
|
|
101888
|
+
if (reasons.length === 0) return { refreshed: false, reason: "below threshold", contextTokens: __cwcEstimatedTokens, contextThreshold: __cwcThresholdTokens, baselineBytes: __aopBaselineBytes, effectiveTranscriptBytes: __aopEffectiveBytes, transcriptBytes, messageCount, heapUsedBytes };
|
|
101878
101889
|
let last = 0;
|
|
101879
101890
|
let lastFailed = false;
|
|
101880
101891
|
let lastBytes = 0;
|
package/dist/reply-C5LKjXcC.js
CHANGED
|
@@ -74132,9 +74132,7 @@ function buildEmbeddedExtensionFactories(params) {
|
|
|
74132
74132
|
|
|
74133
74133
|
//#region johnness local active-session pressure guard
|
|
74134
74134
|
const LOCAL_PRESSURE_GUARD_DEFAULTS = {
|
|
74135
|
-
|
|
74136
|
-
messageCount: 220,
|
|
74137
|
-
heapUsedBytes: 3221225472,
|
|
74135
|
+
contextRatio: 0.7,
|
|
74138
74136
|
minIntervalMs: 300000,
|
|
74139
74137
|
minMessagesAfterCompaction: 24
|
|
74140
74138
|
};
|
|
@@ -74145,14 +74143,24 @@ function localPressureGuardNumber(value, fallback) {
|
|
|
74145
74143
|
function localPressureGuardSettings(cfg) {
|
|
74146
74144
|
const raw = cfg?.agents?.defaults?.activeSessionPressure ?? cfg?.session?.activePressure ?? {};
|
|
74147
74145
|
if (raw?.enabled === false) return null;
|
|
74146
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: legacy transcriptBytes/messageCount/heapUsedBytes keys are accepted without error and ignored. Config surface: enabled, contextRatio, minIntervalMs, minMessagesAfterCompaction. */
|
|
74147
|
+
const contextRatio = localPressureGuardNumber(raw.contextRatio, LOCAL_PRESSURE_GUARD_DEFAULTS.contextRatio);
|
|
74148
74148
|
return {
|
|
74149
|
-
|
|
74150
|
-
messageCount: localPressureGuardNumber(raw.messageCount ?? raw.maxMessages, LOCAL_PRESSURE_GUARD_DEFAULTS.messageCount),
|
|
74151
|
-
heapUsedBytes: localPressureGuardNumber(raw.heapUsedBytes ?? raw.maxHeapUsedBytes, LOCAL_PRESSURE_GUARD_DEFAULTS.heapUsedBytes),
|
|
74149
|
+
contextRatio: contextRatio > 0 ? contextRatio : LOCAL_PRESSURE_GUARD_DEFAULTS.contextRatio,
|
|
74152
74150
|
minIntervalMs: localPressureGuardNumber(raw.minIntervalMs, LOCAL_PRESSURE_GUARD_DEFAULTS.minIntervalMs),
|
|
74153
74151
|
minMessagesAfterCompaction: localPressureGuardNumber(raw.minMessagesAfterCompaction, LOCAL_PRESSURE_GUARD_DEFAULTS.minMessagesAfterCompaction)
|
|
74154
74152
|
};
|
|
74155
74153
|
}
|
|
74154
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: single pressure trigger — estimated active-context tokens vs the active model's declared context window; the window falls back to DEFAULT_CONTEXT_TOKENS when undeclared. See docs/PATCHES.md family 74. */
|
|
74155
|
+
function localPressureGuardContextWindowTokens(model) {
|
|
74156
|
+
const declared = typeof model?.contextWindow === "number" && Number.isFinite(model.contextWindow) ? Math.floor(model.contextWindow) : 0;
|
|
74157
|
+
return declared > 0 ? declared : DEFAULT_CONTEXT_TOKENS;
|
|
74158
|
+
}
|
|
74159
|
+
function localPressureGuardContextThreshold(settings, contextWindowTokens, cfg) {
|
|
74160
|
+
const reserveTokensFloor = localPressureGuardNumber(cfg?.agents?.defaults?.compaction?.reserveTokensFloor, 2e4);
|
|
74161
|
+
const floor = Math.max(reserveTokensFloor, 50000);
|
|
74162
|
+
return Math.max(Math.ceil(settings.contextRatio * contextWindowTokens), floor);
|
|
74163
|
+
}
|
|
74156
74164
|
/* JOHNNESS_PATCH_APPEND_ONLY_PRESSURE_BASELINE: derive a restart-safe byte baseline from the append-only JSONL so transcriptBytes pressure measures NEW growth since the last successful compaction rather than total (never-shrinking) file size. See docs/PATCHES.md family 22. Scans getEntries() newest->oldest for the newest SUCCESSFUL johnness.active-pressure-refresh marker (failed !== true) and returns its recorded post-compaction size (postCompactionBytes, else transcriptBytes). Returns 0 for legacy sessions with no such marker, so a first over-limit session still compacts once. */
|
|
74157
74165
|
function computeActivePressureBaselineBytes(sessionManager) {
|
|
74158
74166
|
try {
|
|
@@ -74310,12 +74318,12 @@ function compactionRotationNumber(value, fallback) {
|
|
|
74310
74318
|
return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
|
|
74311
74319
|
}
|
|
74312
74320
|
function compactionRotationSettings(cfg) {
|
|
74313
|
-
const pressure = localPressureGuardSettings(cfg) ?? { transcriptBytes: 1048576 };
|
|
74314
74321
|
const raw = cfg?.agents?.defaults?.activeSessionPressure ?? cfg?.session?.activePressure ?? {};
|
|
74315
74322
|
if (raw?.rotateAfterCompaction === false) return null;
|
|
74316
|
-
|
|
74323
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: the legacy transcriptBytes threshold no longer exists; the rotation size budget keeps its historical 1 MiB-derived default so default rotation behavior is unchanged. */
|
|
74324
|
+
const threshold = 1048576;
|
|
74317
74325
|
const configuredMax = compactionRotationNumber(raw.rotationMaxBytes, 0);
|
|
74318
|
-
const maxBytes = configuredMax > 0 ? configuredMax :
|
|
74326
|
+
const maxBytes = configuredMax > 0 ? configuredMax : Math.max(131072, Math.min(524288, Math.floor(threshold * .45)));
|
|
74319
74327
|
return {
|
|
74320
74328
|
maxBytes,
|
|
74321
74329
|
maxMessages: Math.max(4, Math.floor(compactionRotationNumber(raw.rotationMaxMessages, 80))),
|
|
@@ -74451,18 +74459,20 @@ async function maybeRefreshActiveSessionForPressure(params) {
|
|
|
74451
74459
|
const heapUsedBytes = typeof process?.memoryUsage === "function" ? process.memoryUsage().heapUsed : 0;
|
|
74452
74460
|
const __hasCompactedContext = Array.isArray(params.session.messages) && params.session.messages.some((message) => message?.role === "compactionSummary");
|
|
74453
74461
|
const __alreadyRotated = params.sessionManager.getEntries?.().some((entry) => entry?.type === "custom" && entry?.customType === "johnness.compaction-session-rotation");
|
|
74454
|
-
|
|
74462
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: the existing-compacted-lineage rotation follows the same single context-token trigger; the byte gate is gone (family 74). */
|
|
74463
|
+
const __cwcWindowTokens = localPressureGuardContextWindowTokens(params.session?.model);
|
|
74464
|
+
const __cwcThresholdTokens = localPressureGuardContextThreshold(settings, __cwcWindowTokens, params.config);
|
|
74465
|
+
const __cwcEstimatedTokens = estimateMessagesTokens(messages);
|
|
74466
|
+
if (__cwcEstimatedTokens >= __cwcThresholdTokens && __hasCompactedContext && !__alreadyRotated) {
|
|
74455
74467
|
const __existingRotation = await rotateCompactedSessionLineage({ config: params.config, session: params.session, sessionManager: params.sessionManager, sessionFile: params.sessionFile, sessionKey: params.sessionKey, sessionId: params.sessionId, reason: "existing-compacted-lineage" });
|
|
74456
74468
|
if (__existingRotation.rotated) return { refreshed: true, rotated: true, reasons: ["existing-compacted-lineage"], transcriptBytes: __existingRotation.transcriptBytes, messageCount: __existingRotation.messageCount, heapUsedBytes, sessionId: __existingRotation.sessionId, sessionFile: __existingRotation.sessionFile, oldSessionId: __existingRotation.oldSessionId, oldSessionFile: __existingRotation.oldSessionFile };
|
|
74457
74469
|
}
|
|
74458
74470
|
const reasons = [];
|
|
74459
|
-
/*
|
|
74471
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: single trigger — estimated active-context tokens vs the context-window threshold (family 74). Legacy byte/message/heap heuristics no longer gate; the family 22 append-only baseline below is computed and recorded for observability only. */
|
|
74460
74472
|
const __aopBaselineBytes = computeActivePressureBaselineBytes(params.sessionManager);
|
|
74461
74473
|
const __aopEffectiveBytes = effectiveTranscriptPressureBytes(transcriptBytes, __aopBaselineBytes);
|
|
74462
|
-
if (
|
|
74463
|
-
if (
|
|
74464
|
-
if (settings.heapUsedBytes > 0 && heapUsedBytes >= settings.heapUsedBytes) reasons.push("heapUsed=" + heapUsedBytes + "/" + settings.heapUsedBytes);
|
|
74465
|
-
if (reasons.length === 0) return { refreshed: false, reason: "below threshold", transcriptBytes, messageCount, heapUsedBytes };
|
|
74474
|
+
if (__cwcEstimatedTokens >= __cwcThresholdTokens) reasons.push("contextTokens=" + __cwcEstimatedTokens + "/" + __cwcThresholdTokens);
|
|
74475
|
+
if (reasons.length === 0) return { refreshed: false, reason: "below threshold", contextTokens: __cwcEstimatedTokens, contextThreshold: __cwcThresholdTokens, baselineBytes: __aopBaselineBytes, effectiveTranscriptBytes: __aopEffectiveBytes, transcriptBytes, messageCount, heapUsedBytes };
|
|
74466
74476
|
let last = 0;
|
|
74467
74477
|
let lastFailed = false;
|
|
74468
74478
|
let lastBytes = 0;
|
|
@@ -79883,13 +79893,14 @@ async function maybeCompactActiveRunForPressure(params) {
|
|
|
79883
79893
|
} catch {}
|
|
79884
79894
|
const heapUsedBytes = typeof process?.memoryUsage === "function" ? process.memoryUsage().heapUsed : 0;
|
|
79885
79895
|
const reasons = [];
|
|
79886
|
-
/*
|
|
79896
|
+
/* JOHNNESS_PATCH_CONTEXT_WINDOW_COMPACTION: single trigger — estimated active-context tokens vs the context-window threshold (family 74). Legacy byte/message/heap heuristics no longer gate; the family 22 append-only baseline below is computed and recorded for observability only. */
|
|
79887
79897
|
const __aopBaselineBytes = computeActivePressureBaselineBytes(params.sessionManager);
|
|
79888
79898
|
const __aopEffectiveBytes = effectiveTranscriptPressureBytes(transcriptBytes, __aopBaselineBytes);
|
|
79889
|
-
|
|
79890
|
-
|
|
79891
|
-
|
|
79892
|
-
if (
|
|
79899
|
+
const __cwcWindowTokens = localPressureGuardContextWindowTokens(params.session?.model);
|
|
79900
|
+
const __cwcThresholdTokens = localPressureGuardContextThreshold(settings, __cwcWindowTokens, params.config);
|
|
79901
|
+
const __cwcEstimatedTokens = estimateMessagesTokens(messages);
|
|
79902
|
+
if (__cwcEstimatedTokens >= __cwcThresholdTokens) reasons.push("contextTokens=" + __cwcEstimatedTokens + "/" + __cwcThresholdTokens);
|
|
79903
|
+
if (reasons.length === 0) return { refreshed: false, reason: "below threshold", contextTokens: __cwcEstimatedTokens, contextThreshold: __cwcThresholdTokens, baselineBytes: __aopBaselineBytes, effectiveTranscriptBytes: __aopEffectiveBytes, transcriptBytes, messageCount, heapUsedBytes };
|
|
79893
79904
|
let last = 0;
|
|
79894
79905
|
let lastFailed = false;
|
|
79895
79906
|
let lastBytes = 0;
|
package/docs/PATCHES.md
CHANGED
|
@@ -17,7 +17,7 @@ they predate ~2026-06-06).
|
|
|
17
17
|
|
|
18
18
|
## Index
|
|
19
19
|
|
|
20
|
-
Family 01 is retired. Families 02 through 41, 43 through
|
|
20
|
+
Family 01 is retired. Families 02 through 41, 43 through 74, including the 65.1 amendment, are live on `main`; the `latest` and `extended` release lines converged at 2026.9.24. Family 42 is omitted; native Codex OAuth ownership is Family 58.
|
|
21
21
|
|
|
22
22
|
1. **01, announce queue TTL, retired:** Removed the five-minute age filter that could discard delayed sub-agent completion announcements. [Details](#01--announce-ttl-retired-2026-07-30)
|
|
23
23
|
2. **02, failover rotation:** Returns model selection to the highest-priority profile after its cooldown ends. [Details](#02--failover-rotation-undocumented)
|
|
@@ -97,7 +97,9 @@ Family 01 is retired. Families 02 through 41, 43 through 72, including the 65.1
|
|
|
97
97
|
|
|
98
98
|
71. **71, native-first Jiti standard on latest:** The Family 68 native-first loader option ships on every artifact, the `latest` and `extended` lines converge, and a packed-artifact gate proves the tarball carries it. [Details](#family-71-native-first-jiti-standard-on-latest)
|
|
99
99
|
|
|
100
|
-
72. **72, bundled generic skills:**
|
|
100
|
+
72. **72, bundled generic skills:** Eight workspace skills (code operations, research, todos, planning, logs, and more) ship as generic bundled skills that load by description match, with no owner names or personal paths. [Details](#family-72-bundled-generic-skills)
|
|
101
|
+
73. **73, prune bundled skills:** `content-story`, `dashboard` and `cold-outreach` are removed from the Family 72 bundled set on request after `2026.9.25`; the remaining eight ship unchanged. [Details](#family-73-prune-bundled-skills)
|
|
102
|
+
74. **74, context-window compaction:** The local active-session pressure guard becomes single-trigger and model-aware: estimated active-context tokens against 70% of the active model's declared context window, floored at `max(compaction.reserveTokensFloor, 50000)`; the 1 MB byte, 220-message and 3 GiB heap triggers are removed. [Details](#family-74-context-window-compaction)
|
|
101
103
|
|
|
102
104
|
---
|
|
103
105
|
|
|
@@ -728,6 +730,7 @@ already-compacting / compaction-disabled / cooldown are no-ops.
|
|
|
728
730
|
---
|
|
729
731
|
|
|
730
732
|
## 22 - append-only-pressure-baseline (2026-07-29)
|
|
733
|
+
**Superseded by Family 74:** the append-only baseline is still computed and recorded on the `active-pressure-refresh` marker (see below), but nothing gates on it any more; the pressure trigger is now estimated context tokens against the active model's declared context window.
|
|
731
734
|
**What:** The active-pressure `transcriptBytes` trigger now measures **NEW transcript
|
|
732
735
|
growth since the last successful compaction** instead of the total, never-shrinking
|
|
733
736
|
append-only file size. This removes the false-retrigger loop where a session that has
|
|
@@ -2627,9 +2630,9 @@ Roll back with `npm i -g johns-harness@2026.9.23` (no native-first Jiti) or `npm
|
|
|
2627
2630
|
|
|
2628
2631
|
**Release:** `johns-harness@2026.9.25`. Published as `latest` and the `extended` dist-tag moves to it (the two lines converged at 2026.9.24).
|
|
2629
2632
|
|
|
2630
|
-
|
|
2633
|
+
Eight skills from the author's personal workspace ship as bundled skills in `skills/<name>/SKILL.md`, made fully generic first: no owner names, no personal paths, repos, accounts, or products. Every one loads by description match like the other bundled skills (none is `always`-on, unlike the Family 70 orchestrator), a workspace or managed copy overrides it, `skills.entries.<name>.enabled: false` turns it off, and an `allowBundled` allowlist that omits it is respected. (Superseded by Family 73: from `2026.9.26` `dashboard`, `content-story` and `cold-outreach` are removed from the bundle.)
|
|
2631
2634
|
|
|
2632
|
-
Shipped skills: `code-ops` (learnings protocol, config tracing, publishing safety), `web-research` (never give up deep research method), `plan-archival` (move finished plans to plans/archive and memory/completed-plans), `todos` (workspace memory/todos protocol), `
|
|
2635
|
+
Shipped skills: `code-ops` (learnings protocol, config tracing, publishing safety), `web-research` (never give up deep research method), `plan-archival` (move finished plans to plans/archive and memory/completed-plans), `todos` (workspace memory/todos protocol), `arch-viz` (sub-agent generated architecture visualization), `gcp-logs` (Cloud Run log debugging via gcloud, placeholder service names), `activity-logging` (log outcomes, not tasks, plus the ACTION_LOG), `outlook` (outlook tool quick reference).
|
|
2633
2636
|
|
|
2634
2637
|
Decision table:
|
|
2635
2638
|
|
|
@@ -2639,10 +2642,10 @@ Decision table:
|
|
|
2639
2642
|
| web-research | ship, converted | generic method, em dashes stripped |
|
|
2640
2643
|
| plan-archival | ship, converted | personal paths replaced with workspace-relative |
|
|
2641
2644
|
| todos | ship, converted | owner name and paths replaced |
|
|
2642
|
-
| dashboard |
|
|
2645
|
+
| dashboard | dropped | removed on request after 2026.9.25 |
|
|
2643
2646
|
| arch-viz | ship, converted | personal paths and projects scrubbed |
|
|
2644
|
-
| content-story |
|
|
2645
|
-
| cold-outreach |
|
|
2647
|
+
| content-story | dropped | removed on request after 2026.9.25 |
|
|
2648
|
+
| cold-outreach | dropped | removed on request after 2026.9.25 |
|
|
2646
2649
|
| gcp-logs | ship, converted | baked-in service names replaced with placeholders |
|
|
2647
2650
|
| activity-logging | ship, converted | log names and paths made workspace-relative |
|
|
2648
2651
|
| outlook | ship, converted | account domain scrubbed |
|
|
@@ -2655,6 +2658,30 @@ Decision table:
|
|
|
2655
2658
|
| hyperframes, hyperframes-cli, hyperframes-media, website-to-hyperframes, impeccable | exclude | third-party vendored skills |
|
|
2656
2659
|
| orchestrator | already shipped | Family 70 |
|
|
2657
2660
|
|
|
2658
|
-
Verifier checks 72.1 through 72.5 cover presence with frontmatter, the generic wording contract (no owner, product or personal names and no `always` flag), no em dashes, the RULES.md skill table, and the packed artifact (the Family 71 gate now also proves all
|
|
2661
|
+
Verifier checks 72.1 through 72.5 cover presence with frontmatter, the generic wording contract (no owner, product or personal names and no `always` flag), no em dashes, the RULES.md skill table, and the packed artifact (the Family 71 gate now also proves all eight skills are inside the tarball). `tests/bundled-skills.test.mjs` proves every skills chunk loads all eight from an empty workspace, a workspace copy overrides, `enabled: false` disables, and the `allowBundled` allowlist still wins. `RULES.md` section 5 lists every bundled skill.
|
|
2659
2662
|
|
|
2660
2663
|
Roll back with `npm i -g johns-harness@2026.9.24`.
|
|
2664
|
+
|
|
2665
|
+
## Family 73: prune bundled skills
|
|
2666
|
+
|
|
2667
|
+
**Release:** `johns-harness@2026.9.26`. Published as `latest` and the `extended` dist-tag moves to it.
|
|
2668
|
+
|
|
2669
|
+
Three of the Family 72 bundled skills are removed from the bundled set on request after `2026.9.25`: `content-story`, `dashboard` and `cold-outreach`. The remaining eight (`activity-logging`, `arch-viz`, `code-ops`, `gcp-logs`, `outlook`, `plan-archival`, `todos`, `web-research`) are unchanged, and a workspace or managed copy of a removed skill still overrides and loads as it always did. Nothing else differs from `2026.9.25`.
|
|
2670
|
+
|
|
2671
|
+
The counters move with the set: the verifier emits one check per remaining skill through the same 72.1 loop (455 checks in total), `tests/bundled-skills.test.mjs` asserts exactly eight bundled skills, `scripts/check-packed-artifact.mjs` fails closed unless a tarball carries all eight with frontmatter, and `README.md` and the pinned copy in `patches/59-migrate-cli.patch` carry the new counts together so check 59c stays green. `RULES.md` section 5 drops the three rows.
|
|
2672
|
+
|
|
2673
|
+
Roll back with `npm i -g johns-harness@2026.9.25`.
|
|
2674
|
+
|
|
2675
|
+
## Family 74: context-window compaction
|
|
2676
|
+
|
|
2677
|
+
**Release:** `johns-harness@2026.9.27`. Published as `latest` and the `extended` dist-tag moves to it.
|
|
2678
|
+
|
|
2679
|
+
A live gateway session compacted at `messages=221/220` while its transcript held only 528 KB of a 1,048,576-byte budget. The guard was firing on a fixed message count, which is the wrong unit: 221 small messages can sit comfortably inside a large context window, and a few large tool outputs can overflow a small one. Family 74 makes the local active-session pressure guard single-trigger and model-aware.
|
|
2680
|
+
|
|
2681
|
+
The only trigger is estimated active-context tokens (`estimateMessagesTokens`, the estimator the compaction path already uses) against `max(ceil(contextRatio x activeModel.contextWindow), max(compaction.reserveTokensFloor, 50000))`, with `contextRatio` defaulting to 0.7. A model that declares no `contextWindow` falls back to the runtime default. Both the startup rotation gate and the in-loop refresh push only `contextTokens=<n>/<threshold>`.
|
|
2682
|
+
|
|
2683
|
+
The `transcriptBytes` (1 MB), `messageCount` (220) and `heapUsedBytes` (3 GiB) triggers are removed by design; the legacy config keys are accepted without error and ignored. The 5-minute cooldown, the 24-message post-compaction floor and the failed-attempt growth gate stay as anti-thrash throttles, and the emergency compaction path (Family 13) is untouched, so a genuine overflow is still caught. The Family 22 append-only baseline is still computed and recorded on the `active-pressure-refresh` marker for observability, but nothing gates on it. The config surface is `enabled`, `contextRatio`, `minIntervalMs`, `minMessagesAfterCompaction`.
|
|
2684
|
+
|
|
2685
|
+
Verifier checks 74.1 through 74.4 prove the marker, the absence of the byte/message/heap triggers, the threshold math and the config parsing in all four pressure bundles; `scripts/patch-context-window-compaction.py` applies the same change to any install root (both naming eras), is idempotent with `--check`, and fails closed on anchor drift. `patches/provider-catalog/changes.json` pins the four pressure bundles by hash, so `scripts/patch-provider-catalog.py` maps the Family 74 rewrite back to its pre-image in `family67_surface`, exactly as it already does for Family 68.
|
|
2686
|
+
|
|
2687
|
+
Roll back with `npm i -g johns-harness@2026.9.26`.
|
package/package.json
CHANGED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: cold-outreach
|
|
3
|
-
description: Write cold DMs that get responses using the Four Pillars framework. Use when drafting outreach messages, direct messages, or connection requests for the user.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Cold Outreach / DM Skill
|
|
7
|
-
|
|
8
|
-
Write cold DMs that get responses. Uses the Four Pillars framework.
|
|
9
|
-
|
|
10
|
-
## Required Reading
|
|
11
|
-
|
|
12
|
-
Before ANY outreach, read the full playbook if one exists:
|
|
13
|
-
- `memory/outreach-playbook.md` in the workspace
|
|
14
|
-
|
|
15
|
-
## The Four Pillars
|
|
16
|
-
|
|
17
|
-
Every message must hit all 4:
|
|
18
|
-
|
|
19
|
-
1. **PERSONAL**: their thesis/worldview (what they REALLY believe)
|
|
20
|
-
2. **RELEVANT**: their current mission (what they're building NOW)
|
|
21
|
-
3. **TIMELY**: recent content (what's top of mind TODAY)
|
|
22
|
-
4. **POWERFUL**: peer energy (you're a collaborator, not a fan)
|
|
23
|
-
|
|
24
|
-
## The DM Flow
|
|
25
|
-
|
|
26
|
-
| Step | What to Say | Goal |
|
|
27
|
-
|------|-------------|------|
|
|
28
|
-
| 1. Opener | React to THEIR thing + ask question | Start conversation |
|
|
29
|
-
| 2. Listen | Let them share their pain | Understand their words |
|
|
30
|
-
| 3. "Same" | "yeah same, I built something" | Create curiosity |
|
|
31
|
-
| 4. Wait | They ask "what is it?" | Make them pull |
|
|
32
|
-
| 5. Share | Now give them the product | Favor, not pitch |
|
|
33
|
-
|
|
34
|
-
## Opener Formula
|
|
35
|
-
|
|
36
|
-
```
|
|
37
|
-
"[reaction to specific content]. [establish same problem]. [ask what they did about it]"
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
**Example:**
|
|
41
|
-
> "yo that piece on agents forgetting everything hit hard. been banging my head on the same problem. curious what you ended up doing about it"
|
|
42
|
-
|
|
43
|
-
## Anti-Patterns (NEVER)
|
|
44
|
-
|
|
45
|
-
- ❌ Product name in opener
|
|
46
|
-
- ❌ Install commands
|
|
47
|
-
- ❌ "Your audience would love..."
|
|
48
|
-
- ❌ Flattery ("love your content!")
|
|
49
|
-
- ❌ Fan energy ("would you check out...")
|
|
50
|
-
- ❌ Offering before they ask
|
|
51
|
-
|
|
52
|
-
## Good vs Bad
|
|
53
|
-
|
|
54
|
-
**Bad (ad energy):**
|
|
55
|
-
> "Hey [name] - been watching your agent coverage. I built [our product], a plugin that gives agents persistent memory. One-liner install. Think your audience would love it."
|
|
56
|
-
|
|
57
|
-
**Good (peer energy):**
|
|
58
|
-
> "yo that piece on agents forgetting everything hit hard. been banging my head on the same problem. curious what you ended up doing about it"
|
|
59
|
-
|
|
60
|
-
## Research Requirements
|
|
61
|
-
|
|
62
|
-
Before writing ANY outreach:
|
|
63
|
-
1. Watch 2-3 recent videos: find their THESIS
|
|
64
|
-
2. Read social presence: what identity are they building?
|
|
65
|
-
3. Find ONE specific thing to react to
|
|
66
|
-
4. Know what they'll likely respond (from research)
|
|
67
|
-
5. Plan your step 3 response
|
|
68
|
-
|
|
69
|
-
## Output Format
|
|
70
|
-
|
|
71
|
-
For each creator, produce:
|
|
72
|
-
|
|
73
|
-
```markdown
|
|
74
|
-
## [Creator Name]
|
|
75
|
-
|
|
76
|
-
### Research
|
|
77
|
-
- **Thesis:** [what they really believe]
|
|
78
|
-
- **Current mission:** [what they're building now]
|
|
79
|
-
- **Recent content:** [specific thing to reference]
|
|
80
|
-
- **Their solution:** [what they're currently doing about the problem]
|
|
81
|
-
|
|
82
|
-
### Opener
|
|
83
|
-
> [the DM]
|
|
84
|
-
|
|
85
|
-
### Expected Response
|
|
86
|
-
> [what they'll likely say]
|
|
87
|
-
|
|
88
|
-
### Step 3 Response
|
|
89
|
-
> [our "same, I built something" response]
|
|
90
|
-
|
|
91
|
-
### Step 5 Share
|
|
92
|
-
> [product share if they ask]
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
## Key Insight
|
|
96
|
-
|
|
97
|
-
**Make them ask. Never offer first.**
|
|
98
|
-
|
|
99
|
-
The goal is to create curiosity so strong that THEY pull the product out of you. Then sharing feels like a favor, not a pitch.
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: content-story
|
|
3
|
-
description: Generate content ideas using the Story, Concept, Drop framework. Use when brainstorming short-form video content, social posts, or creative concepts that need a hook and a payoff.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Content Story Skill
|
|
7
|
-
|
|
8
|
-
Generate content ideas using the Story → Concept → Drop framework.
|
|
9
|
-
|
|
10
|
-
## The Framework
|
|
11
|
-
|
|
12
|
-
Every piece of content needs three things:
|
|
13
|
-
|
|
14
|
-
### 1. The Story
|
|
15
|
-
The journey. Beginning → destination. A problem that's relatable and a resolution that's satisfying.
|
|
16
|
-
- The problem doesn't need to be big
|
|
17
|
-
- The resolution doesn't need to be inspiring
|
|
18
|
-
- But there MUST be a journey: something changes from start to finish
|
|
19
|
-
|
|
20
|
-
### 2. The Concept
|
|
21
|
-
The viral component. What's on screen that makes someone WATCH?
|
|
22
|
-
- A beautiful person
|
|
23
|
-
- Something unexpected just happened
|
|
24
|
-
- You need to see what comes next
|
|
25
|
-
- A visual that stops the scroll
|
|
26
|
-
- Curiosity gap: "wait, what?"
|
|
27
|
-
|
|
28
|
-
### 3. The Drop
|
|
29
|
-
The climax. The moment the video makes sense. The payoff.
|
|
30
|
-
- This is what people REWATCH for
|
|
31
|
-
- Rewatches = algorithm fuel
|
|
32
|
-
- The drop should feel earned: the story builds to it
|
|
33
|
-
- Can be visual (reveal), emotional (surprise), or both
|
|
34
|
-
|
|
35
|
-
## Rules
|
|
36
|
-
|
|
37
|
-
- **Would YOU watch it?** If no, don't post it
|
|
38
|
-
- **15-30 seconds max** for reels: tight, no fat
|
|
39
|
-
- **Music matters**: the right song makes or breaks the drop
|
|
40
|
-
- **Film 10x more than you post**: capture everything, curate ruthlessly
|
|
41
|
-
- **No talking heads, no "5 tips", no corporate energy**
|
|
42
|
-
- **Raw + cinematic > polished + corporate**
|
|
43
|
-
- **Not looking at the lens > looking at the lens**: candid energy even when staged
|
|
44
|
-
- **Daily posting beats perfect posting**: consistency wins
|
|
45
|
-
|
|
46
|
-
## How to Use
|
|
47
|
-
|
|
48
|
-
When brainstorming content, fill in:
|
|
49
|
-
|
|
50
|
-
```
|
|
51
|
-
STORY: [the journey: what changes?]
|
|
52
|
-
CONCEPT: [the hook: why do they watch?]
|
|
53
|
-
DROP: [the payoff: what's the climax?]
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
Then figure out:
|
|
57
|
-
- What do you need to film?
|
|
58
|
-
- What song fits?
|
|
59
|
-
- What's the edit style? (slow-mo, transition, split screen, etc.)
|
|
60
|
-
|
|
61
|
-
## Content Types That Hit
|
|
62
|
-
|
|
63
|
-
- **Main character POV**: walking, arriving, living. Viewer projects themselves into it
|
|
64
|
-
- **Transitions**: before/after, location swap, outfit change, time shift
|
|
65
|
-
- **Silent storytelling**: music + visuals + text overlay. Works sound on AND off
|
|
66
|
-
- **Candid energy**: looks unplanned but isn't. Natural > posed
|
|
67
|
-
- **Reveals**: camera pulls back or cuts to show something unexpected
|
|
68
|
-
- **Contrast**: old life vs new life, morning vs night, alone vs crowd
|
|
69
|
-
|
|
70
|
-
## The Test
|
|
71
|
-
|
|
72
|
-
Before posting, ask:
|
|
73
|
-
1. Does it have all three? (Story, Concept, Drop)
|
|
74
|
-
2. Would I stop scrolling for this?
|
|
75
|
-
3. Would I rewatch it?
|
|
76
|
-
|
|
77
|
-
If yes to all three → post it.
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: dashboard
|
|
3
|
-
description: Maintain the user's command center dashboard in memory/dashboard.md. Update after any action (email sent, reply received, task completed, status change). Use when tracking pending items, project status, or giving the user a view of what's happening. The dashboard is the user's starting point; keep it current and useful.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# The Dashboard
|
|
7
|
-
|
|
8
|
-
The user's command center. Updated constantly. Shows what matters RIGHT NOW.
|
|
9
|
-
|
|
10
|
-
## Location
|
|
11
|
-
|
|
12
|
-
- **File:** `memory/dashboard.md` in the workspace
|
|
13
|
-
- If the workspace is a git repo, commit and push after every update so the user can view it from anywhere.
|
|
14
|
-
|
|
15
|
-
## Philosophy
|
|
16
|
-
|
|
17
|
-
**Dynamic, not rigid.** Include what's relevant today. Sections appear/disappear based on what matters.
|
|
18
|
-
|
|
19
|
-
**Curated, not comprehensive.** This is not a todo list dump. It is the user's "here's what you need to know right now."
|
|
20
|
-
|
|
21
|
-
**Work AND life.** Personal stuff belongs here too if it is on the user's mind.
|
|
22
|
-
|
|
23
|
-
## Sections (Use What's Relevant)
|
|
24
|
-
|
|
25
|
-
```markdown
|
|
26
|
-
# The Dashboard
|
|
27
|
-
**Updated:** [timestamp in the user's timezone]
|
|
28
|
-
|
|
29
|
-
## Right Now
|
|
30
|
-
[Most urgent/relevant thing: meeting in 30 min, decision needed, blocker resolved]
|
|
31
|
-
|
|
32
|
-
## Waiting On
|
|
33
|
-
[People who owe the user something: name, what, how long]
|
|
34
|
-
|
|
35
|
-
## Today
|
|
36
|
-
[What's on deck: meetings, tasks, deadlines]
|
|
37
|
-
|
|
38
|
-
## Hot Projects
|
|
39
|
-
[Active projects with one-liner status + next action]
|
|
40
|
-
|
|
41
|
-
## Notes
|
|
42
|
-
[Context, reminders, thoughts worth capturing]
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
Not every section every day. Just what matters.
|
|
46
|
-
|
|
47
|
-
## When to Update
|
|
48
|
-
|
|
49
|
-
| Trigger | Action |
|
|
50
|
-
|---------|--------|
|
|
51
|
-
| Email sent | Add to "Waiting On" with timestamp |
|
|
52
|
-
| Reply received | Update or remove from "Waiting On" |
|
|
53
|
-
| Task completed | Remove from "Today" or note completion |
|
|
54
|
-
| Meeting coming up | Add to "Right Now" if within 1 hour |
|
|
55
|
-
| Status change | Update "Hot Projects" |
|
|
56
|
-
| New blocker | Add to "Right Now" or "Waiting On" |
|
|
57
|
-
| Something resolved | Remove or celebrate in "Notes" |
|
|
58
|
-
|
|
59
|
-
## Prioritization (What Goes in "Right Now")
|
|
60
|
-
|
|
61
|
-
1. **Time-sensitive**: meeting in < 1 hour, deadline today
|
|
62
|
-
2. **Blocking**: something the user needs to unblock others
|
|
63
|
-
3. **Waiting too long**: pending response > 3 days
|
|
64
|
-
4. **Big news**: reply that changes things, win worth noting
|
|
65
|
-
|
|
66
|
-
## Format Rules
|
|
67
|
-
|
|
68
|
-
- **Timestamps:** always in the user's timezone, 12-hour format (e.g., "1:45 PM")
|
|
69
|
-
- **People:** name + company/context (e.g., "Alex (vendor)")
|
|
70
|
-
- **Projects:** link to the project folder if one exists
|
|
71
|
-
- **Keep it scannable:** tables for lists, bullets for notes
|
|
72
|
-
|
|
73
|
-
## After Every Update
|
|
74
|
-
|
|
75
|
-
```bash
|
|
76
|
-
cd <workspace>
|
|
77
|
-
git add -A && git commit -m "Update dashboard" && git push
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
(If the workspace is not a git repo, skip the push.)
|
|
81
|
-
|
|
82
|
-
## Automated Monitoring
|
|
83
|
-
|
|
84
|
-
A scheduled job can check the user's inbox, compare against "Waiting On" and "Hot Projects", message the user if anything relevant, and stay silent if nothing important. Manual updates still happen after interactions.
|
|
85
|
-
|
|
86
|
-
## Calendar Integration
|
|
87
|
-
|
|
88
|
-
Pull from the calendar tool when relevant. Add meetings to "Today" with times in the user's timezone.
|
|
89
|
-
|
|
90
|
-
## Examples
|
|
91
|
-
|
|
92
|
-
**Busy day with meetings:**
|
|
93
|
-
```markdown
|
|
94
|
-
## Right Now
|
|
95
|
-
📅 Team meeting in 25 min (11:00 AM)
|
|
96
|
-
|
|
97
|
-
## Today
|
|
98
|
-
- 11:00 AM - Team meeting
|
|
99
|
-
- 12:00 PM - Vendor call
|
|
100
|
-
- 2:00 PM - Project check-in
|
|
101
|
-
|
|
102
|
-
## Waiting On
|
|
103
|
-
- Alex (vendor) - server config fix (sent 1:42 PM)
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
**Quiet day, project focus:**
|
|
107
|
-
```markdown
|
|
108
|
-
## Right Now
|
|
109
|
-
Nothing urgent. Good day to ship.
|
|
110
|
-
|
|
111
|
-
## Hot Projects
|
|
112
|
-
- **Project A** - building the configurator (from this morning's meeting)
|
|
113
|
-
- **Project B** - blocked on a vendor fix
|
|
114
|
-
|
|
115
|
-
## Notes
|
|
116
|
-
The user should have their password synced by end of day.
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
**Personal stuff mixed in:**
|
|
120
|
-
```markdown
|
|
121
|
-
## Today
|
|
122
|
-
- 10:00 AM - Dentist
|
|
123
|
-
- 2:00 PM - Demo with a client
|
|
124
|
-
- Pick up dry cleaning
|
|
125
|
-
|
|
126
|
-
## Waiting On
|
|
127
|
-
- Alex (vendor) - server fix
|
|
128
|
-
- Online order - package arriving today
|
|
129
|
-
```
|