@webpresso/agent-kit 3.1.26 → 3.1.30
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/catalog/AGENTS.md.tpl +7 -11
- package/catalog/agent/commands/verify.md +2 -2
- package/catalog/agent/rules/changeset-release.md +4 -2
- package/catalog/agent/rules/ci-cost-local-first.md +139 -0
- package/catalog/agent/rules/ci-test-perf.md +5 -1
- package/catalog/agent/rules/cmd-execution.md +9 -0
- package/catalog/agent/rules/pre-implementation.md +2 -1
- package/catalog/agent/rules/test-scan-perf.md +80 -0
- package/catalog/agent/rules/workflow-skills-routing.md +9 -4
- package/catalog/agent/skills/autopilot/SKILL.md +48 -11
- package/catalog/agent/skills/claude/SKILL.md +7 -0
- package/catalog/agent/skills/codex/SKILL.md +7 -0
- package/catalog/agent/skills/fix/SKILL.md +36 -8
- package/catalog/agent/skills/grok/SKILL.md +7 -0
- package/catalog/agent/skills/investigate/SKILL.md +12 -1
- package/catalog/agent/skills/pll/SKILL.md +53 -48
- package/catalog/agent/skills/team/SKILL.md +26 -9
- package/catalog/agent/skills/ultragoal/SKILL.md +147 -19
- package/catalog/agent/skills/verify/SKILL.md +89 -51
- package/dist/esm/audit/blueprint-lifecycle-sql.d.ts +8 -0
- package/dist/esm/audit/blueprint-lifecycle-sql.js +25 -1
- package/dist/esm/audit/blueprint-pr-coverage.js +68 -7
- package/dist/esm/audit/registry.d.ts +4 -4
- package/dist/esm/audit/registry.js +3 -0
- package/dist/esm/audit/roadmap-links.js +6 -0
- package/dist/esm/audit/test-scan-perf.d.ts +18 -0
- package/dist/esm/audit/test-scan-perf.js +275 -0
- package/dist/esm/blueprint/lifecycle/engine.d.ts +9 -0
- package/dist/esm/blueprint/lifecycle/engine.js +53 -6
- package/dist/esm/blueprint/lifecycle/review-provenance.d.ts +6 -0
- package/dist/esm/blueprint/lifecycle/review-provenance.js +93 -12
- package/dist/esm/blueprint/markdown/helpers.js +6 -2
- package/dist/esm/ci/act-replay.js +110 -7
- package/dist/esm/ci/act-runner.d.ts +4 -0
- package/dist/esm/ci/act-runner.js +85 -26
- package/dist/esm/ci/act-worktree-git.d.ts +11 -0
- package/dist/esm/ci/act-worktree-git.js +219 -0
- package/dist/esm/ci/native-session-memory-cache.d.ts +9 -1
- package/dist/esm/ci/native-session-memory-cache.js +9 -1
- package/dist/esm/ci/vitest-ci-shards.d.ts +6 -4
- package/dist/esm/ci/vitest-ci-shards.js +6 -4
- package/dist/esm/cli/auto-update/guard-tombstone.d.ts +25 -0
- package/dist/esm/cli/auto-update/guard-tombstone.js +67 -0
- package/dist/esm/cli/auto-update/installer.d.ts +4 -17
- package/dist/esm/cli/auto-update/installer.js +6 -57
- package/dist/esm/cli/auto-update/self-invocation.d.ts +37 -0
- package/dist/esm/cli/auto-update/self-invocation.js +62 -0
- package/dist/esm/cli/commands/audit.js +4 -0
- package/dist/esm/cli/commands/blueprint/mutations.js +35 -18
- package/dist/esm/cli/commands/blueprint/router.js +27 -2
- package/dist/esm/cli/commands/ci.d.ts +8 -1
- package/dist/esm/cli/commands/ci.js +80 -21
- package/dist/esm/cli/commands/dash/index.js +3 -3
- package/dist/esm/cli/commands/dash/keymap.js +1 -0
- package/dist/esm/cli/commands/dash/launch-preferences.d.ts +15 -0
- package/dist/esm/cli/commands/dash/launch-preferences.js +46 -17
- package/dist/esm/cli/commands/dash/plan-once-attention.d.ts +32 -0
- package/dist/esm/cli/commands/dash/plan-once-attention.js +50 -0
- package/dist/esm/cli/commands/dash/plan-once-label.d.ts +7 -0
- package/dist/esm/cli/commands/dash/plan-once-label.js +5 -0
- package/dist/esm/cli/commands/dash/plan-once-membership.d.ts +67 -0
- package/dist/esm/cli/commands/dash/plan-once-membership.js +151 -0
- package/dist/esm/cli/commands/dash/plan-once-merge.d.ts +143 -0
- package/dist/esm/cli/commands/dash/plan-once-merge.js +238 -0
- package/dist/esm/cli/commands/dash/plan-once-schema.d.ts +73 -0
- package/dist/esm/cli/commands/dash/plan-once-schema.js +119 -0
- package/dist/esm/cli/commands/dash/plan-once.d.ts +142 -0
- package/dist/esm/cli/commands/dash/plan-once.js +261 -0
- package/dist/esm/cli/commands/dash/tui/attention-hud.d.ts +9 -0
- package/dist/esm/cli/commands/dash/tui/attention-hud.js +9 -0
- package/dist/esm/cli/commands/dash/tui/chat-bridge.d.ts +41 -0
- package/dist/esm/cli/commands/dash/tui/chat-bridge.js +73 -0
- package/dist/esm/cli/commands/dash/tui/chat-mode.d.ts +47 -0
- package/dist/esm/cli/commands/dash/tui/chat-mode.js +98 -0
- package/dist/esm/cli/commands/dash/tui/frame.d.ts +3 -0
- package/dist/esm/cli/commands/dash/tui/frame.js +3 -1
- package/dist/esm/cli/commands/dash/tui/ipc-protocol.d.ts +87 -0
- package/dist/esm/cli/commands/dash/tui/ipc-protocol.js +128 -0
- package/dist/esm/cli/commands/dash/tui/native-host.d.ts +34 -0
- package/dist/esm/cli/commands/dash/tui/native-host.js +256 -0
- package/dist/esm/cli/commands/dash/tui/native-path.d.ts +11 -0
- package/dist/esm/cli/commands/dash/tui/native-path.js +41 -0
- package/dist/esm/cli/commands/dash/tui/palette.d.ts +1 -1
- package/dist/esm/cli/commands/dash/tui/palette.js +14 -0
- package/dist/esm/cli/commands/dash/tui/runtime.js +311 -4
- package/dist/esm/cli/commands/dash/tui/state.d.ts +41 -0
- package/dist/esm/cli/commands/dash/tui/state.js +257 -4
- package/dist/esm/cli/commands/format.js +0 -2
- package/dist/esm/cli/commands/init/config.d.ts +0 -1
- package/dist/esm/cli/commands/init/config.js +1 -4
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/emitters/claude.d.ts +5 -6
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/emitters/claude.js +6 -13
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/ir.d.ts +0 -2
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/ir.js +0 -2
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/merge.d.ts +6 -3
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/merge.js +39 -26
- package/dist/esm/cli/commands/init/scaffolders/agent-kit-global/index.js +1 -1
- package/dist/esm/cli/commands/init/scaffolders/codex-mcp/index.js +61 -23
- package/dist/esm/cli/commands/logs.d.ts +15 -0
- package/dist/esm/cli/commands/logs.js +192 -3
- package/dist/esm/cli/commands/package-manager.js +2 -1
- package/dist/esm/cli/commands/quality-log-store.d.ts +1 -0
- package/dist/esm/cli/commands/quality-log-store.js +187 -51
- package/dist/esm/cli/commands/review.js +5 -8
- package/dist/esm/cli/commands/secrets.d.ts +1 -0
- package/dist/esm/cli/commands/secrets.js +4 -1
- package/dist/esm/cli/commands/self-install-guard.d.ts +14 -32
- package/dist/esm/cli/commands/self-install-guard.js +17 -63
- package/dist/esm/cli/direct-provider-launch.js +25 -1
- package/dist/esm/hooks/doctor.d.ts +15 -0
- package/dist/esm/hooks/doctor.js +56 -0
- package/dist/esm/hooks/guard-switch/index.js +8 -4
- package/dist/esm/hooks/post-tool/lint-after-edit.js +6 -4
- package/dist/esm/hooks/precompact/index.js +5 -3
- package/dist/esm/hooks/pretool-guard/validators/forbidden-commands.js +4 -4
- package/dist/esm/hooks/pretool-guard/validators/mcp-redirect.d.ts +0 -1
- package/dist/esm/hooks/pretool-guard/validators/mcp-redirect.js +8 -5
- package/dist/esm/hooks/pretool-guard/validators/worktree-discipline.d.ts +9 -7
- package/dist/esm/hooks/pretool-guard/validators/worktree-discipline.js +126 -14
- package/dist/esm/hooks/sessionstart/index.d.ts +10 -0
- package/dist/esm/hooks/sessionstart/index.js +61 -4
- package/dist/esm/hooks/shared/types.d.ts +11 -0
- package/dist/esm/hooks/shared/types.js +21 -0
- package/dist/esm/mcp/tools/_shared/audit-kinds.d.ts +1 -1
- package/dist/esm/mcp/tools/audit.d.ts +2 -1
- package/dist/esm/mcp/tools/audit.js +10 -0
- package/dist/esm/mcp/tools/audits.d.ts +1 -0
- package/dist/esm/mcp/tools/ci-act.js +9 -11
- package/dist/esm/paths/state-root.js +9 -0
- package/dist/esm/review/authority.js +17 -2
- package/dist/esm/review/availability.js +18 -5
- package/dist/esm/review/subject.d.ts +15 -0
- package/dist/esm/review/subject.js +105 -10
- package/dist/esm/runtime/executor.d.ts +1 -0
- package/dist/esm/runtime/executor.js +2 -1
- package/dist/esm/secret-gate/runner.d.ts +1 -0
- package/dist/esm/secret-gate/runner.js +4 -1
- package/dist/esm/session-memory/current-session.js +2 -0
- package/dist/esm/session-memory/native-runtime.js +5 -3
- package/dist/esm/session-memory/native-warm-markers.d.ts +18 -0
- package/dist/esm/session-memory/native-warm-markers.js +22 -0
- package/dist/esm/session-memory/sync/types.d.ts +4 -0
- package/dist/esm/session-memory/types.d.ts +3 -1
- package/dist/esm/session-memory/types.js +2 -0
- package/dist/esm/ultragoal/runtime.js +44 -2
- package/dist/esm/worktrees/current.d.ts +1 -0
- package/dist/esm/worktrees/current.js +1 -0
- package/dist/esm/worktrees/project-agent-surfaces.d.ts +1 -0
- package/dist/esm/worktrees/project-agent-surfaces.js +2 -1
- package/package.json +17 -14
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export declare const MCP_AUDIT_KINDS: readonly ["test-smells", "tph-e2e", "agents", "catalog-drift", "package-surface", "reference-parity-matrix", "docs-frontmatter", "blueprint-readme-drift", "blueprint-pr-coverage", "blueprint-lifecycle", "blueprint-trust", "architecture-drift", "cloudflare-deploy-contract", "absolute-path-policy", "no-first-party-mjs", "no-math-random", "roadmap-links", "bundle-budget", "commit-message", "tech-debt", "supported-agent-clis", "hook-surface", "harness-surfaces", "weakness-mining", "harness-overlay-evidence", "ai-contracts", "atomic-state-writes", "no-relative-package-scripts", "toolchain-isolation", "open-source-licenses", "secrets-policy", "no-dev-vars", "github-actions-secrets", "secret-provider-quarantine", "security-quality-regressions", "secrets-config", "consumer-agent-kit-dependency", "ci-test-perf", "session-memory-hardcut", "worktree-main-ownership", "sast"];
|
|
1
|
+
export declare const MCP_AUDIT_KINDS: readonly ["test-smells", "tph-e2e", "agents", "catalog-drift", "package-surface", "reference-parity-matrix", "docs-frontmatter", "blueprint-readme-drift", "blueprint-pr-coverage", "blueprint-lifecycle", "blueprint-trust", "architecture-drift", "cloudflare-deploy-contract", "absolute-path-policy", "no-first-party-mjs", "no-math-random", "roadmap-links", "bundle-budget", "commit-message", "tech-debt", "supported-agent-clis", "hook-surface", "harness-surfaces", "weakness-mining", "harness-overlay-evidence", "ai-contracts", "atomic-state-writes", "no-relative-package-scripts", "toolchain-isolation", "open-source-licenses", "secrets-policy", "no-dev-vars", "github-actions-secrets", "secret-provider-quarantine", "security-quality-regressions", "secrets-config", "consumer-agent-kit-dependency", "ci-test-perf", "test-scan-perf", "session-memory-hardcut", "worktree-main-ownership", "sast"];
|
|
2
2
|
export type MCPAuditKind = (typeof MCP_AUDIT_KINDS)[number];
|
|
3
3
|
export declare function isMCPAuditKind(value: string): value is MCPAuditKind;
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { z } from "zod";
|
|
17
17
|
import type { ToolDescriptor } from "#mcp/auto-discover";
|
|
18
|
-
export declare const KINDS: readonly ["test-smells", "tph-e2e", "agents", "catalog-drift", "package-surface", "reference-parity-matrix", "docs-frontmatter", "blueprint-readme-drift", "blueprint-pr-coverage", "blueprint-lifecycle", "blueprint-trust", "architecture-drift", "cloudflare-deploy-contract", "absolute-path-policy", "no-first-party-mjs", "no-math-random", "roadmap-links", "bundle-budget", "commit-message", "tech-debt", "supported-agent-clis", "hook-surface", "harness-surfaces", "weakness-mining", "harness-overlay-evidence", "ai-contracts", "atomic-state-writes", "no-relative-package-scripts", "toolchain-isolation", "open-source-licenses", "secrets-policy", "no-dev-vars", "github-actions-secrets", "secret-provider-quarantine", "security-quality-regressions", "secrets-config", "consumer-agent-kit-dependency", "ci-test-perf", "session-memory-hardcut", "worktree-main-ownership", "sast"];
|
|
18
|
+
export declare const KINDS: readonly ["test-smells", "tph-e2e", "agents", "catalog-drift", "package-surface", "reference-parity-matrix", "docs-frontmatter", "blueprint-readme-drift", "blueprint-pr-coverage", "blueprint-lifecycle", "blueprint-trust", "architecture-drift", "cloudflare-deploy-contract", "absolute-path-policy", "no-first-party-mjs", "no-math-random", "roadmap-links", "bundle-budget", "commit-message", "tech-debt", "supported-agent-clis", "hook-surface", "harness-surfaces", "weakness-mining", "harness-overlay-evidence", "ai-contracts", "atomic-state-writes", "no-relative-package-scripts", "toolchain-isolation", "open-source-licenses", "secrets-policy", "no-dev-vars", "github-actions-secrets", "secret-provider-quarantine", "security-quality-regressions", "secrets-config", "consumer-agent-kit-dependency", "ci-test-perf", "test-scan-perf", "session-memory-hardcut", "worktree-main-ownership", "sast"];
|
|
19
19
|
export declare const inputSchema: z.ZodObject<{
|
|
20
20
|
kind: z.ZodEnum<{
|
|
21
21
|
"absolute-path-policy": "absolute-path-policy";
|
|
@@ -54,6 +54,7 @@ export declare const inputSchema: z.ZodObject<{
|
|
|
54
54
|
"session-memory-hardcut": "session-memory-hardcut";
|
|
55
55
|
"supported-agent-clis": "supported-agent-clis";
|
|
56
56
|
"tech-debt": "tech-debt";
|
|
57
|
+
"test-scan-perf": "test-scan-perf";
|
|
57
58
|
"test-smells": "test-smells";
|
|
58
59
|
"toolchain-isolation": "toolchain-isolation";
|
|
59
60
|
"tph-e2e": "tph-e2e";
|
|
@@ -464,6 +464,16 @@ export async function dispatchAudit(input) {
|
|
|
464
464
|
details: auditResult,
|
|
465
465
|
};
|
|
466
466
|
}
|
|
467
|
+
case "test-scan-perf": {
|
|
468
|
+
const { auditTestScanPerf } = await import("#audit/test-scan-perf");
|
|
469
|
+
const auditResult = auditTestScanPerf(input.cwd ?? input.directory ?? process.cwd());
|
|
470
|
+
return {
|
|
471
|
+
passed: auditResult.ok,
|
|
472
|
+
summary: summarizeRepoAudit(kind, auditResult),
|
|
473
|
+
kind,
|
|
474
|
+
details: auditResult,
|
|
475
|
+
};
|
|
476
|
+
}
|
|
467
477
|
case "hook-surface": {
|
|
468
478
|
const { auditHookSurface } = await import("#audit/hook-surface");
|
|
469
479
|
const auditResult = auditHookSurface(input.cwd ?? input.directory);
|
|
@@ -50,6 +50,7 @@ declare const inputSchema: z.ZodObject<{
|
|
|
50
50
|
"session-memory-hardcut": "session-memory-hardcut";
|
|
51
51
|
"supported-agent-clis": "supported-agent-clis";
|
|
52
52
|
"tech-debt": "tech-debt";
|
|
53
|
+
"test-scan-perf": "test-scan-perf";
|
|
53
54
|
"test-smells": "test-smells";
|
|
54
55
|
"toolchain-isolation": "toolchain-isolation";
|
|
55
56
|
"tph-e2e": "tph-e2e";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { DEFAULT_CI_ACT_TIMEOUT_MS, MAX_CI_ACT_TIMEOUT_MS } from "#cli/commands/ci";
|
|
3
|
-
import { buildPublicCiActCommand, preparePublicCiActExecution, resolveCiActExecutionMode, resolveCiActSecretEnvProfile, sanitizePublicCiActArgv, } from "#ci/act-runner.js";
|
|
2
|
+
import { DEFAULT_CI_ACT_TIMEOUT_MS, MAX_CI_ACT_TIMEOUT_MS, SMOKE_CI_ACT_TIMEOUT_MS, } from "#cli/commands/ci";
|
|
3
|
+
import { buildPublicCiActCommand, preparePublicCiActExecution, resolveCiActExecutionMode, resolveCiActSecretEnvProfile, sanitizePublicCiActArgv, shouldForceCiActSecretGate, } from "#ci/act-runner.js";
|
|
4
4
|
import { isSecretGateRuntimeProfile, runSecretGateCommand } from "#secret-gate/runner.js";
|
|
5
5
|
import { clipRawOutput, createSummaryOutputSchema, createSummaryResult } from "./_shared/result.js";
|
|
6
6
|
import { resolveProjectRoot } from "./_shared/project-root.js";
|
|
@@ -10,6 +10,7 @@ const inputSchema = z
|
|
|
10
10
|
cwd: z.string().optional(),
|
|
11
11
|
workflowPath: z.string(),
|
|
12
12
|
job: z.string().optional(),
|
|
13
|
+
matrix: z.array(z.string()).optional().default([]),
|
|
13
14
|
eventName: z
|
|
14
15
|
.enum(["pull_request", "push", "workflow_dispatch"])
|
|
15
16
|
.optional()
|
|
@@ -24,13 +25,8 @@ const inputSchema = z
|
|
|
24
25
|
}),
|
|
25
26
|
secretProfile: z.string().optional(),
|
|
26
27
|
mode: z.enum(["direct", "replay"]).optional().default("direct"),
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
.int()
|
|
30
|
-
.positive()
|
|
31
|
-
.max(MAX_CI_ACT_TIMEOUT_MS)
|
|
32
|
-
.optional()
|
|
33
|
-
.default(DEFAULT_CI_ACT_TIMEOUT_MS),
|
|
28
|
+
smoke: z.boolean().optional().default(false),
|
|
29
|
+
timeoutMs: z.number().int().positive().max(MAX_CI_ACT_TIMEOUT_MS).optional(),
|
|
34
30
|
containerArchitecture: z.string().optional(),
|
|
35
31
|
platformImage: z.string().optional().default("ghcr.io/catthehacker/ubuntu:full-latest"),
|
|
36
32
|
execute: z.boolean().optional().default(false),
|
|
@@ -96,6 +92,7 @@ const tool = {
|
|
|
96
92
|
handler: async (raw, extra) => {
|
|
97
93
|
const input = inputSchema.parse(raw ?? {});
|
|
98
94
|
const cwd = resolveProjectRoot(input.cwd ? { cwd: input.cwd } : {});
|
|
95
|
+
const timeoutMs = input.timeoutMs ?? (input.smoke ? SMOKE_CI_ACT_TIMEOUT_MS : DEFAULT_CI_ACT_TIMEOUT_MS);
|
|
99
96
|
if (!input.execute) {
|
|
100
97
|
return createSummaryResult({
|
|
101
98
|
passed: true,
|
|
@@ -108,13 +105,14 @@ const tool = {
|
|
|
108
105
|
const secretProfile = resolveCiActSecretEnvProfile({ ...input, cwd }) ?? "preview";
|
|
109
106
|
const result = await runSecretGateCommand({
|
|
110
107
|
cwd,
|
|
108
|
+
commandCwd: prepared.cwd,
|
|
111
109
|
sink: "act",
|
|
112
110
|
profile: secretProfile,
|
|
113
111
|
envProfile: input.envProfile,
|
|
114
|
-
forceSecretGate:
|
|
112
|
+
forceSecretGate: shouldForceCiActSecretGate(input.envProfile),
|
|
115
113
|
command: "act",
|
|
116
114
|
args: prepared.command.actArgs,
|
|
117
|
-
timeoutMs
|
|
115
|
+
timeoutMs,
|
|
118
116
|
signal: extra?.signal,
|
|
119
117
|
});
|
|
120
118
|
const merged = [result.stdout, result.stderr].filter(Boolean).join("\n");
|
|
@@ -72,6 +72,12 @@ function sha256Hex(value) {
|
|
|
72
72
|
* Probe whether a directory can hold state files.
|
|
73
73
|
* Used so quality CLIs (wp audit/test/…) keep working in sandboxes that
|
|
74
74
|
* deny writes under Application Support (e.g. Codex outside-voice).
|
|
75
|
+
*
|
|
76
|
+
* Any probe failure means the root is not usable (permission, ENOSPC, bad
|
|
77
|
+
* path, …). That is intentionally broader than `createCliLogSink`, which only
|
|
78
|
+
* remaps EPERM/EACCES/EROFS so unexpected IO errors stay loud at the log layer.
|
|
79
|
+
* A failed preferred env-paths root falls back once and is memoized for the
|
|
80
|
+
* process; set `WP_STATE_ROOT` to pin an explicit location instead.
|
|
75
81
|
*/
|
|
76
82
|
function canWriteStateRoot(root) {
|
|
77
83
|
try {
|
|
@@ -241,6 +247,9 @@ export async function getSurfacePathAsync(name, scope, cwd = resolveCwd()) {
|
|
|
241
247
|
export async function withLock(scope, fn, cwd) {
|
|
242
248
|
const lockTarget = await getSurfacePathAsync(".lock", scope, cwd);
|
|
243
249
|
mkdirSync(dirname(lockTarget), { recursive: true });
|
|
250
|
+
// Keep retries short so lock-contention probes (review gate contender tests)
|
|
251
|
+
// still fail closed in a few seconds. Dual-writer create loops retry at the
|
|
252
|
+
// call site when they need longer budgets under CI load.
|
|
244
253
|
const release = await lockfile.lock(lockTarget, {
|
|
245
254
|
realpath: false,
|
|
246
255
|
retries: { retries: 5, minTimeout: 50, maxTimeout: 500, factor: 2 },
|
|
@@ -9,7 +9,7 @@ import { createHash } from "node:crypto";
|
|
|
9
9
|
import { existsSync, lstatSync, readFileSync } from "node:fs";
|
|
10
10
|
import path from "node:path";
|
|
11
11
|
import { evaluateReviewEvents, parseReviewEventLog } from "./events.js";
|
|
12
|
-
import { createDeliverySubjectAtRef, createPlanSubjectAtRef, resolveReviewCommit, } from "./subject.js";
|
|
12
|
+
import { createDeliverySubjectAtRef, createLegacyPlanSubjectAtRef, createPlanSubjectAtRef, resolveReviewCommit, } from "./subject.js";
|
|
13
13
|
const GIT_TIMEOUT_MS = 5_000;
|
|
14
14
|
const GIT_MAX_BUFFER_BYTES = 128 * 1024 * 1024;
|
|
15
15
|
const REGULAR_MODE_PATTERN = /^100(?:644|755)$/u;
|
|
@@ -126,12 +126,27 @@ export function readReviewAuthorityAtRef(cwd, ref, stableSlug, purpose) {
|
|
|
126
126
|
const subject = purpose === "plan"
|
|
127
127
|
? createPlanSubjectAtRef(cwd, commit, stableSlug, overview.path)
|
|
128
128
|
: createDeliverySubjectAtRef(cwd, commit, stableSlug, overview.path);
|
|
129
|
-
|
|
129
|
+
let evaluation = evaluateReviewEvents(events, {
|
|
130
130
|
purpose,
|
|
131
131
|
blueprintSlug: stableSlug,
|
|
132
132
|
subjectScheme: subject.scheme,
|
|
133
133
|
subjectDigest: subject.digest,
|
|
134
134
|
}, compromisedIds);
|
|
135
|
+
if (purpose === "plan" && evaluation.approvals.length === 0) {
|
|
136
|
+
// Digest-compatibility fallback: events recorded before the lifecycle
|
|
137
|
+
// stripped-key extension bound their subjectDigest to the legacy
|
|
138
|
+
// normalization. Accept those for the same tracked content; new events
|
|
139
|
+
// always record the current digest (see legacyNormalizePlanSubjectContent).
|
|
140
|
+
const legacySubject = createLegacyPlanSubjectAtRef(cwd, commit, stableSlug, overview.path);
|
|
141
|
+
if (legacySubject.digest !== subject.digest) {
|
|
142
|
+
evaluation = evaluateReviewEvents(events, {
|
|
143
|
+
purpose,
|
|
144
|
+
blueprintSlug: stableSlug,
|
|
145
|
+
subjectScheme: legacySubject.scheme,
|
|
146
|
+
subjectDigest: legacySubject.digest,
|
|
147
|
+
}, compromisedIds);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
135
150
|
return {
|
|
136
151
|
commit,
|
|
137
152
|
blueprintPath: overview.path,
|
|
@@ -3,11 +3,7 @@ import path from "node:path";
|
|
|
3
3
|
import { NotInGitRepoError, withLock } from "#paths/state-root.js";
|
|
4
4
|
import { writeJsonFileAtomic } from "#shared-utils/write-json-file.js";
|
|
5
5
|
export const REVIEW_AVAILABILITY_SCHEMA_VERSION = 1;
|
|
6
|
-
const FAILURE_CLASSIFICATIONS = new Set([
|
|
7
|
-
"provider-limit-reached",
|
|
8
|
-
"provider-unavailable",
|
|
9
|
-
"provider-failed",
|
|
10
|
-
]);
|
|
6
|
+
const FAILURE_CLASSIFICATIONS = new Set(["provider-limit-reached", "provider-unavailable"]);
|
|
11
7
|
const SUCCESS_CLASSIFICATIONS = new Set([
|
|
12
8
|
"complete",
|
|
13
9
|
"approved",
|
|
@@ -117,6 +113,10 @@ export function saveReviewAvailability(projectRoot, state) {
|
|
|
117
113
|
function shouldSuppress(event) {
|
|
118
114
|
return FAILURE_CLASSIFICATIONS.has(event.terminalClassification);
|
|
119
115
|
}
|
|
116
|
+
function suppressedRecordStillApplies(record) {
|
|
117
|
+
return (record.terminalClassification !== undefined &&
|
|
118
|
+
FAILURE_CLASSIFICATIONS.has(record.terminalClassification));
|
|
119
|
+
}
|
|
120
120
|
function isAvailabilitySuccess(event) {
|
|
121
121
|
return SUCCESS_CLASSIFICATIONS.has(event.terminalClassification);
|
|
122
122
|
}
|
|
@@ -155,6 +155,15 @@ function nextRecord(previous, event, input) {
|
|
|
155
155
|
const success = isAvailabilitySuccess(event);
|
|
156
156
|
if (!input.suppress) {
|
|
157
157
|
const preserveSuppression = !success && previous?.suppressed === true;
|
|
158
|
+
if (preserveSuppression) {
|
|
159
|
+
return {
|
|
160
|
+
...previous,
|
|
161
|
+
...(event.model ? { lastModel: event.model } : {}),
|
|
162
|
+
...(event.effort ? { lastEffort: event.effort } : {}),
|
|
163
|
+
...(event.stage ? { lastStage: event.stage } : {}),
|
|
164
|
+
suppressed: true,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
158
167
|
return {
|
|
159
168
|
...common,
|
|
160
169
|
...(success
|
|
@@ -244,6 +253,10 @@ export function suppressedReviewers(state) {
|
|
|
244
253
|
export function pruneExpiredAvailabilitySuppressions(state, nowMs = Date.now()) {
|
|
245
254
|
const pruned = [];
|
|
246
255
|
const pruneMap = (records) => Object.fromEntries(Object.entries(records).map(([key, record]) => {
|
|
256
|
+
if (record.suppressed && !suppressedRecordStillApplies(record)) {
|
|
257
|
+
pruned.push(key);
|
|
258
|
+
return [key, { ...record, suppressed: false }];
|
|
259
|
+
}
|
|
247
260
|
if (record.suppressed &&
|
|
248
261
|
record.retryAfterMs !== undefined &&
|
|
249
262
|
record.lastFailureAt !== undefined) {
|
|
@@ -18,7 +18,22 @@ declare function updateField(hash: Hash, value: Buffer | string): void;
|
|
|
18
18
|
export declare function createDeliverySubjectAtRef(cwd: string, ref: string, blueprintSlug: string, blueprintPath?: string): ReviewSubject;
|
|
19
19
|
export declare function createSourceSubjectAtRef(cwd: string, ref: string): ReviewSubject;
|
|
20
20
|
export declare function normalizePlanSubjectContent(content: Buffer | string): Buffer;
|
|
21
|
+
/**
|
|
22
|
+
* Plan-subject digest for in-memory (working-tree) blueprint content. Used to
|
|
23
|
+
* accept working-ledger review events that digest-bind the exact bytes being
|
|
24
|
+
* committed (pre-commit runs before those events reach any git ref).
|
|
25
|
+
*/
|
|
26
|
+
export declare function createPlanSubjectDigestForContent(blueprintSlug: string, content: Buffer | string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Digest-compatibility variant for review events recorded before the
|
|
29
|
+
* stripped-key extension of `neutralizeLifecycleFrontmatter`. Verification
|
|
30
|
+
* accepts a match against either normalization; new digests always use
|
|
31
|
+
* `normalizePlanSubjectContent`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function legacyNormalizePlanSubjectContent(content: Buffer | string): Buffer;
|
|
21
34
|
export declare function createPlanSubjectAtRef(cwd: string, ref: string, blueprintSlug: string, blueprintPath?: string): ReviewSubject;
|
|
35
|
+
/** Plan subject digested with the pre-extension normalization (see above). */
|
|
36
|
+
export declare function createLegacyPlanSubjectAtRef(cwd: string, ref: string, blueprintSlug: string, blueprintPath?: string): ReviewSubject;
|
|
22
37
|
export declare const reviewSubjectInternals: {
|
|
23
38
|
isExcludedReviewEnvelope: typeof isExcludedReviewEnvelope;
|
|
24
39
|
isReviewEvidencePath: typeof isReviewEvidencePath;
|
|
@@ -255,12 +255,39 @@ function neutralizePromotionGateResults(text) {
|
|
|
255
255
|
}
|
|
256
256
|
return lines.join("\n");
|
|
257
257
|
}
|
|
258
|
-
//
|
|
259
|
-
//
|
|
258
|
+
// Frontmatter keys removed wholesale by the normalizer (value + folded
|
|
259
|
+
// continuation lines). Each mirrors exactly one lifecycle writer:
|
|
260
|
+
// `completed_at` (upsertCompletedAt) and the `wp blueprint start` /
|
|
261
|
+
// progress-stamp fields (setBlueprintFrontmatterFields lifecycle intents).
|
|
262
|
+
const PLAN_LIFECYCLE_STRIPPED_KEYS = [
|
|
263
|
+
"completed_at",
|
|
264
|
+
"last_updated",
|
|
265
|
+
"progress",
|
|
266
|
+
"worktree_owner_id",
|
|
267
|
+
"worktree_owner_branch",
|
|
268
|
+
];
|
|
269
|
+
// Neutralize the lifecycle-owned frontmatter fields (`status:` value plus the
|
|
270
|
+
// stripped keys above) INSIDE the leading frontmatter block only. A body line
|
|
260
271
|
// that merely looks like one of these (e.g. task text reading
|
|
261
272
|
// "completed_at: must remain unset until release") is plan substance and must
|
|
262
|
-
// keep affecting the digest.
|
|
273
|
+
// keep affecting the digest. Stripping removes the key line and any indented
|
|
274
|
+
// continuation lines so folded (`>-`) values normalize away too.
|
|
263
275
|
function neutralizeLifecycleFrontmatter(text) {
|
|
276
|
+
const match = /^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/u.exec(text);
|
|
277
|
+
if (!match)
|
|
278
|
+
return text;
|
|
279
|
+
let frontmatter = match[0];
|
|
280
|
+
frontmatter = frontmatter.replace(/^(status:\s*)(['"]?)[^'"\r\n]+?(['"]?)(\s*)$/m, `$1${PLAN_STATUS_PLACEHOLDER}$4`);
|
|
281
|
+
for (const key of PLAN_LIFECYCLE_STRIPPED_KEYS) {
|
|
282
|
+
frontmatter = frontmatter.replace(new RegExp(String.raw `^${key}:[^\n]*\n?(?:[ \t]+[^\n]*\n?)*`, "gmu"), "");
|
|
283
|
+
}
|
|
284
|
+
return `${frontmatter}${text.slice(match[0].length)}`;
|
|
285
|
+
}
|
|
286
|
+
// The pre-extension normalizer (status + completed_at only). Review events
|
|
287
|
+
// recorded before the stripped-key extension bound their subjectDigest to this
|
|
288
|
+
// normalization; verification accepts either digest so committed approvals are
|
|
289
|
+
// not stranded by the rollout. New events always record the current digest.
|
|
290
|
+
function legacyNeutralizeLifecycleFrontmatter(text) {
|
|
264
291
|
const match = /^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/u.exec(text);
|
|
265
292
|
if (!match)
|
|
266
293
|
return text;
|
|
@@ -305,21 +332,85 @@ function neutralizeReadinessStamps(text) {
|
|
|
305
332
|
// NO_CODE_CHANGE / GitLab patch-id semantics: approvals are re-derivable from
|
|
306
333
|
// substance-only digests, not carried). Each rule mirrors exactly one
|
|
307
334
|
// lifecycle writer, scoped to the location that writer owns:
|
|
308
|
-
// - frontmatter
|
|
309
|
-
// - frontmatter `completed_at:` line
|
|
335
|
+
// - frontmatter status/progress/owner fields (blueprint lifecycle mutations)
|
|
336
|
+
// - frontmatter `completed_at:` line (upsertCompletedAt)
|
|
310
337
|
// - Readiness Verdict `- verified-at:`/`- verified-head:` items (upsertReadinessValue)
|
|
311
338
|
// - Promotion Gates "Last result" cells (updateGateLastResult)
|
|
312
339
|
// Any other byte change — task text, acceptance criteria, scope, lookalike
|
|
313
340
|
// lines outside the owned locations — still changes the digest and dismisses
|
|
314
341
|
// prior plan approvals.
|
|
342
|
+
const PLAN_TASK_STATUS_PLACEHOLDER = "__wp-task-status__";
|
|
343
|
+
// Neutralize the task-execution state the lifecycle engine writes
|
|
344
|
+
// (updateTaskStatus, applyVerification): `**Status:** <status>` lines,
|
|
345
|
+
// acceptance checkbox marks, and `**Verification:**` +
|
|
346
|
+
// ```webpresso-evidence-v1 fenced evidence blocks. Task execution is lifecycle
|
|
347
|
+
// state, not plan substance — without this, the engine's own task_verify /
|
|
348
|
+
// finalize writes dismiss the plan approval and no completion commit can ever
|
|
349
|
+
// carry authority. Acceptance-criteria TEXT stays substance; only the check
|
|
350
|
+
// mark is neutralized.
|
|
351
|
+
function neutralizeTaskExecutionState(text) {
|
|
352
|
+
const lines = text.split("\n");
|
|
353
|
+
const out = [];
|
|
354
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
355
|
+
const line = lines[index];
|
|
356
|
+
if (/^\*\*Verification:\*\*\s*$/u.test(line)) {
|
|
357
|
+
// Skip the writer-owned block: "**Verification:**", blank(s), the
|
|
358
|
+
// evidence fence, and one trailing blank line.
|
|
359
|
+
let cursor = index + 1;
|
|
360
|
+
while (cursor < lines.length && lines[cursor].trim() === "")
|
|
361
|
+
cursor += 1;
|
|
362
|
+
if (/^```webpresso-evidence-v1\s*$/u.test(lines[cursor] ?? "")) {
|
|
363
|
+
cursor += 1;
|
|
364
|
+
while (cursor < lines.length && !/^```\s*$/u.test(lines[cursor]))
|
|
365
|
+
cursor += 1;
|
|
366
|
+
cursor += 1; // closing fence
|
|
367
|
+
if ((lines[cursor] ?? "").trim() === "")
|
|
368
|
+
cursor += 1;
|
|
369
|
+
index = cursor - 1;
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
if (/^\*\*Status:\*\* (?:todo|in-progress|blocked|done|dropped)\s*$/u.test(line)) {
|
|
374
|
+
out.push(`**Status:** ${PLAN_TASK_STATUS_PLACEHOLDER}`);
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
out.push(line.replace(/^(\s*)- \[[xX ]\] /u, "$1- [_] "));
|
|
378
|
+
}
|
|
379
|
+
return out.join("\n");
|
|
380
|
+
}
|
|
315
381
|
export function normalizePlanSubjectContent(content) {
|
|
316
382
|
let text = typeof content === "string" ? content : content.toString("utf8");
|
|
317
383
|
text = neutralizeLifecycleFrontmatter(text);
|
|
318
384
|
text = neutralizeReadinessStamps(text);
|
|
319
385
|
text = neutralizePromotionGateResults(text);
|
|
386
|
+
text = neutralizeTaskExecutionState(text);
|
|
320
387
|
return Buffer.from(text, "utf8");
|
|
321
388
|
}
|
|
322
|
-
|
|
389
|
+
/**
|
|
390
|
+
* Plan-subject digest for in-memory (working-tree) blueprint content. Used to
|
|
391
|
+
* accept working-ledger review events that digest-bind the exact bytes being
|
|
392
|
+
* committed (pre-commit runs before those events reach any git ref).
|
|
393
|
+
*/
|
|
394
|
+
export function createPlanSubjectDigestForContent(blueprintSlug, content) {
|
|
395
|
+
const hash = createHash("sha256").update(PLAN_DOMAIN);
|
|
396
|
+
updateField(hash, blueprintSlug);
|
|
397
|
+
updateField(hash, normalizePlanSubjectContent(content));
|
|
398
|
+
return hash.digest("hex");
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Digest-compatibility variant for review events recorded before the
|
|
402
|
+
* stripped-key extension of `neutralizeLifecycleFrontmatter`. Verification
|
|
403
|
+
* accepts a match against either normalization; new digests always use
|
|
404
|
+
* `normalizePlanSubjectContent`.
|
|
405
|
+
*/
|
|
406
|
+
export function legacyNormalizePlanSubjectContent(content) {
|
|
407
|
+
let text = typeof content === "string" ? content : content.toString("utf8");
|
|
408
|
+
text = legacyNeutralizeLifecycleFrontmatter(text);
|
|
409
|
+
text = neutralizeReadinessStamps(text);
|
|
410
|
+
text = neutralizePromotionGateResults(text);
|
|
411
|
+
return Buffer.from(text, "utf8");
|
|
412
|
+
}
|
|
413
|
+
function planSubjectAtRef(cwd, ref, blueprintSlug, normalize, blueprintPath) {
|
|
323
414
|
const commit = resolveReviewCommit(cwd, ref);
|
|
324
415
|
const entries = parseTree(cwd, commit);
|
|
325
416
|
const blueprintRoot = findBlueprintRoot(entries, blueprintSlug, blueprintPath);
|
|
@@ -333,10 +424,7 @@ export function createPlanSubjectAtRef(cwd, ref, blueprintSlug, blueprintPath) {
|
|
|
333
424
|
throw new Error("Tracked blueprint overview content is unavailable.");
|
|
334
425
|
const hash = createHash("sha256").update(PLAN_DOMAIN);
|
|
335
426
|
updateField(hash, blueprintSlug);
|
|
336
|
-
|
|
337
|
-
// safe pre-merge: no committed review-events.jsonl exists anywhere, so no
|
|
338
|
-
// recorded plan digest can break.
|
|
339
|
-
updateField(hash, normalizePlanSubjectContent(content));
|
|
427
|
+
updateField(hash, normalize(content));
|
|
340
428
|
return {
|
|
341
429
|
scheme: "wp-blueprint-v1",
|
|
342
430
|
digest: hash.digest("hex"),
|
|
@@ -344,6 +432,13 @@ export function createPlanSubjectAtRef(cwd, ref, blueprintSlug, blueprintPath) {
|
|
|
344
432
|
files: [overviewPath.toString("utf8")],
|
|
345
433
|
};
|
|
346
434
|
}
|
|
435
|
+
export function createPlanSubjectAtRef(cwd, ref, blueprintSlug, blueprintPath) {
|
|
436
|
+
return planSubjectAtRef(cwd, ref, blueprintSlug, normalizePlanSubjectContent, blueprintPath);
|
|
437
|
+
}
|
|
438
|
+
/** Plan subject digested with the pre-extension normalization (see above). */
|
|
439
|
+
export function createLegacyPlanSubjectAtRef(cwd, ref, blueprintSlug, blueprintPath) {
|
|
440
|
+
return planSubjectAtRef(cwd, ref, blueprintSlug, legacyNormalizePlanSubjectContent, blueprintPath);
|
|
441
|
+
}
|
|
347
442
|
export const reviewSubjectInternals = {
|
|
348
443
|
isExcludedReviewEnvelope,
|
|
349
444
|
isReviewEvidencePath,
|
|
@@ -14,6 +14,7 @@ export interface ResolveRuntimeEnvironmentOptions {
|
|
|
14
14
|
}
|
|
15
15
|
export interface RuntimeSpawnOptions {
|
|
16
16
|
readonly cwd?: string;
|
|
17
|
+
readonly envCwd?: string;
|
|
17
18
|
readonly profile?: RuntimeSelector;
|
|
18
19
|
readonly secretProfile?: string;
|
|
19
20
|
readonly environment?: string;
|
|
@@ -82,9 +82,10 @@ export function resolveRuntimeEnvironment(options = {}) {
|
|
|
82
82
|
}
|
|
83
83
|
export function buildRuntimeSpawnOptions(options = {}) {
|
|
84
84
|
const cwd = options.cwd ?? process.cwd();
|
|
85
|
+
const envCwd = options.envCwd ?? cwd;
|
|
85
86
|
const cache = options.cache ?? createRuntimeEnvCache();
|
|
86
87
|
const resolvedEnv = resolveRuntimeEnvironment({
|
|
87
|
-
cwd,
|
|
88
|
+
cwd: envCwd,
|
|
88
89
|
profile: options.profile,
|
|
89
90
|
secretProfile: options.secretProfile,
|
|
90
91
|
environment: options.environment,
|
|
@@ -11,6 +11,7 @@ export interface SecretGateCommandOptions {
|
|
|
11
11
|
readonly command: string;
|
|
12
12
|
readonly args?: readonly string[];
|
|
13
13
|
readonly cwd?: string;
|
|
14
|
+
readonly commandCwd?: string;
|
|
14
15
|
readonly timeoutMs?: number;
|
|
15
16
|
readonly signal?: AbortSignal;
|
|
16
17
|
readonly forceSecretGate?: boolean;
|
|
@@ -35,6 +35,7 @@ export function buildSecretGateCommand(options) {
|
|
|
35
35
|
sink,
|
|
36
36
|
"--profile",
|
|
37
37
|
profile,
|
|
38
|
+
...(options.commandCwd ? ["--command-cwd", options.commandCwd] : []),
|
|
38
39
|
"--",
|
|
39
40
|
options.command,
|
|
40
41
|
...(options.args ?? []),
|
|
@@ -45,9 +46,11 @@ export function runSecretGateCommand(options) {
|
|
|
45
46
|
const timeoutMs = options.timeoutMs ?? 30_000;
|
|
46
47
|
const maxOutputBytes = options.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES;
|
|
47
48
|
const command = buildSecretGateCommand(options);
|
|
49
|
+
const runsInnerCommandDirectly = command.command === options.command;
|
|
50
|
+
const spawnCwd = runsInnerCommandDirectly && options.commandCwd ? options.commandCwd : options.cwd;
|
|
48
51
|
return new Promise((resolve) => {
|
|
49
52
|
const child = spawn(command.command, [...command.args], {
|
|
50
|
-
cwd:
|
|
53
|
+
cwd: spawnCwd,
|
|
51
54
|
env: buildRuntimeProcessEnv(options.cwd, process.env),
|
|
52
55
|
detached: process.platform !== "win32",
|
|
53
56
|
});
|
|
@@ -23,6 +23,8 @@ const LIVE_SESSION_ENV_KEYS = [
|
|
|
23
23
|
"CLAUDE_SESSION_ID",
|
|
24
24
|
"CLAUDE_CODE_SESSION_ID",
|
|
25
25
|
"OPENCODE_SESSION_ID",
|
|
26
|
+
// Grok Build: hook processes always get this; tool children may in future builds.
|
|
27
|
+
"GROK_SESSION_ID",
|
|
26
28
|
"RUNTIME_SESSION_ID",
|
|
27
29
|
];
|
|
28
30
|
export function readLiveSessionIdFromEnv(env) {
|
|
@@ -9,6 +9,7 @@ import envPaths from "env-paths";
|
|
|
9
9
|
import lockfile from "proper-lockfile";
|
|
10
10
|
import { resolveAgentKitPackageRoot } from "#cli/commands/init/package-root.js";
|
|
11
11
|
import { SESSION_MEMORY_NATIVE_ADDON_FILENAME, resolveSessionMemoryNativeTarget, } from "./native-targets.js";
|
|
12
|
+
import { NATIVE_WARM_LOG_CORRUPT_REBUILD, NATIVE_WARM_LOG_HIT, NATIVE_WARM_LOG_REBUILD, } from "./native-warm-markers.js";
|
|
12
13
|
const requireFromHere = createRequire(import.meta.url);
|
|
13
14
|
const NATIVE_WORKSPACE_DIRNAME = join("native", "session-memory-engine");
|
|
14
15
|
const BUILD_PACKAGE = "session-memory-napi";
|
|
@@ -240,12 +241,12 @@ function ensureNativeModuleBuilt(options = {}) {
|
|
|
240
241
|
const nodePath = compiledNodePath();
|
|
241
242
|
const force = options.force === true;
|
|
242
243
|
if (!force && !shouldRebuildNativeSessionMemoryNode(nodePath, workspaceRoot)) {
|
|
243
|
-
console.log(`[native-session-memory]
|
|
244
|
+
console.log(`[native-session-memory] ${NATIVE_WARM_LOG_HIT}${nodePath} trust=${trustCachedNativeNode() ? "1" : "0"}`);
|
|
244
245
|
return nodePath;
|
|
245
246
|
}
|
|
246
247
|
return withNativeBuildLock(sessionMemoryNativeCacheRoot(), () => {
|
|
247
248
|
if (!force && !shouldRebuildNativeSessionMemoryNode(nodePath, workspaceRoot)) {
|
|
248
|
-
console.log(`[native-session-memory]
|
|
249
|
+
console.log(`[native-session-memory] ${NATIVE_WARM_LOG_HIT}${nodePath} trust=${trustCachedNativeNode() ? "1" : "0"}`);
|
|
249
250
|
return nodePath;
|
|
250
251
|
}
|
|
251
252
|
if (force && existsSync(nodePath)) {
|
|
@@ -256,7 +257,8 @@ function ensureNativeModuleBuilt(options = {}) {
|
|
|
256
257
|
// Best-effort: cargo rebuild overwrites via copyFileSync below.
|
|
257
258
|
}
|
|
258
259
|
}
|
|
259
|
-
|
|
260
|
+
const warmMarker = force ? NATIVE_WARM_LOG_CORRUPT_REBUILD : NATIVE_WARM_LOG_REBUILD;
|
|
261
|
+
console.log(`[native-session-memory] ${warmMarker}${nodePath} trust=${trustCachedNativeNode() ? "1" : "0"}`);
|
|
260
262
|
const targetDir = cargoTargetDir();
|
|
261
263
|
mkdirSync(targetDir, { recursive: true });
|
|
262
264
|
try {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grep-stable warm-path log markers for the session-memory native warm step.
|
|
3
|
+
*
|
|
4
|
+
* Emitted by `native-runtime` and classified by the Test job E1 summary greps
|
|
5
|
+
* in `.github/workflows/ci.agent-kit.yml`. YAML cannot import TS — contract
|
|
6
|
+
* tests in `src/ci/native-session-memory-cache.test.ts` pin that the workflow
|
|
7
|
+
* greps these exact substrings.
|
|
8
|
+
*
|
|
9
|
+
* Rename only with a coordinated workflow + contract-test update.
|
|
10
|
+
*/
|
|
11
|
+
/** Exact-hit warm log marker (`grep -q` target + runtime emit prefix). */
|
|
12
|
+
export declare const NATIVE_WARM_LOG_HIT = "warm=hit path=";
|
|
13
|
+
/** Source/mtime rebuild warm log marker. */
|
|
14
|
+
export declare const NATIVE_WARM_LOG_REBUILD = "warm=rebuild path=";
|
|
15
|
+
/** Forced corrupt-node rebuild warm log marker. */
|
|
16
|
+
export declare const NATIVE_WARM_LOG_CORRUPT_REBUILD = "warm=corrupt-rebuild path=";
|
|
17
|
+
/** All E1-classified warm markers (corrupt-rebuild → hit → rebuild order matches workflow). */
|
|
18
|
+
export declare const NATIVE_WARM_LOG_MARKERS: readonly ["warm=corrupt-rebuild path=", "warm=hit path=", "warm=rebuild path="];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grep-stable warm-path log markers for the session-memory native warm step.
|
|
3
|
+
*
|
|
4
|
+
* Emitted by `native-runtime` and classified by the Test job E1 summary greps
|
|
5
|
+
* in `.github/workflows/ci.agent-kit.yml`. YAML cannot import TS — contract
|
|
6
|
+
* tests in `src/ci/native-session-memory-cache.test.ts` pin that the workflow
|
|
7
|
+
* greps these exact substrings.
|
|
8
|
+
*
|
|
9
|
+
* Rename only with a coordinated workflow + contract-test update.
|
|
10
|
+
*/
|
|
11
|
+
/** Exact-hit warm log marker (`grep -q` target + runtime emit prefix). */
|
|
12
|
+
export const NATIVE_WARM_LOG_HIT = "warm=hit path=";
|
|
13
|
+
/** Source/mtime rebuild warm log marker. */
|
|
14
|
+
export const NATIVE_WARM_LOG_REBUILD = "warm=rebuild path=";
|
|
15
|
+
/** Forced corrupt-node rebuild warm log marker. */
|
|
16
|
+
export const NATIVE_WARM_LOG_CORRUPT_REBUILD = "warm=corrupt-rebuild path=";
|
|
17
|
+
/** All E1-classified warm markers (corrupt-rebuild → hit → rebuild order matches workflow). */
|
|
18
|
+
export const NATIVE_WARM_LOG_MARKERS = [
|
|
19
|
+
NATIVE_WARM_LOG_CORRUPT_REBUILD,
|
|
20
|
+
NATIVE_WARM_LOG_HIT,
|
|
21
|
+
NATIVE_WARM_LOG_REBUILD,
|
|
22
|
+
];
|
|
@@ -48,6 +48,7 @@ export declare const shareContinuityEventV1: z.ZodObject<{
|
|
|
48
48
|
helper_waiting: "helper_waiting";
|
|
49
49
|
rejected_approach: "rejected_approach";
|
|
50
50
|
rule_snapshot: "rule_snapshot";
|
|
51
|
+
session_identity: "session_identity";
|
|
51
52
|
tool_command: "tool_command";
|
|
52
53
|
tool_edit: "tool_edit";
|
|
53
54
|
tool_read: "tool_read";
|
|
@@ -81,6 +82,7 @@ export declare const shareAgentRunDeltaV1: z.ZodObject<{
|
|
|
81
82
|
helper_waiting: "helper_waiting";
|
|
82
83
|
rejected_approach: "rejected_approach";
|
|
83
84
|
rule_snapshot: "rule_snapshot";
|
|
85
|
+
session_identity: "session_identity";
|
|
84
86
|
tool_command: "tool_command";
|
|
85
87
|
tool_edit: "tool_edit";
|
|
86
88
|
tool_read: "tool_read";
|
|
@@ -119,6 +121,7 @@ export declare const localAgentRunDeltaEnvelopeV1: z.ZodObject<{
|
|
|
119
121
|
helper_waiting: "helper_waiting";
|
|
120
122
|
rejected_approach: "rejected_approach";
|
|
121
123
|
rule_snapshot: "rule_snapshot";
|
|
124
|
+
session_identity: "session_identity";
|
|
122
125
|
tool_command: "tool_command";
|
|
123
126
|
tool_edit: "tool_edit";
|
|
124
127
|
tool_read: "tool_read";
|
|
@@ -155,6 +158,7 @@ export declare const sessionShareEnvelopeV1: z.ZodObject<{
|
|
|
155
158
|
helper_waiting: "helper_waiting";
|
|
156
159
|
rejected_approach: "rejected_approach";
|
|
157
160
|
rule_snapshot: "rule_snapshot";
|
|
161
|
+
session_identity: "session_identity";
|
|
158
162
|
tool_command: "tool_command";
|
|
159
163
|
tool_edit: "tool_edit";
|
|
160
164
|
tool_read: "tool_read";
|
|
@@ -23,7 +23,9 @@ export interface SessionMemorySearchResult extends IndexedSessionMemoryChunk {
|
|
|
23
23
|
score: number;
|
|
24
24
|
tier: "porter" | "trigram" | "levenshtein";
|
|
25
25
|
}
|
|
26
|
-
export declare const SESSION_CONTINUITY_EVENT_TYPES: readonly ["user_prompt", "decision", "constraint", "tool_read", "tool_edit", "tool_command", "failure", "rejected_approach", "assistant_turn_summary", "compaction_boundary", "rule_snapshot",
|
|
26
|
+
export declare const SESSION_CONTINUITY_EVENT_TYPES: readonly ["user_prompt", "decision", "constraint", "tool_read", "tool_edit", "tool_command", "failure", "rejected_approach", "assistant_turn_summary", "compaction_boundary", "rule_snapshot",
|
|
27
|
+
/** SessionStart seed so `wp session-info` can resolve a real host session id. */
|
|
28
|
+
"session_identity", "helper_selected", "helper_started", "helper_waiting", "helper_completed", "helper_failed", "helper_returned"];
|
|
27
29
|
export type SessionContinuityEventType = (typeof SESSION_CONTINUITY_EVENT_TYPES)[number];
|
|
28
30
|
/**
|
|
29
31
|
* Optional dashboard identity carried in continuity-event metadata. It keeps
|
|
@@ -10,6 +10,8 @@ export const SESSION_CONTINUITY_EVENT_TYPES = [
|
|
|
10
10
|
"assistant_turn_summary",
|
|
11
11
|
"compaction_boundary",
|
|
12
12
|
"rule_snapshot",
|
|
13
|
+
/** SessionStart seed so `wp session-info` can resolve a real host session id. */
|
|
14
|
+
"session_identity",
|
|
13
15
|
"helper_selected",
|
|
14
16
|
"helper_started",
|
|
15
17
|
"helper_waiting",
|