Compare commits

...
Author SHA1 Message Date
morluto 11d295eeab Merge branch 'main' into fix/main-maintenance-ci-20261010 2026-10-14 03:09:00 +08:00
morluto 0d31902b7f fix(reference-source): refresh maintenance fixes against main 2026-10-14 02:29:20 +08:00
吴佳浩Alben ccc009412e fix: repair the static-check failures on the default branch (#2895)
* fix: repair the static-check failures on the default branch

The default branch fails its own required `Static checks` job three ways, so
every pull request reports that job as failed regardless of its own change.

- `npm run format:check` reports `src/domain/functionComparison.test.ts` and
  `src/ida/IdaOperationRunner.ts`.
- `npm run lint` reports a duplicate `import { join } from "node:path"` in
  `tests/boundary/mcp/ghidraInventoryMcp.test.ts` (lines 4 and 17).
- `npm run typecheck` reports `format: "devin"` missing from the client format
  union in `src/application/SupportedClients.ts`, and an unchecked index in
  `tests/boundary/cli/clientProfileLifecycle.test.ts`, whose pair array is
  inferred as `string[][]`.

Apply the pinned formatter, drop the duplicate import, list the `"devin"` format
that its own definition already uses, and mark the pair array `as const`.

Validation: `npm run check:fast` and `npm run format:check` pass.

* fix(setup): keep Devin on the JSON configuration dialect

---------

Co-authored-by: 吴佳浩 <wujiahao@supremind.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
(cherry picked from commit df3d96da80)
2026-10-14 01:15:17 +08:00
morluto 0d2bb5fb09 fix(android): make DEX descriptor pattern portable
(cherry picked from commit 1335bcddc5)
2026-10-14 01:15:04 +08:00
REA Maintenance 47dd84ea69 fix(ci): isolate Linux Hopper process fixture inventory
(cherry picked from commit 8cac51e121)
2026-10-14 01:15:04 +08:00
Lucien 4e829cea2f fix(comparison): recheck historical calls-only changes (#2223)
* fix(comparison): preserve incomplete function call evidence

Keep missing, unknown, partial and unresolved call relationships unknown in function comparisons and reconstruction claims. Aggregate IDA caller and callee coverage without overwriting uncertainty.

Validate with 144 focused tests, typecheck/lint, docs checks and test discovery. Real providers were not verified; the full headless IDA session suite requires unavailable Windows native controls.

* fix(comparison): recheck historical calls-only changes

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
(cherry picked from commit 688defca0f)
2026-10-14 01:15:04 +08:00
morluto bf30b081db fix: reconcile captured main and owned findings for PR #1603 2026-10-13 23:02:19 +08:00
morluto 15efa61149 style: format reviewed source changes 2026-10-13 20:36:55 +08:00
morluto 70435de2c6 chore: merge latest main after source review 2026-10-13 20:29:41 +08:00
morluto 1b3371ad7f fix(ci): reconcile Git ownership and preserve portable checks 2026-10-13 20:11:02 +08:00
N0zoM1z0 c7fdd7e153 test(artifacts): share ASAR member fixture setup 2026-10-11 03:54:57 +08:00
N0zoM1z0 3c794a5cc0 Merge commit '5100a1a1a56b810c8246b8c7ed19ff42c4d9dbe1' into fix/ci-duplicate-boundaries-1603 2026-10-11 03:50:21 +08:00
N0zoM1z0 16caa5ca9b chore(ci): refresh maintenance checks against current main 2026-10-11 03:44:06 +08:00
N0zoM1z0 2a6bef5589 chore(ci): include current snapshot and runtime repairs 2026-10-11 01:50:32 +08:00
N0zoM1z0 cace19caad fix(ci): reconcile lifecycle checks with current main
Preserve failed event finalization across retries and current capture ownership checks. Retain Git unreadable-ref and bounded-heap Evidence coverage, pinned maintenance destinations, and explicit native binding facts.
2026-10-11 01:08:09 +08:00
N0zoM1z0 87b7bf8db1 fix(reference-source): distinguish Git API probes from failed reads 2026-10-10 16:59:30 +00:00
N0zoM1z0 3b66532e26 Merge commit '603d04ee3ac6ed496f84478164f832a9b5ce3b91' into fix/main-maintenance-ci-20261010
# Conflicts:
#	tests/process-global/updateMaintenance.test.ts
2026-10-10 16:36:42 +00:00
N0zoM1z0 3ad063b454 Merge remote-tracking branch 'origin/main' into fix/main-maintenance-ci-20261010 2026-10-10 16:34:18 +00:00
N0zoM1z0 69485e27f7 fix(ci): restore capture and maintenance regression checks 2026-10-10 16:34:17 +00:00
5 changed files with 103 additions and 27 deletions

No files matched your search

+12 -5
View File
@@ -162,14 +162,21 @@ const resolveSourceHead = async (
// The library probes readFile() without a path to detect promise APIs.
// Reject that invocation without attributing it to a source read.
if (path === undefined)
throw new TypeError("Git filesystem read requires a path");
throw new TypeError("Git metadata path is required");
try {
const bytes = await readMetadataBytes(path);
const encoding =
typeof options === "string" ? options : options?.encoding;
return encoding === undefined || encoding === null
? bytes
: bytes.toString(encoding);
typeof options === "string"
? options
: typeof options === "object" &&
options !== null &&
"encoding" in options
? options.encoding
: undefined;
if (encoding === undefined || encoding === null) return bytes;
if (typeof encoding !== "string" || !Buffer.isEncoding(encoding))
throw new TypeError("Unsupported Git metadata text encoding");
return bytes.toString(encoding);
} catch (cause: unknown) {
if (cause instanceof ArtifactReaderFailure) {
cleanupFailures.push(cause);
+20 -4
View File
@@ -8,14 +8,14 @@ import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import { cliTest } from "../../support/cli/cliFixture.js";
cliTest(
"rejects malformed oversized JSON through both CLI and Evidence readers",
"rejects malformed oversized input through CLI and Evidence readers",
async ({ cli, processes }) => {
const root = await createTestTempDirectory("rea-json-string-limit-");
const input = join(root, "oversized.json");
const file = await open(input, "wx");
try {
// Sparse zero bytes are valid UTF-8 but invalid JSON. Both readers
// stream the input and reject the syntax before assembling a value.
// Sparse zero bytes are valid UTF-8. Both streaming readers reject
// their invalid JSON syntax without assembling a whole-document string.
await file.truncate(constants.MAX_STRING_LENGTH + 1);
} finally {
await file.close();
@@ -175,7 +175,7 @@ cliTest(
cliTest(
"returns a typed string assembly constraint under a bounded heap",
async ({ cli }) => {
async ({ cli, processes }) => {
const root = await createTestTempDirectory("rea-json-string-headroom-");
const input = join(root, "long-string.json");
const file = await open(input, "wx");
@@ -207,5 +207,21 @@ cliTest(
action: expect.stringContaining("re-analyze a smaller selection"),
},
});
const evidence = await processes.run(process.execPath, [
"--max-old-space-size=768",
"--input-type=module",
"-e",
`import { readJsonFile } from "./dist/application/JsonFiles.js";
import { projectAnalysisError } from "./dist/domain/analysisErrorProjection.js";
const result = await readJsonFile(process.argv[1]);
console.log(JSON.stringify(result.ok ? result : projectAnalysisError(result.error)));`,
input,
]);
expect(JSON.parse(evidence.stdout)).toMatchObject({
code: "resource_constraint",
details: { operation: "read_evidence_file", resource: "memory" },
});
expect(evidence.stderr).toBe("");
expect(evidence.exitCode).toBe(0);
},
);
@@ -72,17 +72,8 @@ describe("static Electron application analysis", () => {
const result = await reconstructJavaScriptArtifact({ input_path: root });
const graph = parseJavaScriptApplicationGraph(result.graph);
// Computed access keeps no known members; the unknown access is an
// explicit dynamic flag rather than a "*" sentinel inside members.
const accesses = graph.nodes.flatMap((node) =>
node.kind === "native-export"
? node.observations.map(({ properties }) => ({
members: Array.isArray(properties.requested_members)
? properties.requested_members
: [],
dynamicMemberAccess: properties.dynamic_member_access ?? false,
}))
: [],
const nativeBindings = graph.nodes.filter(
(node) => node.kind === "native-export",
);
expect(result.electron_summary).toMatchObject({
@@ -90,7 +81,20 @@ describe("static Electron application analysis", () => {
native_addon_bindings: 1,
resolved_native_addon_bindings: 1,
});
expect(accesses).toEqual([{ members: [], dynamicMemberAccess: true }]);
expect(nativeBindings).toMatchObject([
{
observations: [
{
properties: {
requested_members: [],
namespace_access: false,
dynamic_member_access: true,
native_export_verification: "not-performed",
},
},
],
},
]);
});
it("maps Electron boundaries through bundler-renamed bindings", async () => {
@@ -1,4 +1,4 @@
import { mkdir, writeFile } from "node:fs/promises";
import { chmod, mkdir, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { expect, it } from "vitest";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
@@ -108,3 +108,33 @@ it("reads a linked worktree's own branch and detached HEAD through shared Git re
dirty: null,
});
});
it.skipIf(process.platform === "win32")(
"keeps unreadable loose refs unknown instead of falling back to packed refs",
async () => {
const root = await createTestTempDirectory("rea-reference-loose-ref-");
const gitdir = join(root, ".git");
const looseRef = join(gitdir, "refs", "heads", "main");
await mkdir(join(gitdir, "refs", "heads"), { recursive: true });
const head = "1234567890abcdef1234567890abcdef12345678";
await writeFile(join(gitdir, "HEAD"), "ref: refs/heads/main\n");
await writeFile(join(gitdir, "packed-refs"), `${head} refs/heads/main\n`);
expect(await readVcs(root)).toEqual({
kind: "git",
head,
dirty: null,
});
if (process.getuid?.() === 0) return;
await writeFile(looseRef, `${head}\n`);
await chmod(looseRef, 0);
try {
expect(await readVcs(root)).toEqual({
kind: "unknown",
head: null,
dirty: null,
});
} finally {
await chmod(looseRef, 0o600);
}
},
);
+24 -5
View File
@@ -319,6 +319,8 @@ describe("updated executable maintenance planning", () => {
it("runs real setup as a noninteractive dry run and creates no new integrations or backups", async () => {
const configPath = await writeClient("codex", staleCodex);
const untouched = await writeClient("claude_code", '{"mcpServers":{}}');
const skillContent = `---\nname: ${PRODUCT_IDENTITY.skillName}\nmetadata:\n version: "1"\n---\n# REA\n`;
const skillPath = await writeSkill(skillContent);
vi.stubEnv("npm_command", "exec");
const result = await planIntegrationMaintenance(
home,
@@ -328,18 +330,35 @@ describe("updated executable maintenance planning", () => {
);
expect(result).toMatchObject({
status: "planned",
scope: { clients: ["codex"], skill: false },
plannedActions: [
{ id: "configure_client:codex", kind: "configure_client" },
],
scope: {
clients: ["codex"],
skill: true,
skillDestinations: [{ client: "shared", path: dirname(skillPath) }],
},
});
if (result.status !== "planned") throw new Error(JSON.stringify(result));
expect(result.plannedActions).toEqual([
expect.objectContaining({
id: "configure_client:codex",
kind: "configure_client",
}),
expect.objectContaining({
id: "install_skill",
kind: "install_skill",
target: dirname(skillPath),
}),
]);
expect(await readFile(configPath, "utf8")).toBe(staleCodex);
expect(await readFile(untouched, "utf8")).toBe('{"mcpServers":{}}');
expect(await readFile(skillPath, "utf8")).toBe(skillContent);
await expect(access(`${configPath}.rea.backup`)).rejects.toMatchObject({
code: "ENOENT",
});
await expect(access(`${skillPath}.rea.backup`)).rejects.toMatchObject({
code: "ENOENT",
});
await expect(
access(join(home, ".agents", "skills", PRODUCT_IDENTITY.skillName)),
access(join(home, ".claude", "skills", PRODUCT_IDENTITY.skillName)),
).rejects.toMatchObject({ code: "ENOENT" });
});
});