openlore 2.0.1 → 2.0.3
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/README.md +57 -0
- package/dist/cli/commands/mcp.d.ts.map +1 -1
- package/dist/cli/commands/mcp.js +18 -1
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/export/index.d.ts +10 -0
- package/dist/cli/export/index.d.ts.map +1 -0
- package/dist/cli/export/index.js +27 -0
- package/dist/cli/export/index.js.map +1 -0
- package/dist/cli/export/scip.d.ts +22 -0
- package/dist/cli/export/scip.d.ts.map +1 -0
- package/dist/cli/export/scip.js +95 -0
- package/dist/cli/export/scip.js.map +1 -0
- package/dist/cli/index.js +19 -9
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/install/adapters/agents-md.d.ts +8 -0
- package/dist/cli/install/adapters/agents-md.d.ts.map +1 -0
- package/dist/cli/install/adapters/agents-md.js +21 -0
- package/dist/cli/install/adapters/agents-md.js.map +1 -0
- package/dist/cli/install/adapters/claude-code.d.ts +8 -0
- package/dist/cli/install/adapters/claude-code.d.ts.map +1 -0
- package/dist/cli/install/adapters/claude-code.js +184 -0
- package/dist/cli/install/adapters/claude-code.js.map +1 -0
- package/dist/cli/install/adapters/cline.d.ts +6 -0
- package/dist/cli/install/adapters/cline.d.ts.map +1 -0
- package/dist/cli/install/adapters/cline.js +19 -0
- package/dist/cli/install/adapters/cline.js.map +1 -0
- package/dist/cli/install/adapters/continue.d.ts +13 -0
- package/dist/cli/install/adapters/continue.d.ts.map +1 -0
- package/dist/cli/install/adapters/continue.js +119 -0
- package/dist/cli/install/adapters/continue.js.map +1 -0
- package/dist/cli/install/adapters/cursor.d.ts +8 -0
- package/dist/cli/install/adapters/cursor.d.ts.map +1 -0
- package/dist/cli/install/adapters/cursor.js +195 -0
- package/dist/cli/install/adapters/cursor.js.map +1 -0
- package/dist/cli/install/adapters/markdown-block.d.ts +20 -0
- package/dist/cli/install/adapters/markdown-block.d.ts.map +1 -0
- package/dist/cli/install/adapters/markdown-block.js +114 -0
- package/dist/cli/install/adapters/markdown-block.js.map +1 -0
- package/dist/cli/install/adapters/types.d.ts +39 -0
- package/dist/cli/install/adapters/types.d.ts.map +1 -0
- package/dist/cli/install/adapters/types.js +10 -0
- package/dist/cli/install/adapters/types.js.map +1 -0
- package/dist/cli/install/block.d.ts +53 -0
- package/dist/cli/install/block.d.ts.map +1 -0
- package/dist/cli/install/block.js +106 -0
- package/dist/cli/install/block.js.map +1 -0
- package/dist/cli/install/detect.d.ts +23 -0
- package/dist/cli/install/detect.d.ts.map +1 -0
- package/dist/cli/install/detect.js +115 -0
- package/dist/cli/install/detect.js.map +1 -0
- package/dist/cli/install/diff.d.ts +12 -0
- package/dist/cli/install/diff.d.ts.map +1 -0
- package/dist/cli/install/diff.js +51 -0
- package/dist/cli/install/diff.js.map +1 -0
- package/dist/cli/install/index.d.ts +19 -0
- package/dist/cli/install/index.d.ts.map +1 -0
- package/dist/cli/install/index.js +133 -0
- package/dist/cli/install/index.js.map +1 -0
- package/dist/cli/install/json-managed.d.ts +43 -0
- package/dist/cli/install/json-managed.d.ts.map +1 -0
- package/dist/cli/install/json-managed.js +137 -0
- package/dist/cli/install/json-managed.js.map +1 -0
- package/dist/cli/install/templates/agent-instructions.md +12 -0
- package/dist/cli/install/templates/cursor-openlore.mdc +7 -0
- package/dist/cli/manifest/detect/events.d.ts +31 -0
- package/dist/cli/manifest/detect/events.d.ts.map +1 -0
- package/dist/cli/manifest/detect/events.js +22 -0
- package/dist/cli/manifest/detect/events.js.map +1 -0
- package/dist/cli/manifest/detect/http-routes.d.ts +22 -0
- package/dist/cli/manifest/detect/http-routes.d.ts.map +1 -0
- package/dist/cli/manifest/detect/http-routes.js +18 -0
- package/dist/cli/manifest/detect/http-routes.js.map +1 -0
- package/dist/cli/manifest/detect/public-symbols.d.ts +46 -0
- package/dist/cli/manifest/detect/public-symbols.d.ts.map +1 -0
- package/dist/cli/manifest/detect/public-symbols.js +144 -0
- package/dist/cli/manifest/detect/public-symbols.js.map +1 -0
- package/dist/cli/manifest/emit.d.ts +103 -0
- package/dist/cli/manifest/emit.d.ts.map +1 -0
- package/dist/cli/manifest/emit.js +272 -0
- package/dist/cli/manifest/emit.js.map +1 -0
- package/dist/cli/manifest/index.d.ts +11 -0
- package/dist/cli/manifest/index.d.ts.map +1 -0
- package/dist/cli/manifest/index.js +31 -0
- package/dist/cli/manifest/index.js.map +1 -0
- package/dist/cli/manifest/schema-validator.d.ts +18 -0
- package/dist/cli/manifest/schema-validator.d.ts.map +1 -0
- package/dist/cli/manifest/schema-validator.js +77 -0
- package/dist/cli/manifest/schema-validator.js.map +1 -0
- package/dist/cli/manifest/validate.d.ts +15 -0
- package/dist/cli/manifest/validate.d.ts.map +1 -0
- package/dist/cli/manifest/validate.js +51 -0
- package/dist/cli/manifest/validate.js.map +1 -0
- package/dist/cli/preflight/diff.d.ts +42 -0
- package/dist/cli/preflight/diff.d.ts.map +1 -0
- package/dist/cli/preflight/diff.js +162 -0
- package/dist/cli/preflight/diff.js.map +1 -0
- package/dist/cli/preflight/index.d.ts +31 -0
- package/dist/cli/preflight/index.d.ts.map +1 -0
- package/dist/cli/preflight/index.js +126 -0
- package/dist/cli/preflight/index.js.map +1 -0
- package/dist/cli/preflight/report.d.ts +50 -0
- package/dist/cli/preflight/report.d.ts.map +1 -0
- package/dist/cli/preflight/report.js +174 -0
- package/dist/cli/preflight/report.js.map +1 -0
- package/dist/cli/preflight/score.d.ts +43 -0
- package/dist/cli/preflight/score.d.ts.map +1 -0
- package/dist/cli/preflight/score.js +102 -0
- package/dist/cli/preflight/score.js.map +1 -0
- package/dist/core/analyzer/file-walker.d.ts.map +1 -1
- package/dist/core/analyzer/file-walker.js +20 -13
- package/dist/core/analyzer/file-walker.js.map +1 -1
- package/dist/core/analyzer/vector-index.d.ts +2 -0
- package/dist/core/analyzer/vector-index.d.ts.map +1 -1
- package/dist/core/analyzer/vector-index.js +30 -20
- package/dist/core/analyzer/vector-index.js.map +1 -1
- package/dist/core/scip/index.d.ts +51 -0
- package/dist/core/scip/index.d.ts.map +1 -0
- package/dist/core/scip/index.js +210 -0
- package/dist/core/scip/index.js.map +1 -0
- package/dist/core/scip/moniker.d.ts +48 -0
- package/dist/core/scip/moniker.d.ts.map +1 -0
- package/dist/core/scip/moniker.js +109 -0
- package/dist/core/scip/moniker.js.map +1 -0
- package/dist/core/scip/schema.d.ts +34 -0
- package/dist/core/scip/schema.d.ts.map +1 -0
- package/dist/core/scip/schema.js +48 -0
- package/dist/core/scip/schema.js.map +1 -0
- package/dist/core/scip/vendor/scip.proto +910 -0
- package/dist/core/services/mcp-handlers/utils.d.ts +2 -0
- package/dist/core/services/mcp-handlers/utils.d.ts.map +1 -1
- package/dist/core/services/mcp-handlers/utils.js +18 -2
- package/dist/core/services/mcp-handlers/utils.js.map +1 -1
- package/examples/ci/openlore-preflight.gitlab.yml +16 -0
- package/examples/ci/openlore-preflight.sh +16 -0
- package/examples/ci/openlore-preflight.yml +30 -0
- package/package.json +6 -2
- package/schemas/openlore-manifest-v1.json +191 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A deliberately tiny JSON Schema validator — just the subset used by
|
|
3
|
+
* schemas/openlore-manifest-v1.json. Avoids pulling in Ajv (a large dep) for a
|
|
4
|
+
* single internal schema, per spec-05's acceptance criteria.
|
|
5
|
+
*
|
|
6
|
+
* Supported keywords: type (string or array incl. "null"), const, enum,
|
|
7
|
+
* required, properties, additionalProperties (false only), items. The
|
|
8
|
+
* `integer` type is distinguished from `number`.
|
|
9
|
+
*/
|
|
10
|
+
function typeOf(value) {
|
|
11
|
+
if (value === null)
|
|
12
|
+
return 'null';
|
|
13
|
+
if (Array.isArray(value))
|
|
14
|
+
return 'array';
|
|
15
|
+
if (Number.isInteger(value))
|
|
16
|
+
return 'integer';
|
|
17
|
+
return typeof value; // 'number' | 'string' | 'boolean' | 'object'
|
|
18
|
+
}
|
|
19
|
+
/** Returns true if `value` satisfies a single JSON Schema `type` token. */
|
|
20
|
+
function matchesType(value, type) {
|
|
21
|
+
const actual = typeOf(value);
|
|
22
|
+
if (type === 'number')
|
|
23
|
+
return actual === 'number' || actual === 'integer';
|
|
24
|
+
return actual === type;
|
|
25
|
+
}
|
|
26
|
+
function validateNode(value, schema, path, errors) {
|
|
27
|
+
// const
|
|
28
|
+
if ('const' in schema && value !== schema.const) {
|
|
29
|
+
errors.push({ path, message: `expected const ${JSON.stringify(schema.const)}, got ${JSON.stringify(value)}` });
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
// type
|
|
33
|
+
if ('type' in schema) {
|
|
34
|
+
const types = Array.isArray(schema.type) ? schema.type : [schema.type];
|
|
35
|
+
if (!types.some(t => matchesType(value, t))) {
|
|
36
|
+
errors.push({ path, message: `expected type ${types.join('|')}, got ${typeOf(value)}` });
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// null short-circuits remaining checks
|
|
41
|
+
if (value === null)
|
|
42
|
+
return;
|
|
43
|
+
// enum
|
|
44
|
+
if (Array.isArray(schema.enum) && !schema.enum.includes(value)) {
|
|
45
|
+
errors.push({ path, message: `value ${JSON.stringify(value)} not in enum ${JSON.stringify(schema.enum)}` });
|
|
46
|
+
}
|
|
47
|
+
// object
|
|
48
|
+
if (typeOf(value) === 'object') {
|
|
49
|
+
const obj = value;
|
|
50
|
+
const props = schema.properties ?? {};
|
|
51
|
+
for (const req of schema.required ?? []) {
|
|
52
|
+
if (!(req in obj))
|
|
53
|
+
errors.push({ path: `${path}/${req}`, message: 'missing required property' });
|
|
54
|
+
}
|
|
55
|
+
if (schema.additionalProperties === false) {
|
|
56
|
+
for (const key of Object.keys(obj)) {
|
|
57
|
+
if (!(key in props))
|
|
58
|
+
errors.push({ path: `${path}/${key}`, message: 'additional property not allowed' });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
for (const [key, subSchema] of Object.entries(props)) {
|
|
62
|
+
if (key in obj)
|
|
63
|
+
validateNode(obj[key], subSchema, `${path}/${key}`, errors);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// array
|
|
67
|
+
if (typeOf(value) === 'array' && schema.items) {
|
|
68
|
+
value.forEach((item, i) => validateNode(item, schema.items, `${path}/${i}`, errors));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** Validate a parsed JSON value against a parsed JSON Schema. */
|
|
72
|
+
export function validateAgainstSchema(value, schema) {
|
|
73
|
+
const errors = [];
|
|
74
|
+
validateNode(value, schema, '', errors);
|
|
75
|
+
return errors;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=schema-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-validator.js","sourceRoot":"","sources":["../../../src/cli/manifest/schema-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `openlore manifest validate <path>` — schema-check an existing manifest.
|
|
3
|
+
*
|
|
4
|
+
* Validates against the canonical JSON Schema shipped with OpenLore
|
|
5
|
+
* (schemas/openlore-manifest-v1.json), using the small in-repo validator
|
|
6
|
+
* rather than a heavyweight dependency.
|
|
7
|
+
*/
|
|
8
|
+
import { type ValidationError } from './schema-validator.js';
|
|
9
|
+
/** Absolute path to the vendored manifest JSON Schema (ships in the package). */
|
|
10
|
+
export declare function manifestSchemaPath(): string;
|
|
11
|
+
export declare function loadManifestSchema(): Record<string, unknown>;
|
|
12
|
+
/** Validate a parsed manifest object; returns the (possibly empty) error list. */
|
|
13
|
+
export declare function validateManifest(manifest: unknown): ValidationError[];
|
|
14
|
+
export declare function runManifestValidate(path: string): number;
|
|
15
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/cli/manifest/validate.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAEpF,iFAAiF;AACjF,wBAAgB,kBAAkB,IAAI,MAAM,CAG3C;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE5D;AAED,kFAAkF;AAClF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,GAAG,eAAe,EAAE,CAErE;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA0BxD"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `openlore manifest validate <path>` — schema-check an existing manifest.
|
|
3
|
+
*
|
|
4
|
+
* Validates against the canonical JSON Schema shipped with OpenLore
|
|
5
|
+
* (schemas/openlore-manifest-v1.json), using the small in-repo validator
|
|
6
|
+
* rather than a heavyweight dependency.
|
|
7
|
+
*/
|
|
8
|
+
import { readFileSync } from 'node:fs';
|
|
9
|
+
import { fileURLToPath } from 'node:url';
|
|
10
|
+
import { logger } from '../../utils/logger.js';
|
|
11
|
+
import { validateAgainstSchema } from './schema-validator.js';
|
|
12
|
+
/** Absolute path to the vendored manifest JSON Schema (ships in the package). */
|
|
13
|
+
export function manifestSchemaPath() {
|
|
14
|
+
// src/cli/manifest/validate.ts → repo root → schemas/ (same depth in dist/).
|
|
15
|
+
return fileURLToPath(new URL('../../../schemas/openlore-manifest-v1.json', import.meta.url));
|
|
16
|
+
}
|
|
17
|
+
export function loadManifestSchema() {
|
|
18
|
+
return JSON.parse(readFileSync(manifestSchemaPath(), 'utf-8'));
|
|
19
|
+
}
|
|
20
|
+
/** Validate a parsed manifest object; returns the (possibly empty) error list. */
|
|
21
|
+
export function validateManifest(manifest) {
|
|
22
|
+
return validateAgainstSchema(manifest, loadManifestSchema());
|
|
23
|
+
}
|
|
24
|
+
export function runManifestValidate(path) {
|
|
25
|
+
let raw;
|
|
26
|
+
try {
|
|
27
|
+
raw = readFileSync(path, 'utf-8');
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
logger.error(`Cannot read manifest: ${path}`);
|
|
31
|
+
return 2;
|
|
32
|
+
}
|
|
33
|
+
let parsed;
|
|
34
|
+
try {
|
|
35
|
+
parsed = JSON.parse(raw);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
logger.error(`Invalid JSON in ${path}: ${err instanceof Error ? err.message : String(err)}`);
|
|
39
|
+
return 1;
|
|
40
|
+
}
|
|
41
|
+
const errors = validateManifest(parsed);
|
|
42
|
+
if (errors.length === 0) {
|
|
43
|
+
logger.success(`${path} is a valid OpenLore manifest (v1).`);
|
|
44
|
+
return 0;
|
|
45
|
+
}
|
|
46
|
+
logger.error(`${path} failed schema validation (${errors.length} error(s)):`);
|
|
47
|
+
for (const e of errors)
|
|
48
|
+
logger.error(` ${e.path || '/'}: ${e.message}`);
|
|
49
|
+
return 1;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/cli/manifest/validate.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,qBAAqB,EAAwB,MAAM,uBAAuB,CAAC;AAEpF,iFAAiF;AACjF,MAAM,UAAU,kBAAkB;IAChC,6EAA6E;IAC7E,OAAO,aAAa,CAAC,IAAI,GAAG,CAAC,4CAA4C,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/F,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,kBAAkB,EAAE,EAAE,OAAO,CAAC,CAA4B,CAAC;AAC5F,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,gBAAgB,CAAC,QAAiB;IAChD,OAAO,qBAAqB,CAAC,QAAQ,EAAE,kBAAkB,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,CAAC,KAAK,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC;QAC9C,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,KAAK,CAAC,mBAAmB,IAAI,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7F,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACxC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,qCAAqC,CAAC,CAAC;QAC7D,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,8BAA8B,MAAM,CAAC,MAAM,aAAa,CAAC,CAAC;IAC9E,KAAK,MAAM,CAAC,IAAI,MAAM;QAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,GAAG,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IACzE,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute the set of source files that have changed since the graph was built.
|
|
3
|
+
*
|
|
4
|
+
* Two paths:
|
|
5
|
+
*
|
|
6
|
+
* 1. `--since <git-ref>` (CI-friendly) — `git diff --name-only <ref>...HEAD`
|
|
7
|
+
* plus uncommitted modifications. The merge-base form is intentional:
|
|
8
|
+
* it captures every file the PR touched, not just the latest commit.
|
|
9
|
+
*
|
|
10
|
+
* 2. No `--since` flag — fall back to comparing file mtimes against
|
|
11
|
+
* `fingerprint.json.computedAt`. Slower but works without git history.
|
|
12
|
+
*
|
|
13
|
+
* Either path returns paths relative to the repo root. Non-source files
|
|
14
|
+
* (anything not tracked by the analyzer's language config) are filtered out
|
|
15
|
+
* by the caller via the node table.
|
|
16
|
+
*/
|
|
17
|
+
export interface DiffResult {
|
|
18
|
+
/** Repo-relative paths of files that may have changed since graph build. */
|
|
19
|
+
changed: string[];
|
|
20
|
+
/** Which mechanism produced the list. */
|
|
21
|
+
mechanism: 'git' | 'mtime';
|
|
22
|
+
/** Any non-fatal warnings (e.g. "no .git found, used mtime"). */
|
|
23
|
+
warnings: string[];
|
|
24
|
+
/** The short commit hash of HEAD at the moment of the check, if available. */
|
|
25
|
+
workingCommit: string | null;
|
|
26
|
+
}
|
|
27
|
+
export interface DiffOptions {
|
|
28
|
+
repoRoot: string;
|
|
29
|
+
/** Iso8601 timestamp the graph was built — used by mtime fallback. */
|
|
30
|
+
graphBuiltAt: string | null;
|
|
31
|
+
/** Optional git ref to diff against (e.g. "origin/main"). */
|
|
32
|
+
since?: string;
|
|
33
|
+
}
|
|
34
|
+
export declare function hasGitDirectory(repoRoot: string): Promise<boolean>;
|
|
35
|
+
export declare function refExists(repoRoot: string, ref: string): Promise<boolean>;
|
|
36
|
+
export declare function computeDiff(opts: DiffOptions): Promise<DiffResult>;
|
|
37
|
+
/** Read `fingerprint.json` if present. */
|
|
38
|
+
export declare function readGraphFingerprint(repoRoot: string): Promise<{
|
|
39
|
+
computedAt: string | null;
|
|
40
|
+
fileCount: number | null;
|
|
41
|
+
} | null>;
|
|
42
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../../src/cli/preflight/diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAUH,MAAM,WAAW,UAAU;IACzB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,yCAAyC;IACzC,SAAS,EAAE,KAAK,GAAG,OAAO,CAAC;IAC3B,iEAAiE;IACjE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8EAA8E;IAC9E,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOxE;AAOD,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO/E;AAsED,wBAAsB,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAwCxE;AAED,0CAA0C;AAC1C,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IACpE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,GAAG,IAAI,CAAC,CAYR"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute the set of source files that have changed since the graph was built.
|
|
3
|
+
*
|
|
4
|
+
* Two paths:
|
|
5
|
+
*
|
|
6
|
+
* 1. `--since <git-ref>` (CI-friendly) — `git diff --name-only <ref>...HEAD`
|
|
7
|
+
* plus uncommitted modifications. The merge-base form is intentional:
|
|
8
|
+
* it captures every file the PR touched, not just the latest commit.
|
|
9
|
+
*
|
|
10
|
+
* 2. No `--since` flag — fall back to comparing file mtimes against
|
|
11
|
+
* `fingerprint.json.computedAt`. Slower but works without git history.
|
|
12
|
+
*
|
|
13
|
+
* Either path returns paths relative to the repo root. Non-source files
|
|
14
|
+
* (anything not tracked by the analyzer's language config) are filtered out
|
|
15
|
+
* by the caller via the node table.
|
|
16
|
+
*/
|
|
17
|
+
import { execFile } from 'node:child_process';
|
|
18
|
+
import { promisify } from 'node:util';
|
|
19
|
+
import { stat, readdir, readFile, access } from 'node:fs/promises';
|
|
20
|
+
import { join, relative, resolve, sep } from 'node:path';
|
|
21
|
+
import { OPENLORE_DIR } from '../../constants.js';
|
|
22
|
+
const execFileAsync = promisify(execFile);
|
|
23
|
+
export async function hasGitDirectory(repoRoot) {
|
|
24
|
+
try {
|
|
25
|
+
await access(join(repoRoot, '.git'));
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async function runGit(repoRoot, args) {
|
|
33
|
+
const { stdout } = await execFileAsync('git', args, { cwd: repoRoot });
|
|
34
|
+
return stdout;
|
|
35
|
+
}
|
|
36
|
+
export async function refExists(repoRoot, ref) {
|
|
37
|
+
try {
|
|
38
|
+
await runGit(repoRoot, ['rev-parse', '--verify', '--quiet', ref]);
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async function shortHead(repoRoot) {
|
|
46
|
+
try {
|
|
47
|
+
return (await runGit(repoRoot, ['rev-parse', '--short', 'HEAD'])).trim();
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** Changed files via git diff against `since`, plus uncommitted modifications. */
|
|
54
|
+
async function diffViaGit(repoRoot, since) {
|
|
55
|
+
// Use ...HEAD (merge-base) so we capture every file the PR touched relative
|
|
56
|
+
// to the branch point, not just the latest commit's diff.
|
|
57
|
+
const tracked = (await runGit(repoRoot, ['diff', '--name-only', `${since}...HEAD`]))
|
|
58
|
+
.split('\n')
|
|
59
|
+
.filter(Boolean);
|
|
60
|
+
// Include uncommitted modifications so a developer running locally before
|
|
61
|
+
// committing also gets honest feedback.
|
|
62
|
+
const uncommitted = (await runGit(repoRoot, ['diff', '--name-only', 'HEAD']))
|
|
63
|
+
.split('\n')
|
|
64
|
+
.filter(Boolean);
|
|
65
|
+
const set = new Set([...tracked, ...uncommitted]);
|
|
66
|
+
return Array.from(set).sort();
|
|
67
|
+
}
|
|
68
|
+
/** Changed files via mtime comparison against graphBuiltAtMs. */
|
|
69
|
+
async function diffViaMtime(repoRoot, graphBuiltAtMs) {
|
|
70
|
+
const out = [];
|
|
71
|
+
await walk(repoRoot, repoRoot, graphBuiltAtMs, out);
|
|
72
|
+
return out.sort();
|
|
73
|
+
}
|
|
74
|
+
const SKIP_DIRECTORIES = new Set([
|
|
75
|
+
'node_modules',
|
|
76
|
+
'dist',
|
|
77
|
+
'build',
|
|
78
|
+
'out',
|
|
79
|
+
'coverage',
|
|
80
|
+
OPENLORE_DIR,
|
|
81
|
+
'.git',
|
|
82
|
+
]);
|
|
83
|
+
async function walk(repoRoot, dir, cutoffMs, out) {
|
|
84
|
+
let entries;
|
|
85
|
+
try {
|
|
86
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
for (const ent of entries) {
|
|
92
|
+
if (ent.name.startsWith('.') && ent.name !== '.gitignore')
|
|
93
|
+
continue;
|
|
94
|
+
if (SKIP_DIRECTORIES.has(ent.name))
|
|
95
|
+
continue;
|
|
96
|
+
const full = join(dir, ent.name);
|
|
97
|
+
if (ent.isDirectory()) {
|
|
98
|
+
await walk(repoRoot, full, cutoffMs, out);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (!ent.isFile())
|
|
102
|
+
continue;
|
|
103
|
+
try {
|
|
104
|
+
const s = await stat(full);
|
|
105
|
+
if (s.mtimeMs > cutoffMs) {
|
|
106
|
+
out.push(relative(repoRoot, full).split(sep).join('/'));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
/* unreadable file — skip */
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
export async function computeDiff(opts) {
|
|
115
|
+
const root = resolve(opts.repoRoot);
|
|
116
|
+
const warnings = [];
|
|
117
|
+
const workingCommit = await shortHead(root);
|
|
118
|
+
const gitAvailable = await hasGitDirectory(root);
|
|
119
|
+
if (opts.since) {
|
|
120
|
+
if (!gitAvailable) {
|
|
121
|
+
throw Object.assign(new Error(`--since requires a git repository`), { exitCode: 2 });
|
|
122
|
+
}
|
|
123
|
+
if (!(await refExists(root, opts.since))) {
|
|
124
|
+
throw Object.assign(new Error(`git ref not found: ${opts.since}`), { exitCode: 2 });
|
|
125
|
+
}
|
|
126
|
+
const changed = await diffViaGit(root, opts.since);
|
|
127
|
+
return { changed, mechanism: 'git', warnings, workingCommit };
|
|
128
|
+
}
|
|
129
|
+
if (!gitAvailable) {
|
|
130
|
+
warnings.push('no .git found — falling back to mtime comparison');
|
|
131
|
+
}
|
|
132
|
+
if (!opts.graphBuiltAt) {
|
|
133
|
+
warnings.push('graph has no build timestamp — everything will look stale');
|
|
134
|
+
// Treat as "everything changed since epoch" — caller can decide.
|
|
135
|
+
const changed = await diffViaMtime(root, 0);
|
|
136
|
+
return { changed, mechanism: 'mtime', warnings, workingCommit };
|
|
137
|
+
}
|
|
138
|
+
const cutoff = Date.parse(opts.graphBuiltAt);
|
|
139
|
+
if (Number.isNaN(cutoff)) {
|
|
140
|
+
warnings.push(`graph build timestamp unparseable: ${opts.graphBuiltAt}`);
|
|
141
|
+
const changed = await diffViaMtime(root, 0);
|
|
142
|
+
return { changed, mechanism: 'mtime', warnings, workingCommit };
|
|
143
|
+
}
|
|
144
|
+
const changed = await diffViaMtime(root, cutoff);
|
|
145
|
+
return { changed, mechanism: 'mtime', warnings, workingCommit };
|
|
146
|
+
}
|
|
147
|
+
/** Read `fingerprint.json` if present. */
|
|
148
|
+
export async function readGraphFingerprint(repoRoot) {
|
|
149
|
+
const path = join(repoRoot, OPENLORE_DIR, 'analysis', 'fingerprint.json');
|
|
150
|
+
try {
|
|
151
|
+
const raw = await readFile(path, 'utf8');
|
|
152
|
+
const parsed = JSON.parse(raw);
|
|
153
|
+
return {
|
|
154
|
+
computedAt: parsed.computedAt ?? null,
|
|
155
|
+
fileCount: typeof parsed.fileCount === 'number' ? parsed.fileCount : null,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../../src/cli/preflight/diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `openlore preflight` — CI staleness gate.
|
|
3
|
+
*
|
|
4
|
+
* Determines whether the persisted analysis graph is current relative to
|
|
5
|
+
* the working tree. Designed to run on every PR so out-of-date graphs
|
|
6
|
+
* never reach orient() / agent runtime silently.
|
|
7
|
+
*
|
|
8
|
+
* Exit codes: 0 = fresh, 1 = stale, 2 = error.
|
|
9
|
+
*/
|
|
10
|
+
import { Command } from 'commander';
|
|
11
|
+
import { type PreflightSummary } from './report.js';
|
|
12
|
+
export interface PreflightOptions {
|
|
13
|
+
cwd?: string;
|
|
14
|
+
fix?: boolean;
|
|
15
|
+
json?: boolean;
|
|
16
|
+
since?: string;
|
|
17
|
+
maxStaleness?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Test-only seam: replace the analyzer invocation used by --fix. Returns
|
|
20
|
+
* the exit code (0 = success). Production code spawns `openlore analyze`;
|
|
21
|
+
* tests pass a stub that simulates the side-effect (refreshing
|
|
22
|
+
* fingerprint.json) without needing the full pipeline.
|
|
23
|
+
*/
|
|
24
|
+
analyzeFn?: (cwd: string) => Promise<number>;
|
|
25
|
+
}
|
|
26
|
+
export declare function runPreflight(opts: PreflightOptions): Promise<{
|
|
27
|
+
code: number;
|
|
28
|
+
summary?: PreflightSummary;
|
|
29
|
+
}>;
|
|
30
|
+
export declare const preflightCommand: Command;
|
|
31
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/preflight/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,OAAO,EAKL,KAAK,gBAAgB,EACtB,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9C;AAID,wBAAsB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B,CAAC,CAgGD;AAeD,eAAO,MAAM,gBAAgB,SAczB,CAAC"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `openlore preflight` — CI staleness gate.
|
|
3
|
+
*
|
|
4
|
+
* Determines whether the persisted analysis graph is current relative to
|
|
5
|
+
* the working tree. Designed to run on every PR so out-of-date graphs
|
|
6
|
+
* never reach orient() / agent runtime silently.
|
|
7
|
+
*
|
|
8
|
+
* Exit codes: 0 = fresh, 1 = stale, 2 = error.
|
|
9
|
+
*/
|
|
10
|
+
import { access } from 'node:fs/promises';
|
|
11
|
+
import { join, resolve } from 'node:path';
|
|
12
|
+
import { spawn } from 'node:child_process';
|
|
13
|
+
import { Command } from 'commander';
|
|
14
|
+
import { logger } from '../../utils/logger.js';
|
|
15
|
+
import { OPENLORE_DIR, OPENLORE_ANALYSIS_SUBDIR, ARTIFACT_CALL_GRAPH_DB, } from '../../constants.js';
|
|
16
|
+
import { computeDiff, readGraphFingerprint } from './diff.js';
|
|
17
|
+
import { scoreChangedFiles } from './score.js';
|
|
18
|
+
import { buildSummary, renderHuman, renderJson, renderGithubAnnotations, } from './report.js';
|
|
19
|
+
const DEFAULT_THRESHOLD = 0;
|
|
20
|
+
export async function runPreflight(opts) {
|
|
21
|
+
const cwd = resolve(opts.cwd ?? process.cwd());
|
|
22
|
+
const threshold = typeof opts.maxStaleness === 'number' ? opts.maxStaleness : DEFAULT_THRESHOLD;
|
|
23
|
+
// 1. Graph must exist.
|
|
24
|
+
const dbPath = join(cwd, OPENLORE_DIR, OPENLORE_ANALYSIS_SUBDIR, ARTIFACT_CALL_GRAPH_DB);
|
|
25
|
+
try {
|
|
26
|
+
await access(dbPath);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
if (opts.json) {
|
|
30
|
+
process.stdout.write(JSON.stringify({
|
|
31
|
+
status: 'ERROR',
|
|
32
|
+
error: 'no graph found',
|
|
33
|
+
hint: 'run `openlore analyze` first',
|
|
34
|
+
}, null, 2) + '\n');
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
logger.error('No graph found. Run `openlore analyze` first to build the analysis graph.');
|
|
38
|
+
}
|
|
39
|
+
return { code: 2 };
|
|
40
|
+
}
|
|
41
|
+
// 2. Read graph metadata.
|
|
42
|
+
const fp = await readGraphFingerprint(cwd);
|
|
43
|
+
const graphBuiltAt = fp?.computedAt ?? null;
|
|
44
|
+
// We don't store the build commit today — leave null. Once analyze records
|
|
45
|
+
// it, this is the single place to surface it. (See TODO in docs/preflight.md.)
|
|
46
|
+
const graphCommit = null;
|
|
47
|
+
// 3. Compute changed files.
|
|
48
|
+
let diff;
|
|
49
|
+
try {
|
|
50
|
+
diff = await computeDiff({ repoRoot: cwd, graphBuiltAt, since: opts.since });
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
const e = err;
|
|
54
|
+
if (opts.json) {
|
|
55
|
+
process.stdout.write(JSON.stringify({ status: 'ERROR', error: e.message }, null, 2) + '\n');
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
logger.error(e.message);
|
|
59
|
+
}
|
|
60
|
+
return { code: e.exitCode ?? 2 };
|
|
61
|
+
}
|
|
62
|
+
// 4. Score.
|
|
63
|
+
const score = scoreChangedFiles(cwd, diff.changed);
|
|
64
|
+
// 5. Build summary.
|
|
65
|
+
const summary = buildSummary({ diff, score, graphBuiltAt, graphCommit, threshold });
|
|
66
|
+
const stale = summary.stalenessScore > threshold;
|
|
67
|
+
// 6. --fix path runs `openlore analyze` then re-checks.
|
|
68
|
+
if (stale && opts.fix) {
|
|
69
|
+
if (!opts.json)
|
|
70
|
+
logger.discovery('Stale graph detected — running `openlore analyze --fix`');
|
|
71
|
+
const code = await (opts.analyzeFn ?? runAnalyzeFix)(cwd);
|
|
72
|
+
if (code !== 0) {
|
|
73
|
+
if (opts.json) {
|
|
74
|
+
process.stdout.write(JSON.stringify({ status: 'ERROR', error: 'openlore analyze --fix failed' }, null, 2) +
|
|
75
|
+
'\n');
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
logger.error('openlore analyze failed during --fix; manual intervention required');
|
|
79
|
+
}
|
|
80
|
+
return { code: 2 };
|
|
81
|
+
}
|
|
82
|
+
// Re-run preflight WITHOUT --fix and WITHOUT --since (now everything
|
|
83
|
+
// should be current vs. the freshly built graph).
|
|
84
|
+
return runPreflight({
|
|
85
|
+
cwd,
|
|
86
|
+
json: opts.json,
|
|
87
|
+
maxStaleness: opts.maxStaleness,
|
|
88
|
+
analyzeFn: opts.analyzeFn,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
// 7. Render.
|
|
92
|
+
if (opts.json) {
|
|
93
|
+
process.stdout.write(renderJson(summary) + '\n');
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
process.stdout.write(renderHuman(summary) + '\n');
|
|
97
|
+
}
|
|
98
|
+
// 8. GitHub Actions inline annotations (no-op outside GHA).
|
|
99
|
+
const annotations = renderGithubAnnotations(summary);
|
|
100
|
+
if (annotations)
|
|
101
|
+
process.stdout.write(annotations + '\n');
|
|
102
|
+
return { code: stale ? 1 : 0, summary };
|
|
103
|
+
}
|
|
104
|
+
async function runAnalyzeFix(cwd) {
|
|
105
|
+
return new Promise((resolveProm) => {
|
|
106
|
+
// TODO(spec-03-followup): when `openlore analyze --incremental` exists,
|
|
107
|
+
// prefer that — it should be a fraction of the cost of the full re-run.
|
|
108
|
+
const child = spawn(process.execPath, [process.argv[1], 'analyze'], {
|
|
109
|
+
cwd,
|
|
110
|
+
stdio: 'inherit',
|
|
111
|
+
});
|
|
112
|
+
child.on('exit', (code) => resolveProm(code ?? 1));
|
|
113
|
+
child.on('error', () => resolveProm(1));
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
export const preflightCommand = new Command('preflight')
|
|
117
|
+
.description('CI staleness gate: check whether the analysis graph is current relative to the working tree.')
|
|
118
|
+
.option('--fix', 'Run `openlore analyze` if the graph is stale, then re-check', false)
|
|
119
|
+
.option('--json', 'Emit JSON instead of human-readable output', false)
|
|
120
|
+
.option('--since <ref>', 'Diff against this git ref (e.g. origin/main) instead of mtimes')
|
|
121
|
+
.option('--max-staleness <n>', `Maximum allowed staleness score (default ${DEFAULT_THRESHOLD})`, (v) => parseInt(v, 10), DEFAULT_THRESHOLD)
|
|
122
|
+
.action(async (opts) => {
|
|
123
|
+
const { code } = await runPreflight(opts);
|
|
124
|
+
process.exit(code);
|
|
125
|
+
});
|
|
126
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/preflight/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Human-readable + JSON renderers for preflight results.
|
|
3
|
+
*/
|
|
4
|
+
import type { DiffResult } from './diff.js';
|
|
5
|
+
import type { ScoreResult } from './score.js';
|
|
6
|
+
export type PreflightStatus = 'FRESH' | 'STALE' | 'ERROR';
|
|
7
|
+
export interface PerFileEntry {
|
|
8
|
+
filePath: string;
|
|
9
|
+
weight: number;
|
|
10
|
+
hub: boolean;
|
|
11
|
+
/** Highest fan-in across nodes in the file (for "why is this a hub"). */
|
|
12
|
+
maxFanIn: number;
|
|
13
|
+
/** True if the file isn't represented in the graph at all. */
|
|
14
|
+
unknown: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface PreflightSummary {
|
|
17
|
+
status: PreflightStatus;
|
|
18
|
+
graphBuiltAt: string | null;
|
|
19
|
+
graphCommit: string | null;
|
|
20
|
+
workingCommit: string | null;
|
|
21
|
+
changedFiles: string[];
|
|
22
|
+
unknownFiles: string[];
|
|
23
|
+
/** Per-file detail with weight + hub flag. Same order as `changedFiles`. */
|
|
24
|
+
perFile: PerFileEntry[];
|
|
25
|
+
hubCount: number;
|
|
26
|
+
leafCount: number;
|
|
27
|
+
stalenessScore: number;
|
|
28
|
+
threshold: number;
|
|
29
|
+
mechanism: 'git' | 'mtime';
|
|
30
|
+
warnings: string[];
|
|
31
|
+
message: string;
|
|
32
|
+
}
|
|
33
|
+
export interface BuildSummaryInput {
|
|
34
|
+
diff: DiffResult;
|
|
35
|
+
score: ScoreResult;
|
|
36
|
+
graphBuiltAt: string | null;
|
|
37
|
+
graphCommit: string | null;
|
|
38
|
+
threshold: number;
|
|
39
|
+
}
|
|
40
|
+
export declare function buildSummary(input: BuildSummaryInput): PreflightSummary;
|
|
41
|
+
export declare function renderHuman(s: PreflightSummary): string;
|
|
42
|
+
/**
|
|
43
|
+
* Emit GitHub Actions workflow-command annotations so that stale files
|
|
44
|
+
* appear inline in the PR diff UI when this runs in CI. No-op outside of
|
|
45
|
+
* GHA. Format docs:
|
|
46
|
+
* https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions
|
|
47
|
+
*/
|
|
48
|
+
export declare function renderGithubAnnotations(s: PreflightSummary): string;
|
|
49
|
+
export declare function renderJson(s: PreflightSummary): string;
|
|
50
|
+
//# sourceMappingURL=report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../src/cli/preflight/report.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAE1D,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;IACb,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,eAAe,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,4EAA4E;IAC5E,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,KAAK,GAAG,OAAO,CAAC;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,WAAW,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,gBAAgB,CA8CvE;AAMD,wBAAgB,WAAW,CAAC,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAmDvD;AAcD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAmBnE;AAMD,wBAAgB,UAAU,CAAC,CAAC,EAAE,gBAAgB,GAAG,MAAM,CA4BtD"}
|