Author SHA1 Message Date
forge-recovery ca2bc895fd Merge pull request 'fix(ci): add eslint, lockfile and tests for central CI' (#3) from ci/central-ci-repair-20261101 into develop
KofTwentyTwo/ci-policy: ci / source-config-9 (push) Skipped
KofTwentyTwo/ci-policy: ci / fork-guard (push) Skipped
KofTwentyTwo/ci-policy: native / native-result (push) Successful in 12s
KofTwentyTwo/ci-policy: ci / gradle-0 (push) Skipped
KofTwentyTwo/ci-policy: ci / java-docker-2 (push) Skipped
KofTwentyTwo/ci-policy: ci / not-enrolled (push) Skipped
KofTwentyTwo/ci-policy: ci / gradle-1 (push) Skipped
KofTwentyTwo/ci-policy: ci / manifests-4 (push) Skipped
KofTwentyTwo/ci-policy: Shared Node CI / gate (push) Successful in 23s
KofTwentyTwo/ci-policy: ci / java-maven-3 (push) Skipped
KofTwentyTwo/ci-policy: native / fork-deny (push) Skipped
KofTwentyTwo/ci-policy: ci / node-5 (push) Successful in 1m23s
KofTwentyTwo/ci-policy: native / dotnet-0 (push) Skipped
KofTwentyTwo/ci-policy: ci / ci-result (push) Successful in 10s
KofTwentyTwo/ci-policy: ci / rust-6 (push) Skipped
KofTwentyTwo/ci-policy: native / swift-1 (push) Skipped
KofTwentyTwo/ci-policy: ci / rust-7 (push) Skipped
KofTwentyTwo/ci-policy: Shared Node CI / secrets (push) Successful in 44s
KofTwentyTwo/ci-policy: native / swift-2 (push) Skipped
KofTwentyTwo/ci-policy: Shared Node CI / verify (push) Successful in 47s
KofTwentyTwo/ci-policy: ci / rust-8 (push) Skipped
KofTwentyTwo/ci-policy: native / swift-3 (push) Skipped
2026-11-01 19:56:09 +00:00
86646832e2 fix(ci): add eslint, lockfile and tests for central CI
KofTwentyTwo/ci-policy: ci / fork-guard (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / gradle-0 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / gradle-1 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / java-docker-2 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / java-maven-3 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / manifests-4 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / rust-6 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / rust-7 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / rust-8 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / source-config-9 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / not-enrolled (pull_request) Skipped
KofTwentyTwo/ci-policy: Shared Node CI / secrets (pull_request) Successful in 27s
KofTwentyTwo/ci-policy: Shared Node CI / verify (pull_request) Successful in 44s
KofTwentyTwo/ci-policy: Shared Node CI / gate (pull_request) Successful in 22s
KofTwentyTwo/ci-policy: ci / node-5 (pull_request) Successful in 1m9s
KofTwentyTwo/ci-policy: ci / ci-result (pull_request) Successful in 7s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

Co-Authored-By: Codex <noreply@openai.com>
2026-11-01 19:38:48 +00:00
9 changed files with 3225 additions and 7 deletions

No files matched your search

+32
View File
@@ -0,0 +1,32 @@
// ESLint flat config for the Jarvis File packages (`npm run lint` and each package's `lint` script).
// ESLint's recommended rules only: correctness checks, no layout rules. The Node packages are CommonJS;
// jarvis-file-core/js holds browser scripts that share globals through window.JF.
import js from "@eslint/js";
import globals from "globals";
export default [
{
ignores: ["**/node_modules/**", "**/dist/**", "**/coverage/**"],
},
js.configs.recommended,
{
rules: {
// An underscore prefix marks a binding kept for the planned implementation but not used yet.
"no-unused-vars": ["error", { argsIgnorePattern: "^_", varsIgnorePattern: "^_", caughtErrorsIgnorePattern: "^_" }],
},
},
{
files: ["**/*.js"],
languageOptions: {
sourceType: "commonjs",
globals: { ...globals.node },
},
},
{
files: ["packages/jarvis-file-core/js/**/*.js"],
languageOptions: {
sourceType: "script",
globals: { ...globals.browser },
},
},
];
+3073
View File
File diff suppressed because it is too large. Load diff
+6 -1
View File
@@ -20,5 +20,10 @@
"url": "git+https://github.com/KofTwentyTwo/jarvis-file.git"
},
"author": "KofTwentyTwo",
"license": "MIT"
"license": "MIT",
"devDependencies": {
"@eslint/js": "^10.0.1",
"eslint": "^10.14.0",
"globals": "^17.14.0"
}
}
@@ -0,0 +1,31 @@
"use strict";
const test = require("node:test");
const assert = require("node:assert/strict");
const { compileRules } = require("../lib/rules-compiler");
const config = {
auth: { allowedDomain: "example.com", ownerEmail: "owner@example.com" },
project: { slug: "acme" },
};
test("scopes every collection to the project slug", () => {
const rules = compileRules(config);
assert.match(rules, /match \/acme_comments\/\{commentId\}/);
assert.match(rules, /match \/acme_jarvis_chats\/\{chatId\}/);
});
test("restricts access to the allowed domain with the dots escaped", () => {
const rules = compileRules(config);
assert.match(rules, /matches\('\.\*@example\[\.\]com'\)/);
assert.doesNotMatch(rules, /@example\.com'\)/);
});
test("never allows deleting comments", () => {
assert.match(compileRules(config), /allow delete: if false;/);
});
test("fails loudly when the config has no auth section", () => {
assert.throws(() => compileRules({ project: { slug: "acme" } }), TypeError);
});
@@ -0,0 +1,39 @@
"use strict";
const test = require("node:test");
const assert = require("node:assert/strict");
const path = require("node:path");
const { resolveProjectDir } = require("../lib/validate-path");
test("resolves a simple name under the current working directory", () => {
assert.equal(resolveProjectDir("my-project"), process.cwd() + path.sep + "my-project");
});
test("trims surrounding whitespace", () => {
assert.equal(resolveProjectDir(" docs "), process.cwd() + path.sep + "docs");
});
test("rejects missing or non-string input", () => {
for (const bad of [undefined, null, "", 42, {}]) {
assert.throws(() => resolveProjectDir(bad), /required/);
}
});
test("rejects parent directory traversal", () => {
for (const bad of ["..", "../evil", "a/../b", "..\\evil"]) {
assert.throws(() => resolveProjectDir(bad), /Invalid project directory/);
}
});
test("rejects absolute paths", () => {
for (const bad of ["/etc", "\\windows"]) {
assert.throws(() => resolveProjectDir(bad), /Invalid project directory/);
}
});
test("rejects nested paths and invalid filesystem characters", () => {
for (const bad of ["a/b", "a\\b", "a:b", "a<b", "a|b", "a?b", "a*b", "a\0b"]) {
assert.throws(() => resolveProjectDir(bad), /Invalid project directory/);
}
});
@@ -15,7 +15,7 @@ const { initFirestore } = require("./lib/firestore");
async function main() {
const config = loadConfig();
const db = initFirestore(config);
const _db = initFirestore(config);
const crCollection = config.project.slug + "_change_requests";
+2 -2
View File
@@ -19,8 +19,8 @@ const { createClient } = require("./lib/anthropic");
async function main() {
const config = loadConfig();
const db = initFirestore(config);
const claude = createClient(config);
const _db = initFirestore(config);
const _claude = createClient(config);
const commentsCollection = config.project.slug + "_comments";
const chatCollection = config.project.slug + "_jarvis_chats";
@@ -12,11 +12,11 @@ const fs = require("fs");
/**
* Extract text content from a specific section of an HTML file.
* @param {string} htmlPath - Path to the HTML file
* @param {string} sectionId - Section identifier to extract
* @param {string} _htmlPath - Path to the HTML file
* @param {string} _sectionId - Section identifier to extract
* @returns {string} Plain text content of the section
*/
function extractSectionText(htmlPath, sectionId) {
function extractSectionText(_htmlPath, _sectionId) {
// TODO: Phase 1 -- implement HTML section text extraction
// Parse HTML, find section by data-section-id or heading,
// strip tags, return plain text for LLM context
@@ -0,0 +1,38 @@
"use strict";
const test = require("node:test");
const assert = require("node:assert/strict");
const fs = require("node:fs");
const os = require("node:os");
const path = require("node:path");
const { extractFullText } = require("../lib/context-reader");
function withTempFile(contents, run) {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "jarvis-context-"));
const file = path.join(dir, "doc.html");
fs.writeFileSync(file, contents);
try {
run(file);
} finally {
fs.rmSync(dir, { recursive: true, force: true });
}
}
test("strips tags, scripts and styles and normalizes whitespace", () => {
const html = "<html><style>p{color:red}</style><body><h1>Title</h1>\n<p>Some <b>bold</b> text</p>" +
"<script>alert(1)</script></body></html>";
withTempFile(html, (file) => {
assert.equal(extractFullText(file), "Title Some bold text");
});
});
test("decodes the common HTML entities", () => {
withTempFile("<p>R&amp;D &lt;draft&gt;&nbsp;done</p>", (file) => {
assert.equal(extractFullText(file), "R&D <draft> done");
});
});
test("returns an empty string for a file that does not exist", () => {
assert.equal(extractFullText(path.join(os.tmpdir(), "jarvis-no-such-file.html")), "");
});