instar 0.28.86 → 0.28.88
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/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +9 -0
- package/dist/commands/server.js.map +1 -1
- package/dist/core/InitiativeTracker.d.ts +1 -0
- package/dist/core/InitiativeTracker.d.ts.map +1 -1
- package/dist/core/InitiativeTracker.js +8 -1
- package/dist/core/InitiativeTracker.js.map +1 -1
- package/dist/core/PlanDocParser.d.ts +62 -0
- package/dist/core/PlanDocParser.d.ts.map +1 -0
- package/dist/core/PlanDocParser.js +328 -0
- package/dist/core/PlanDocParser.js.map +1 -0
- package/dist/core/ProjectDigestCache.d.ts +58 -0
- package/dist/core/ProjectDigestCache.d.ts.map +1 -0
- package/dist/core/ProjectDigestCache.js +146 -0
- package/dist/core/ProjectDigestCache.js.map +1 -0
- package/dist/core/SafeYaml.d.ts +45 -0
- package/dist/core/SafeYaml.d.ts.map +1 -0
- package/dist/core/SafeYaml.js +230 -0
- package/dist/core/SafeYaml.js.map +1 -0
- package/dist/core/SessionManager.d.ts +12 -0
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +60 -0
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/StageTransitionValidator.d.ts +97 -0
- package/dist/core/StageTransitionValidator.d.ts.map +1 -0
- package/dist/core/StageTransitionValidator.js +338 -0
- package/dist/core/StageTransitionValidator.js.map +1 -0
- package/dist/monitoring/StallTriageNurse.d.ts +11 -0
- package/dist/monitoring/StallTriageNurse.d.ts.map +1 -1
- package/dist/monitoring/StallTriageNurse.js +66 -0
- package/dist/monitoring/StallTriageNurse.js.map +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +312 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +58 -50
- package/src/templates/hooks/compaction-recovery.sh +50 -0
- package/src/templates/hooks/session-start.sh +50 -0
- package/upgrades/0.28.87.md +153 -0
- package/upgrades/0.28.88.md +91 -0
- package/upgrades/side-effects/0.28.86.md +13 -0
- package/upgrades/side-effects/0.28.87.md +13 -0
- package/upgrades/side-effects/project-scope-phase1a-pr2.md +377 -0
- package/upgrades/side-effects/project-scope-phase1a-pr3.md +477 -0
- package/upgrades/side-effects/verify-injection-stuck-input.md +107 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { InitiativeTracker, Initiative } from './InitiativeTracker.js';
|
|
2
|
+
/** Where the digest lands. Hooks read this exact path. */
|
|
3
|
+
export declare const DIGEST_CACHE_FILENAME = "projects-digest.cache";
|
|
4
|
+
/** Max projects rendered into `digestLines`. Top-N by `lastTouchedAt`. */
|
|
5
|
+
export declare const MAX_PROJECTS_IN_DIGEST = 5;
|
|
6
|
+
/** Max characters per sanitized string (titles, round names). */
|
|
7
|
+
export declare const MAX_STRING_LENGTH = 80;
|
|
8
|
+
/** JSON shape that the hooks deserialize. */
|
|
9
|
+
export interface ProjectDigestCacheFile {
|
|
10
|
+
/** ISO timestamp when this snapshot was written. */
|
|
11
|
+
generatedAt: string;
|
|
12
|
+
/** One sanitized one-liner per active project, top-N by `lastTouchedAt`. */
|
|
13
|
+
digestLines: string[];
|
|
14
|
+
/** Total active projects in the tracker (independent of truncation). */
|
|
15
|
+
totalActiveProjects: number;
|
|
16
|
+
/** True iff `totalActiveProjects > MAX_PROJECTS_IN_DIGEST`. */
|
|
17
|
+
truncated: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Strip control chars (incl. \n, \r, \t), then collapse runs of internal
|
|
21
|
+
* whitespace to single spaces and cap at `cap` chars.
|
|
22
|
+
*
|
|
23
|
+
* Exported so the hooks (well, their JS-side helpers) and tests can apply
|
|
24
|
+
* the same rule on read. The bash hooks themselves use a `tr`-based
|
|
25
|
+
* equivalent — the literal regex below is the canonical implementation.
|
|
26
|
+
*/
|
|
27
|
+
export declare function sanitizeDigestString(input: unknown, cap?: number): string;
|
|
28
|
+
/**
|
|
29
|
+
* Render one digest line for a single project. Pure function — caller
|
|
30
|
+
* provides the project; sanitization happens inside.
|
|
31
|
+
*/
|
|
32
|
+
export declare function formatProjectDigestLine(project: Initiative): string;
|
|
33
|
+
/**
|
|
34
|
+
* ProjectDigestCache — single-responsibility writer. Construct once at
|
|
35
|
+
* server boot; pass `writeDigestCache.bind(this)` as the invalidator on
|
|
36
|
+
* `InitiativeTracker.setDigestCacheInvalidator(fn)`.
|
|
37
|
+
*/
|
|
38
|
+
export declare class ProjectDigestCache {
|
|
39
|
+
private readonly filePath;
|
|
40
|
+
private readonly tracker;
|
|
41
|
+
/** Bound to `process.pid` so concurrent writers (test sandbox + main
|
|
42
|
+
* process) don't trample one another's temp files. */
|
|
43
|
+
private readonly tmpSuffix;
|
|
44
|
+
constructor(stateDir: string, tracker: InitiativeTracker);
|
|
45
|
+
/** Absolute path to the cache file. Exposed for diagnostics. */
|
|
46
|
+
getCachePath(): string;
|
|
47
|
+
/**
|
|
48
|
+
* Snapshot all active projects, render the top-N digest lines, and write
|
|
49
|
+
* the result atomically. Synchronous on purpose — runs in the
|
|
50
|
+
* invalidator hot path (every project mutation calls it once).
|
|
51
|
+
*
|
|
52
|
+
* Best-effort: any thrown error is swallowed after logging, so a hiccup
|
|
53
|
+
* writing the cache never blocks a successful mutation.
|
|
54
|
+
*/
|
|
55
|
+
writeDigestCache(): void;
|
|
56
|
+
private atomicWrite;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=ProjectDigestCache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProjectDigestCache.d.ts","sourceRoot":"","sources":["../../src/core/ProjectDigestCache.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAE5E,0DAA0D;AAC1D,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAE7D,0EAA0E;AAC1E,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,iEAAiE;AACjE,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,6CAA6C;AAC7C,MAAM,WAAW,sBAAsB;IACrC,oDAAoD;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,wEAAwE;IACxE,mBAAmB,EAAE,MAAM,CAAC;IAC5B,+DAA+D;IAC/D,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,SAAoB,GAAG,MAAM,CAUpF;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAsBnE;AAaD;;;;GAIG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAC5C;2DACuD;IACvD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB;IAMxD,gEAAgE;IAChE,YAAY,IAAI,MAAM;IAItB;;;;;;;OAOG;IACH,gBAAgB,IAAI,IAAI;IA4BxB,OAAO,CAAC,WAAW;CAOpB"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProjectDigestCache — writes a sanitized JSON snapshot of active projects
|
|
3
|
+
* to `.instar/projects-digest.cache` for cheap, no-HTTP consumption by
|
|
4
|
+
* session-start and compaction-recovery hooks.
|
|
5
|
+
*
|
|
6
|
+
* Spec source: PROJECT-SCOPE-SPEC.md § Phase 1.9 (session-start + compaction
|
|
7
|
+
* recovery hooks). The hooks have a ≤50ms budget — pure file read, no HTTP.
|
|
8
|
+
*
|
|
9
|
+
* Invariants:
|
|
10
|
+
* - Top 5 active projects by `lastTouchedAt` (desc) are included; the
|
|
11
|
+
* `truncated` flag + `totalActiveProjects` count make over-limit visible.
|
|
12
|
+
* - Every string field that lands in the cache is sanitized at write time:
|
|
13
|
+
* control chars (incl. newline + CR) stripped, and the result capped at
|
|
14
|
+
* 80 characters. The hooks ALSO sanitize on read (defense in depth),
|
|
15
|
+
* so direct cache-file poisoning can't smuggle an unprintable string
|
|
16
|
+
* into orientation output.
|
|
17
|
+
* - Atomic on-disk write (temp file + rename) — readers never observe a
|
|
18
|
+
* partial file. Matches the pattern `InitiativeTracker.saveToDisk()`
|
|
19
|
+
* uses for its own persistence.
|
|
20
|
+
*
|
|
21
|
+
* This module is the **read side** of the invalidator hook PR 1 added on
|
|
22
|
+
* InitiativeTracker (`setDigestCacheInvalidator`). The server wires
|
|
23
|
+
* `writeDigestCache()` as the invalidator at boot, so every successful
|
|
24
|
+
* project mutation re-renders the file. Mutations on `kind:'task'`
|
|
25
|
+
* initiatives also trigger a rewrite — the function filters internally to
|
|
26
|
+
* `kind:'project' && status:'active'`, so the side effect is a no-op when
|
|
27
|
+
* no project state changed.
|
|
28
|
+
*/
|
|
29
|
+
import fs from 'node:fs';
|
|
30
|
+
import path from 'node:path';
|
|
31
|
+
/** Where the digest lands. Hooks read this exact path. */
|
|
32
|
+
export const DIGEST_CACHE_FILENAME = 'projects-digest.cache';
|
|
33
|
+
/** Max projects rendered into `digestLines`. Top-N by `lastTouchedAt`. */
|
|
34
|
+
export const MAX_PROJECTS_IN_DIGEST = 5;
|
|
35
|
+
/** Max characters per sanitized string (titles, round names). */
|
|
36
|
+
export const MAX_STRING_LENGTH = 80;
|
|
37
|
+
/**
|
|
38
|
+
* Strip control chars (incl. \n, \r, \t), then collapse runs of internal
|
|
39
|
+
* whitespace to single spaces and cap at `cap` chars.
|
|
40
|
+
*
|
|
41
|
+
* Exported so the hooks (well, their JS-side helpers) and tests can apply
|
|
42
|
+
* the same rule on read. The bash hooks themselves use a `tr`-based
|
|
43
|
+
* equivalent — the literal regex below is the canonical implementation.
|
|
44
|
+
*/
|
|
45
|
+
export function sanitizeDigestString(input, cap = MAX_STRING_LENGTH) {
|
|
46
|
+
const raw = typeof input === 'string' ? input : input == null ? '' : String(input);
|
|
47
|
+
// Strip ASCII control chars (0x00-0x1F) and DEL (0x7F).
|
|
48
|
+
// Replaces with a single space so words don't collide.
|
|
49
|
+
// eslint-disable-next-line no-control-regex
|
|
50
|
+
const stripped = raw.replace(/[\x00-\x1F\x7F]/g, ' ');
|
|
51
|
+
// Collapse internal whitespace runs, trim ends.
|
|
52
|
+
const collapsed = stripped.replace(/\s+/g, ' ').trim();
|
|
53
|
+
if (collapsed.length <= cap)
|
|
54
|
+
return collapsed;
|
|
55
|
+
return collapsed.slice(0, cap);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Render one digest line for a single project. Pure function — caller
|
|
59
|
+
* provides the project; sanitization happens inside.
|
|
60
|
+
*/
|
|
61
|
+
export function formatProjectDigestLine(project) {
|
|
62
|
+
const id = sanitizeDigestString(project.id, MAX_STRING_LENGTH);
|
|
63
|
+
const rounds = Array.isArray(project.rounds) ? project.rounds : [];
|
|
64
|
+
const total = rounds.length;
|
|
65
|
+
const done = rounds.filter((r) => r && (r.status === 'complete' || r.status === 'complete-with-skips')).length;
|
|
66
|
+
// Next round: first non-complete round in order. Falls through to "(none)"
|
|
67
|
+
// when every round is done.
|
|
68
|
+
const next = rounds.find((r) => r &&
|
|
69
|
+
r.status !== 'complete' &&
|
|
70
|
+
r.status !== 'complete-with-skips' &&
|
|
71
|
+
r.status !== 'failed');
|
|
72
|
+
const nextLabel = next
|
|
73
|
+
? sanitizeDigestString(next.name || '(unnamed round)', MAX_STRING_LENGTH)
|
|
74
|
+
: '(none — all rounds complete)';
|
|
75
|
+
return `Project [${id}]: ${done} of ${total} done. Next round: ${nextLabel}.`;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Sort projects by `lastTouchedAt` descending. Ties broken by `id` ascending
|
|
79
|
+
* so the output is stable.
|
|
80
|
+
*/
|
|
81
|
+
function sortByLastTouched(a, b) {
|
|
82
|
+
const at = a.lastTouchedAt ?? '';
|
|
83
|
+
const bt = b.lastTouchedAt ?? '';
|
|
84
|
+
if (at === bt)
|
|
85
|
+
return a.id.localeCompare(b.id);
|
|
86
|
+
return bt.localeCompare(at);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* ProjectDigestCache — single-responsibility writer. Construct once at
|
|
90
|
+
* server boot; pass `writeDigestCache.bind(this)` as the invalidator on
|
|
91
|
+
* `InitiativeTracker.setDigestCacheInvalidator(fn)`.
|
|
92
|
+
*/
|
|
93
|
+
export class ProjectDigestCache {
|
|
94
|
+
filePath;
|
|
95
|
+
tracker;
|
|
96
|
+
/** Bound to `process.pid` so concurrent writers (test sandbox + main
|
|
97
|
+
* process) don't trample one another's temp files. */
|
|
98
|
+
tmpSuffix;
|
|
99
|
+
constructor(stateDir, tracker) {
|
|
100
|
+
this.filePath = path.join(stateDir, DIGEST_CACHE_FILENAME);
|
|
101
|
+
this.tracker = tracker;
|
|
102
|
+
this.tmpSuffix = `.${process.pid}.tmp`;
|
|
103
|
+
}
|
|
104
|
+
/** Absolute path to the cache file. Exposed for diagnostics. */
|
|
105
|
+
getCachePath() {
|
|
106
|
+
return this.filePath;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Snapshot all active projects, render the top-N digest lines, and write
|
|
110
|
+
* the result atomically. Synchronous on purpose — runs in the
|
|
111
|
+
* invalidator hot path (every project mutation calls it once).
|
|
112
|
+
*
|
|
113
|
+
* Best-effort: any thrown error is swallowed after logging, so a hiccup
|
|
114
|
+
* writing the cache never blocks a successful mutation.
|
|
115
|
+
*/
|
|
116
|
+
writeDigestCache() {
|
|
117
|
+
try {
|
|
118
|
+
const all = this.tracker.list({ kind: 'project', status: 'active' });
|
|
119
|
+
// `list()` already sorts by `lastTouchedAt` desc; re-sort defensively
|
|
120
|
+
// in case the contract changes underneath us.
|
|
121
|
+
const sorted = [...all].sort(sortByLastTouched);
|
|
122
|
+
const total = sorted.length;
|
|
123
|
+
const truncated = total > MAX_PROJECTS_IN_DIGEST;
|
|
124
|
+
const top = sorted.slice(0, MAX_PROJECTS_IN_DIGEST);
|
|
125
|
+
const digestLines = top.map((p) => formatProjectDigestLine(p));
|
|
126
|
+
const payload = {
|
|
127
|
+
generatedAt: new Date().toISOString(),
|
|
128
|
+
digestLines,
|
|
129
|
+
totalActiveProjects: total,
|
|
130
|
+
truncated,
|
|
131
|
+
};
|
|
132
|
+
this.atomicWrite(JSON.stringify(payload, null, 2));
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
console.warn(`[ProjectDigestCache] writeDigestCache failed (non-fatal): ${err instanceof Error ? err.message : err}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
atomicWrite(contents) {
|
|
139
|
+
const dir = path.dirname(this.filePath);
|
|
140
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
141
|
+
const tmp = `${this.filePath}${this.tmpSuffix}`;
|
|
142
|
+
fs.writeFileSync(tmp, contents);
|
|
143
|
+
fs.renameSync(tmp, this.filePath);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=ProjectDigestCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProjectDigestCache.js","sourceRoot":"","sources":["../../src/core/ProjectDigestCache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny YAML frontmatter parser used by project-scope.
|
|
3
|
+
*
|
|
4
|
+
* Scope is deliberately narrow:
|
|
5
|
+
* - top-level scalar keys (`key: value`)
|
|
6
|
+
* - top-level boolean (`true` / `false`) and numeric scalars
|
|
7
|
+
* - top-level string scalars (with optional double-quoting)
|
|
8
|
+
* - top-level string arrays via `- item` block sequences OR `[a, b, c]`
|
|
9
|
+
* flow sequences
|
|
10
|
+
* - no nested maps, no anchors, no multi-document streams
|
|
11
|
+
*
|
|
12
|
+
* Why not js-yaml: that dep isn't in the current package.json and the spec
|
|
13
|
+
* (Phase 1.6) only asks for safe-load semantics over a constrained schema.
|
|
14
|
+
* Adding a new runtime dep for ~40 lines of work isn't worth the supply-chain
|
|
15
|
+
* surface. If the schema grows beyond block scalars we add js-yaml then.
|
|
16
|
+
*
|
|
17
|
+
* Hardening:
|
|
18
|
+
* - Tag-like values starting with `!` are rejected (no `!!python/object`).
|
|
19
|
+
* - Anchor / alias tokens (`&` / `*` at the start of a value) are rejected.
|
|
20
|
+
* - Aborts after 1000 lines to bound CPU on adversarial input.
|
|
21
|
+
*
|
|
22
|
+
* All callers wrap the output in their own schema validator — this returns
|
|
23
|
+
* `unknown` shaped as `Record<string, unknown>` and never throws on missing
|
|
24
|
+
* keys.
|
|
25
|
+
*/
|
|
26
|
+
export interface FrontmatterResult {
|
|
27
|
+
ok: true;
|
|
28
|
+
data: Record<string, unknown>;
|
|
29
|
+
}
|
|
30
|
+
export interface FrontmatterError {
|
|
31
|
+
ok: false;
|
|
32
|
+
error: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Extract the YAML frontmatter from a markdown string. Returns the parsed
|
|
36
|
+
* frontmatter and the body (everything after the second `---`). If no
|
|
37
|
+
* frontmatter is present, `data` is `{}` and body is the entire input.
|
|
38
|
+
*/
|
|
39
|
+
export declare function extractFrontmatter(source: string): {
|
|
40
|
+
frontmatter: Record<string, unknown> | null;
|
|
41
|
+
body: string;
|
|
42
|
+
error?: string;
|
|
43
|
+
};
|
|
44
|
+
export declare function parseSafeYaml(input: string): FrontmatterResult | FrontmatterError;
|
|
45
|
+
//# sourceMappingURL=SafeYaml.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SafeYaml.d.ts","sourceRoot":"","sources":["../../src/core/SafeYaml.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,IAAI,CAAC;IACT,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,GACb;IAAE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CA8B/E;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,iBAAiB,GAAG,gBAAgB,CA2EjF"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny YAML frontmatter parser used by project-scope.
|
|
3
|
+
*
|
|
4
|
+
* Scope is deliberately narrow:
|
|
5
|
+
* - top-level scalar keys (`key: value`)
|
|
6
|
+
* - top-level boolean (`true` / `false`) and numeric scalars
|
|
7
|
+
* - top-level string scalars (with optional double-quoting)
|
|
8
|
+
* - top-level string arrays via `- item` block sequences OR `[a, b, c]`
|
|
9
|
+
* flow sequences
|
|
10
|
+
* - no nested maps, no anchors, no multi-document streams
|
|
11
|
+
*
|
|
12
|
+
* Why not js-yaml: that dep isn't in the current package.json and the spec
|
|
13
|
+
* (Phase 1.6) only asks for safe-load semantics over a constrained schema.
|
|
14
|
+
* Adding a new runtime dep for ~40 lines of work isn't worth the supply-chain
|
|
15
|
+
* surface. If the schema grows beyond block scalars we add js-yaml then.
|
|
16
|
+
*
|
|
17
|
+
* Hardening:
|
|
18
|
+
* - Tag-like values starting with `!` are rejected (no `!!python/object`).
|
|
19
|
+
* - Anchor / alias tokens (`&` / `*` at the start of a value) are rejected.
|
|
20
|
+
* - Aborts after 1000 lines to bound CPU on adversarial input.
|
|
21
|
+
*
|
|
22
|
+
* All callers wrap the output in their own schema validator — this returns
|
|
23
|
+
* `unknown` shaped as `Record<string, unknown>` and never throws on missing
|
|
24
|
+
* keys.
|
|
25
|
+
*/
|
|
26
|
+
const MAX_LINES = 1000;
|
|
27
|
+
/**
|
|
28
|
+
* Extract the YAML frontmatter from a markdown string. Returns the parsed
|
|
29
|
+
* frontmatter and the body (everything after the second `---`). If no
|
|
30
|
+
* frontmatter is present, `data` is `{}` and body is the entire input.
|
|
31
|
+
*/
|
|
32
|
+
export function extractFrontmatter(source) {
|
|
33
|
+
const trimmedHead = source.startsWith('') ? source.slice(1) : source;
|
|
34
|
+
if (!trimmedHead.startsWith('---')) {
|
|
35
|
+
return { frontmatter: null, body: source };
|
|
36
|
+
}
|
|
37
|
+
const lines = trimmedHead.split(/\r?\n/);
|
|
38
|
+
if (lines.length > MAX_LINES) {
|
|
39
|
+
return { frontmatter: null, body: source, error: 'document exceeds 1000-line cap' };
|
|
40
|
+
}
|
|
41
|
+
// First line should be the opening `---` (possibly with trailing spaces).
|
|
42
|
+
if (lines[0].trim() !== '---') {
|
|
43
|
+
return { frontmatter: null, body: source };
|
|
44
|
+
}
|
|
45
|
+
let endIdx = -1;
|
|
46
|
+
for (let i = 1; i < lines.length; i++) {
|
|
47
|
+
if (lines[i].trim() === '---' || lines[i].trim() === '...') {
|
|
48
|
+
endIdx = i;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (endIdx === -1) {
|
|
53
|
+
return { frontmatter: null, body: source, error: 'unterminated frontmatter block' };
|
|
54
|
+
}
|
|
55
|
+
const yamlBody = lines.slice(1, endIdx).join('\n');
|
|
56
|
+
const body = lines.slice(endIdx + 1).join('\n');
|
|
57
|
+
const parsed = parseSafeYaml(yamlBody);
|
|
58
|
+
if (!parsed.ok) {
|
|
59
|
+
return { frontmatter: null, body, error: parsed.error };
|
|
60
|
+
}
|
|
61
|
+
return { frontmatter: parsed.data, body };
|
|
62
|
+
}
|
|
63
|
+
export function parseSafeYaml(input) {
|
|
64
|
+
const lines = input.split(/\r?\n/);
|
|
65
|
+
if (lines.length > MAX_LINES) {
|
|
66
|
+
return { ok: false, error: 'yaml exceeds 1000-line cap' };
|
|
67
|
+
}
|
|
68
|
+
const data = {};
|
|
69
|
+
let i = 0;
|
|
70
|
+
while (i < lines.length) {
|
|
71
|
+
const rawLine = lines[i];
|
|
72
|
+
const line = rawLine.replace(/\s+$/, '');
|
|
73
|
+
if (!line.trim() || line.trim().startsWith('#')) {
|
|
74
|
+
i++;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
// Top-level: must start at column 0 with `key:` (no leading whitespace).
|
|
78
|
+
if (/^\s/.test(line)) {
|
|
79
|
+
return { ok: false, error: `unexpected indentation at line ${i + 1}` };
|
|
80
|
+
}
|
|
81
|
+
const colonIdx = line.indexOf(':');
|
|
82
|
+
if (colonIdx === -1) {
|
|
83
|
+
return { ok: false, error: `expected "key:" at line ${i + 1}` };
|
|
84
|
+
}
|
|
85
|
+
const key = line.slice(0, colonIdx).trim();
|
|
86
|
+
if (!/^[A-Za-z_][A-Za-z0-9_-]*$/.test(key)) {
|
|
87
|
+
return { ok: false, error: `invalid key "${key}" at line ${i + 1}` };
|
|
88
|
+
}
|
|
89
|
+
const rest = line.slice(colonIdx + 1).trim();
|
|
90
|
+
if (rest === '' || rest === '|' || rest === '>') {
|
|
91
|
+
// Block sequence or block scalar follows on indented lines.
|
|
92
|
+
const childLines = [];
|
|
93
|
+
let j = i + 1;
|
|
94
|
+
while (j < lines.length) {
|
|
95
|
+
const next = lines[j];
|
|
96
|
+
if (next.trim() === '' || next.startsWith(' ') || next.startsWith('\t') || next.startsWith('-')) {
|
|
97
|
+
childLines.push(next);
|
|
98
|
+
j++;
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// Detect block sequence by leading `-` (with optional indent).
|
|
105
|
+
const seqLines = childLines.filter((l) => /^\s*-\s+/.test(l));
|
|
106
|
+
if (seqLines.length > 0 && seqLines.length === childLines.filter((l) => l.trim()).length) {
|
|
107
|
+
const arr = [];
|
|
108
|
+
for (const sl of seqLines) {
|
|
109
|
+
const item = sl.replace(/^\s*-\s+/, '').trim();
|
|
110
|
+
const v = parseScalar(item);
|
|
111
|
+
if (typeof v !== 'string' && typeof v !== 'number' && typeof v !== 'boolean') {
|
|
112
|
+
return { ok: false, error: `unsupported sequence item at "${key}"` };
|
|
113
|
+
}
|
|
114
|
+
arr.push(String(v));
|
|
115
|
+
}
|
|
116
|
+
data[key] = arr;
|
|
117
|
+
}
|
|
118
|
+
else if (rest === '|' || rest === '>') {
|
|
119
|
+
// Block scalar: dedent shortest common leading whitespace.
|
|
120
|
+
const nonEmpty = childLines.filter((l) => l.trim().length > 0);
|
|
121
|
+
const indents = nonEmpty.map((l) => (l.match(/^\s*/)?.[0].length ?? 0));
|
|
122
|
+
const minIndent = indents.length > 0 ? Math.min(...indents) : 0;
|
|
123
|
+
const joined = nonEmpty.map((l) => l.slice(minIndent)).join(rest === '|' ? '\n' : ' ');
|
|
124
|
+
data[key] = joined;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
// No children → empty string / undefined behaviour: treat as empty string.
|
|
128
|
+
data[key] = '';
|
|
129
|
+
}
|
|
130
|
+
i = j;
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
const valueResult = parseInlineValue(rest);
|
|
134
|
+
if (!valueResult.ok) {
|
|
135
|
+
return { ok: false, error: `${valueResult.error} at line ${i + 1}` };
|
|
136
|
+
}
|
|
137
|
+
data[key] = valueResult.value;
|
|
138
|
+
i++;
|
|
139
|
+
}
|
|
140
|
+
return { ok: true, data };
|
|
141
|
+
}
|
|
142
|
+
function parseInlineValue(raw) {
|
|
143
|
+
const trimmed = raw.trim();
|
|
144
|
+
if (trimmed.startsWith('!')) {
|
|
145
|
+
return { ok: false, error: 'YAML tags are not permitted' };
|
|
146
|
+
}
|
|
147
|
+
if (trimmed.startsWith('&') || trimmed.startsWith('*')) {
|
|
148
|
+
return { ok: false, error: 'YAML anchors and aliases are not permitted' };
|
|
149
|
+
}
|
|
150
|
+
// Flow sequence [a, b, c]
|
|
151
|
+
if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
|
|
152
|
+
const inner = trimmed.slice(1, -1).trim();
|
|
153
|
+
if (inner === '')
|
|
154
|
+
return { ok: true, value: [] };
|
|
155
|
+
const parts = splitFlowList(inner);
|
|
156
|
+
const arr = [];
|
|
157
|
+
for (const p of parts) {
|
|
158
|
+
const v = parseScalar(p.trim());
|
|
159
|
+
arr.push(v);
|
|
160
|
+
}
|
|
161
|
+
return { ok: true, value: arr };
|
|
162
|
+
}
|
|
163
|
+
// Flow mapping {k: v} is not supported in our schema; reject to fail loud.
|
|
164
|
+
if (trimmed.startsWith('{')) {
|
|
165
|
+
return { ok: false, error: 'inline maps are not permitted' };
|
|
166
|
+
}
|
|
167
|
+
return { ok: true, value: parseScalar(trimmed) };
|
|
168
|
+
}
|
|
169
|
+
function splitFlowList(s) {
|
|
170
|
+
const out = [];
|
|
171
|
+
let depth = 0;
|
|
172
|
+
let inStr = null;
|
|
173
|
+
let cur = '';
|
|
174
|
+
for (const ch of s) {
|
|
175
|
+
if (inStr) {
|
|
176
|
+
cur += ch;
|
|
177
|
+
if (ch === inStr)
|
|
178
|
+
inStr = null;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (ch === '"' || ch === "'") {
|
|
182
|
+
inStr = ch;
|
|
183
|
+
cur += ch;
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
if (ch === '[' || ch === '{')
|
|
187
|
+
depth++;
|
|
188
|
+
else if (ch === ']' || ch === '}')
|
|
189
|
+
depth--;
|
|
190
|
+
if (ch === ',' && depth === 0) {
|
|
191
|
+
out.push(cur);
|
|
192
|
+
cur = '';
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
cur += ch;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (cur.trim().length > 0)
|
|
199
|
+
out.push(cur);
|
|
200
|
+
return out;
|
|
201
|
+
}
|
|
202
|
+
function parseScalar(raw) {
|
|
203
|
+
const s = raw.trim();
|
|
204
|
+
if (s === '')
|
|
205
|
+
return '';
|
|
206
|
+
if (s === 'null' || s === '~')
|
|
207
|
+
return null;
|
|
208
|
+
if (s === 'true' || s === 'True' || s === 'TRUE')
|
|
209
|
+
return true;
|
|
210
|
+
if (s === 'false' || s === 'False' || s === 'FALSE')
|
|
211
|
+
return false;
|
|
212
|
+
// Quoted strings (return raw, no escape processing — we don't need it for
|
|
213
|
+
// the project-scope schema).
|
|
214
|
+
if ((s.startsWith('"') && s.endsWith('"')) || (s.startsWith("'") && s.endsWith("'"))) {
|
|
215
|
+
return s.slice(1, -1);
|
|
216
|
+
}
|
|
217
|
+
// Number?
|
|
218
|
+
if (/^-?\d+$/.test(s)) {
|
|
219
|
+
const n = parseInt(s, 10);
|
|
220
|
+
if (Number.isSafeInteger(n))
|
|
221
|
+
return n;
|
|
222
|
+
}
|
|
223
|
+
if (/^-?\d+\.\d+$/.test(s)) {
|
|
224
|
+
const f = parseFloat(s);
|
|
225
|
+
if (Number.isFinite(f))
|
|
226
|
+
return f;
|
|
227
|
+
}
|
|
228
|
+
return s;
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=SafeYaml.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SafeYaml.js","sourceRoot":"","sources":["../../src/core/SafeYaml.ts"],"names":[],"mappings":"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"}
|
|
@@ -386,6 +386,18 @@ export declare class SessionManager extends EventEmitter {
|
|
|
386
386
|
* Used by injectMessage after provenance checks pass.
|
|
387
387
|
*/
|
|
388
388
|
private rawInject;
|
|
389
|
+
/**
|
|
390
|
+
* Verify an injection actually submitted by checking for a marker snippet
|
|
391
|
+
* still present at the ❯ prompt. On Claude Code v2.1.105+ fresh spawns, the
|
|
392
|
+
* Enter after bracketed-paste-end is occasionally eaten by a race with the
|
|
393
|
+
* paste-end sequence and the text sits unsubmitted forever. This guard
|
|
394
|
+
* sends one extra Enter if we detect the stuck state; single-shot, safe
|
|
395
|
+
* when the text did submit normally (no-op).
|
|
396
|
+
*
|
|
397
|
+
* Runs asynchronously — fires a background check after markerCheckMs and
|
|
398
|
+
* does not block the caller. Called from rawInject after Enter is sent.
|
|
399
|
+
*/
|
|
400
|
+
private verifyInjection;
|
|
389
401
|
/**
|
|
390
402
|
* Wait for Claude to be ready in a tmux session by polling output.
|
|
391
403
|
* Looks for Claude Code's prompt character (❯) which appears when ready for input.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionManager.d.ts","sourceRoot":"","sources":["../../src/core/SessionManager.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"SessionManager.d.ts","sourceRoot":"","sources":["../../src/core/SessionManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1713,6 +1713,12 @@ rm() { "${shimRunner}" rm "$@"; }
|
|
|
1713
1713
|
encoding: 'utf-8', timeout: 5000,
|
|
1714
1714
|
});
|
|
1715
1715
|
}
|
|
1716
|
+
// Verify Enter actually submitted — on fresh Claude Code TUIs (v2.1.105+)
|
|
1717
|
+
// the Enter after bracketed-paste-end is occasionally eaten, leaving the
|
|
1718
|
+
// text sitting in the input box unsubmitted. verifyInjection captures the
|
|
1719
|
+
// pane after a short delay and sends one extra Enter if the marker text
|
|
1720
|
+
// is still visible at the ❯ prompt.
|
|
1721
|
+
this.verifyInjection(tmuxSession, text);
|
|
1716
1722
|
return true;
|
|
1717
1723
|
}
|
|
1718
1724
|
catch (err) {
|
|
@@ -1743,6 +1749,60 @@ rm() { "${shimRunner}" rm "$@"; }
|
|
|
1743
1749
|
}
|
|
1744
1750
|
return false;
|
|
1745
1751
|
}
|
|
1752
|
+
/**
|
|
1753
|
+
* Verify an injection actually submitted by checking for a marker snippet
|
|
1754
|
+
* still present at the ❯ prompt. On Claude Code v2.1.105+ fresh spawns, the
|
|
1755
|
+
* Enter after bracketed-paste-end is occasionally eaten by a race with the
|
|
1756
|
+
* paste-end sequence and the text sits unsubmitted forever. This guard
|
|
1757
|
+
* sends one extra Enter if we detect the stuck state; single-shot, safe
|
|
1758
|
+
* when the text did submit normally (no-op).
|
|
1759
|
+
*
|
|
1760
|
+
* Runs asynchronously — fires a background check after markerCheckMs and
|
|
1761
|
+
* does not block the caller. Called from rawInject after Enter is sent.
|
|
1762
|
+
*/
|
|
1763
|
+
verifyInjection(tmuxSession, injectedText) {
|
|
1764
|
+
const markerCheckMs = 1500;
|
|
1765
|
+
// Extract a distinguishing first-40-chars marker from the injected text.
|
|
1766
|
+
// Strip leading whitespace/newlines so we match what's visible at the prompt.
|
|
1767
|
+
const marker = injectedText.replace(/^\s+/, '').slice(0, 40).trim();
|
|
1768
|
+
if (!marker || marker.length < 8)
|
|
1769
|
+
return; // too short to be a reliable marker
|
|
1770
|
+
setTimeout(() => {
|
|
1771
|
+
try {
|
|
1772
|
+
if (!this.tmuxSessionExists(tmuxSession))
|
|
1773
|
+
return;
|
|
1774
|
+
const pane = this.captureOutput(tmuxSession, 20) || '';
|
|
1775
|
+
// If the marker is still at a ❯ prompt line, Enter was eaten.
|
|
1776
|
+
// Check the pane has BOTH ❯ and the marker on the same line (or within 2 lines).
|
|
1777
|
+
const lines = pane.split('\n');
|
|
1778
|
+
let stuck = false;
|
|
1779
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1780
|
+
const line = lines[i];
|
|
1781
|
+
if (line.includes('❯') && (line.includes(marker) || (lines[i + 1] && lines[i + 1].includes(marker.slice(0, 30))))) {
|
|
1782
|
+
stuck = true;
|
|
1783
|
+
break;
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
if (stuck) {
|
|
1787
|
+
console.warn(`[SessionManager] Injection stuck in "${tmuxSession}" — marker "${marker.slice(0, 30)}…" still at prompt. Resending Enter.`);
|
|
1788
|
+
execFileSync(this.config.tmuxPath, ['send-keys', '-t', `=${tmuxSession}:`, 'Enter'], {
|
|
1789
|
+
encoding: 'utf-8', timeout: 5000,
|
|
1790
|
+
});
|
|
1791
|
+
DegradationReporter.getInstance().report({
|
|
1792
|
+
feature: 'SessionManager.verifyInjection',
|
|
1793
|
+
primary: 'Bracketed paste + Enter submits injected message',
|
|
1794
|
+
fallback: 'Auto-resent Enter after detecting stuck input',
|
|
1795
|
+
reason: 'Enter eaten by paste-end race on fresh Claude Code TUI',
|
|
1796
|
+
impact: 'Recovered without user intervention',
|
|
1797
|
+
});
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
catch (err) {
|
|
1801
|
+
// Best-effort — never throw from a background verification
|
|
1802
|
+
console.error(`[SessionManager] verifyInjection error for "${tmuxSession}": ${err instanceof Error ? err.message : err}`);
|
|
1803
|
+
}
|
|
1804
|
+
}, markerCheckMs);
|
|
1805
|
+
}
|
|
1746
1806
|
/**
|
|
1747
1807
|
* Wait for Claude to be ready in a tmux session by polling output.
|
|
1748
1808
|
* Looks for Claude Code's prompt character (❯) which appears when ready for input.
|