sync: update from private repo (402599f)
CI / build-and-test (push) Has been cancelled

This commit is contained in:
oss-sync
2026-06-04 13:41:33 +00:00
parent 57685d995c
commit c526adddc2
28 changed files with 2092 additions and 2727 deletions
+5 -5
View File
@@ -574,7 +574,7 @@ describe('executeMovement parallel tool execution', () => {
expect(markerMessages.length).toBeGreaterThanOrEqual(1);
});
it('force-transitions to defaultNext when initial prompt is oversized and defaultNext is set', async () => {
it('aborts when initial prompt is oversized and defaultNext is terminal', async () => {
const { ContextManager } = await import('./context-manager.js');
const cm = new ContextManager({ limitTokens: 1_000 });
@@ -594,10 +594,10 @@ describe('executeMovement parallel tool execution', () => {
{ contextManager: cm },
);
// makeMovement defaultNext is 'COMPLETE' so we force-transition there
expect(result.next).toBe('COMPLETE');
expect(result.output).toContain('Context overflow');
expect(result.lessons).toContain('Context overflow');
// A terminal fallback would report a false completion, so overflow aborts.
expect(result.next).toBe('ABORT');
expect(result.abortCode).toBe('context_overflow');
expect(result.output).toContain('LLM request blocked before send');
// Only the isolated summary call should have happened — no main LLM call
expect(executeToolMock).not.toHaveBeenCalled();
});
+1 -8
View File
@@ -1,7 +1,7 @@
import { execFileSync } from 'child_process';
import { tmpdir } from 'os';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'fs';
import { existsSync as existsSyncEvents, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'fs';
import { join } from 'path';
import type { MovementResult } from './agent-loop.js';
import type { PieceDef } from './piece-runner.js';
@@ -521,15 +521,9 @@ describe('buildFollowupNotice (option C)', () => {
// Traceability T-2 — handoff / delta / followup / context_action
// ============================================================
import { runPiece } from './piece-runner.js';
import { readFileSync } from 'fs';
import { createFileEventLogger, parseEventLine, type EventBase } from '../progress/event-log.js';
import type { OpenAICompatClient, LLMEvent } from '../llm/openai-compat.js';
vi.mock('./agent-loop.js', () => ({
executeMovement: vi.fn(),
}));
function readAllEvents(workspacePath: string): EventBase[] {
const path = join(workspacePath, 'logs', 'events.jsonl');
if (!existsSyncEvents(path)) return [];
@@ -541,7 +535,6 @@ function readAllEvents(workspacePath: string): EventBase[] {
});
}
import { existsSync as existsSyncEvents } from 'fs';
describe('Traceability T-2: piece-runner emission for subtask boundary + followup', () => {
let workspace: string;
+9 -14
View File
@@ -5,6 +5,14 @@ import { mkdtempSync, rmSync, mkdirSync, writeFileSync, readFileSync, existsSync
import { tmpdir } from 'os';
import { join } from 'path';
import matter from 'gray-matter';
// This mock is intentionally file-wide. vi.mock is hoisted, so keeping it at
// top level makes the actual test behavior explicit and Vitest 4 compatible.
vi.mock('child_process', () => ({
execSync: () => {
throw new Error('git: command not found');
},
}));
// ---- helpers ----------------------------------------------------------------
@@ -134,21 +142,8 @@ describe('silentFork', () => {
});
});
// ---- git-unavailable suite (isolated via vi.mock) ---------------------------
//
// vi.mock hoisting means this mock is set up before any import of the module
// under test, making execSync throw unconditionally for this describe block.
// ---- git-unavailable suite --------------------------------------------------
describe('silentFork — git unavailable', () => {
// Hoist the mock so it applies before the module is evaluated.
vi.mock('child_process', () => {
return {
execSync: () => {
throw new Error('git: command not found');
},
};
});
let dir: string;
let builtinDir: string;
let dataDir: string;
+9 -2
View File
@@ -143,6 +143,13 @@ function isBlockedDocsSubpath(relFromDocs: string): boolean {
});
}
function sanitizeListedDescription(description: string): string {
const referencesInternalDoc = BLOCKED_DOCS_SUBPATHS.some((blocked) =>
description.includes(blocked.replace(/\/$/, '')),
);
return referencesInternalDoc ? '(description omitted: internal reference)' : description;
}
/**
* Map a symbolic doc name to a concrete file path under an allow-listed root.
* Returns null on invalid names, attempted traversal, or blocked internal docs.
@@ -306,7 +313,7 @@ function extractMarkdownDescription(filePath: string): string {
}
if (line.startsWith('#')) continue;
// Use this line as description
return line.slice(0, 140);
return sanitizeListedDescription(line.slice(0, 140));
}
} catch {
// ignore
@@ -326,7 +333,7 @@ function extractPieceDescription(filePath: string): string {
.split('\n')
.map((s) => s.trim())
.find((s) => s.length > 0);
return (first ?? '(no description)').slice(0, 140);
return sanitizeListedDescription((first ?? '(no description)').slice(0, 140));
}
} catch {
// ignore
+3
View File
@@ -1,4 +1,5 @@
import * as dns from 'dns';
import { isIP } from 'node:net';
import { isPrivateOrForbidden } from '../../../net/ssrf-strict.js';
// These delegate to the hardened range check in src/net/ssrf-strict.ts so that
@@ -6,11 +7,13 @@ import { isPrivateOrForbidden } from '../../../net/ssrf-strict.js';
// loopback, RFC1918, link-local + cloud metadata (169.254/16, fd00:ec2::),
// CGNAT (100.64/10), 0.0.0.0/8, IPv4-mapped IPv6, NAT64, multicast, reserved.
export function isPrivateIPv4(ip: string): boolean {
if (isIP(ip) !== 4) return false;
return isPrivateOrForbidden(ip, 4);
}
export function isPrivateIPv6(ip: string): boolean {
const normalized = ip.toLowerCase().replace(/^\[|\]$/g, '');
if (isIP(normalized) !== 6) return false;
return isPrivateOrForbidden(normalized, 6);
}