@open-tomato/rafa 0.20.0 → 0.21.0
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 +39 -1
- package/dist/cli.js +1143 -329
- package/dist/effort/store/index.js +1 -1
- package/dist/{index-afersvp3.js → index-am92b8qp.js} +26 -5
- package/dist/{index-zhh1h3h9.js → index-kv51t295.js} +40 -4
- package/dist/{index-02fx0mzf.js → index-pzpk59ma.js} +3255 -2524
- package/dist/index.js +2 -2
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -1773,7 +1773,7 @@ function restoreRunningCommand(previous) {
|
|
|
1773
1773
|
var running = null;
|
|
1774
1774
|
|
|
1775
1775
|
// package.json
|
|
1776
|
-
var name = "@open-tomato/rafa", version = "0.
|
|
1776
|
+
var name = "@open-tomato/rafa", version = "0.21.0";
|
|
1777
1777
|
var init_package = () => {};
|
|
1778
1778
|
|
|
1779
1779
|
// src/cli/version.ts
|
|
@@ -2718,6 +2718,22 @@ var init_instinct = __esm(() => {
|
|
|
2718
2718
|
];
|
|
2719
2719
|
});
|
|
2720
2720
|
|
|
2721
|
+
// src/schema/failure-strings.ts
|
|
2722
|
+
function failureStringProblem(entry) {
|
|
2723
|
+
if (entry.trim() === "") {
|
|
2724
|
+
return {
|
|
2725
|
+
code: "empty-failure-string",
|
|
2726
|
+
message: "a blank failure string is found in every text, " + "so every task would read as a recurrence"
|
|
2727
|
+
};
|
|
2728
|
+
}
|
|
2729
|
+
const length = Array.from(entry).length;
|
|
2730
|
+
return length < FAILURE_STRING_MIN_LENGTH ? {
|
|
2731
|
+
code: "short-failure-string",
|
|
2732
|
+
message: `failure string "${entry}" is ${length} characters, under ` + `${FAILURE_STRING_MIN_LENGTH}, so it may match failures the skill does not name`
|
|
2733
|
+
} : null;
|
|
2734
|
+
}
|
|
2735
|
+
var FAILURE_STRING_MIN_LENGTH = 6;
|
|
2736
|
+
|
|
2721
2737
|
// src/schema/provenance.ts
|
|
2722
2738
|
function issue2(code, field, message) {
|
|
2723
2739
|
return { code, field, message };
|
|
@@ -3049,6 +3065,9 @@ var init_stack = __esm(() => {
|
|
|
3049
3065
|
});
|
|
3050
3066
|
|
|
3051
3067
|
// src/schema/skill.ts
|
|
3068
|
+
function isSkillWarning(code) {
|
|
3069
|
+
return SKILL_WARNING_CODES.includes(code);
|
|
3070
|
+
}
|
|
3052
3071
|
function countCharacters(text2) {
|
|
3053
3072
|
return Array.from(text2).length;
|
|
3054
3073
|
}
|
|
@@ -3252,6 +3271,22 @@ function checkPaths(data) {
|
|
|
3252
3271
|
}
|
|
3253
3272
|
return issues;
|
|
3254
3273
|
}
|
|
3274
|
+
function checkFailureStrings(data) {
|
|
3275
|
+
const value = data["failure_strings"];
|
|
3276
|
+
if (value === undefined)
|
|
3277
|
+
return [];
|
|
3278
|
+
if (!Array.isArray(value)) {
|
|
3279
|
+
return [issue3("wrong-type", "failure_strings", `failure_strings must be a list, not ${typeName3(value)}`)];
|
|
3280
|
+
}
|
|
3281
|
+
return value.flatMap((entry, index) => {
|
|
3282
|
+
const field = `failure_strings[${index}]`;
|
|
3283
|
+
if (typeof entry !== "string") {
|
|
3284
|
+
return [issue3("wrong-type", field, `failure_strings entries must be strings, and this one is ${typeName3(entry)}`)];
|
|
3285
|
+
}
|
|
3286
|
+
const problem = failureStringProblem(entry);
|
|
3287
|
+
return problem === null ? [] : [issue3(problem.code, field, problem.message)];
|
|
3288
|
+
});
|
|
3289
|
+
}
|
|
3255
3290
|
function checkBoolean(data, field) {
|
|
3256
3291
|
const value = data[field];
|
|
3257
3292
|
if (value === undefined || typeof value === "boolean")
|
|
@@ -3269,6 +3304,7 @@ function checkSkillFrontmatter(data) {
|
|
|
3269
3304
|
...checkStack(data),
|
|
3270
3305
|
...checkWhenToUse(data),
|
|
3271
3306
|
...checkTrigger(data),
|
|
3307
|
+
...checkFailureStrings(data),
|
|
3272
3308
|
...SKILL_NAME_LIST_FIELDS.flatMap((field) => checkNameList(data, field)),
|
|
3273
3309
|
...checkPaths(data),
|
|
3274
3310
|
...SKILL_BOOLEAN_FIELDS.flatMap((field) => checkBoolean(data, field)),
|
|
@@ -3276,7 +3312,7 @@ function checkSkillFrontmatter(data) {
|
|
|
3276
3312
|
...checkForbidden(data)
|
|
3277
3313
|
];
|
|
3278
3314
|
}
|
|
3279
|
-
var DESCRIPTION_LIMIT = 130, LISTING_LIMIT = 1536, SKILL_SIGNALS, FORBIDDEN_SKILL_FIELDS, SKILL_BOOLEAN_FIELDS, SKILL_NAME_LIST_FIELDS, SKILL_NAME_PATTERN;
|
|
3315
|
+
var DESCRIPTION_LIMIT = 130, LISTING_LIMIT = 1536, SKILL_SIGNALS, FORBIDDEN_SKILL_FIELDS, SKILL_BOOLEAN_FIELDS, SKILL_NAME_LIST_FIELDS, SKILL_NAME_PATTERN, SKILL_WARNING_CODES;
|
|
3280
3316
|
var init_skill = __esm(() => {
|
|
3281
3317
|
init_provenance();
|
|
3282
3318
|
init_stack();
|
|
@@ -3285,6 +3321,7 @@ var init_skill = __esm(() => {
|
|
|
3285
3321
|
SKILL_BOOLEAN_FIELDS = ["disable-model-invocation", "user-invocable"];
|
|
3286
3322
|
SKILL_NAME_LIST_FIELDS = ["relates", "supersedes"];
|
|
3287
3323
|
SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
3324
|
+
SKILL_WARNING_CODES = ["short-failure-string"];
|
|
3288
3325
|
});
|
|
3289
3326
|
|
|
3290
3327
|
// src/check/layout.ts
|
|
@@ -3989,11 +4026,14 @@ function fromLayout(issue4) {
|
|
|
3989
4026
|
message: issue4.message
|
|
3990
4027
|
};
|
|
3991
4028
|
}
|
|
4029
|
+
function skillSeverity(code) {
|
|
4030
|
+
return isSkillWarning(code) ? "warning" : "failure";
|
|
4031
|
+
}
|
|
3992
4032
|
function fromSkill(issue4) {
|
|
3993
4033
|
return {
|
|
3994
4034
|
stage: "schema",
|
|
3995
4035
|
code: issue4.code,
|
|
3996
|
-
severity:
|
|
4036
|
+
severity: skillSeverity(issue4.code),
|
|
3997
4037
|
field: issue4.field,
|
|
3998
4038
|
line: null,
|
|
3999
4039
|
message: issue4.message
|
|
@@ -5744,131 +5784,9 @@ var init_ndjson = __esm(() => {
|
|
|
5744
5784
|
init_types2();
|
|
5745
5785
|
});
|
|
5746
5786
|
|
|
5747
|
-
// src/effort/store/
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
import { Database } from "bun:sqlite";
|
|
5751
|
-
function sqliteStorePath(repoRoot) {
|
|
5752
|
-
return join13(repoRoot, EFFORT_STORE_DIR, STORE_FILE_NAME);
|
|
5753
|
-
}
|
|
5754
|
-
function hasKey(entry) {
|
|
5755
|
-
return entry.key !== null;
|
|
5756
|
-
}
|
|
5757
|
-
function refused2(index, length, reason) {
|
|
5758
|
-
return new Error(`effort store: row ${index} of ${length} ${reason}; batch refused`);
|
|
5759
|
-
}
|
|
5760
|
-
function batchEntries(kind, rows2) {
|
|
5761
|
-
const keyOf = EFFORT_KEY_PROJECTIONS[kind];
|
|
5762
|
-
const projected = rows2.map((row2) => ({ key: keyOf(row2), row: row2 }));
|
|
5763
|
-
const keyed = projected.filter(hasKey);
|
|
5764
|
-
if (keyed.length < projected.length) {
|
|
5765
|
-
const keylessAt = projected.findIndex((entry) => !hasKey(entry));
|
|
5766
|
-
throw refused2(keylessAt, rows2.length, "carries no key");
|
|
5767
|
-
}
|
|
5768
|
-
const unholdableAt = keyed.findIndex(({ key }) => LONE_SURROGATE.test(key));
|
|
5769
|
-
if (unholdableAt !== -1) {
|
|
5770
|
-
const reason = "carries a key with a lone UTF-16 surrogate," + " which SQLite text cannot hold";
|
|
5771
|
-
throw refused2(unholdableAt, rows2.length, reason);
|
|
5772
|
-
}
|
|
5773
|
-
return keyed.map(({ key, row: row2 }) => ({ key, body: JSON.stringify(row2) }));
|
|
5774
|
-
}
|
|
5775
|
-
function userVersion(db) {
|
|
5776
|
-
const row2 = db.query("PRAGMA user_version").get();
|
|
5777
|
-
return row2?.user_version ?? 0;
|
|
5778
|
-
}
|
|
5779
|
-
function checkedVersion(db, path, latest) {
|
|
5780
|
-
const version2 = userVersion(db);
|
|
5781
|
-
if (version2 > latest) {
|
|
5782
|
-
throw new Error(`effort store: ${path} is at schema version ${version2}, past the` + ` ${latest} this rafa knows; refusing to read or write it`);
|
|
5783
|
-
}
|
|
5784
|
-
return version2;
|
|
5785
|
-
}
|
|
5786
|
-
function migrateSchema(db, path, migrations = SQLITE_MIGRATIONS) {
|
|
5787
|
-
const latest = migrations.length;
|
|
5788
|
-
if (checkedVersion(db, path, latest) === latest)
|
|
5789
|
-
return;
|
|
5790
|
-
const applyPending = db.transaction(() => {
|
|
5791
|
-
const from = checkedVersion(db, path, latest);
|
|
5792
|
-
for (const sql of migrations.slice(from))
|
|
5793
|
-
db.run(sql);
|
|
5794
|
-
db.run(`PRAGMA user_version = ${latest}`);
|
|
5795
|
-
});
|
|
5796
|
-
applyPending.immediate();
|
|
5797
|
-
}
|
|
5798
|
-
function withSqliteStore(path, create, use) {
|
|
5799
|
-
if (create)
|
|
5800
|
-
mkdirSync4(dirname8(path), { recursive: true });
|
|
5801
|
-
const db = new Database(path, { readwrite: true, create });
|
|
5802
|
-
try {
|
|
5803
|
-
migrateSchema(db, path);
|
|
5804
|
-
return use(db);
|
|
5805
|
-
} finally {
|
|
5806
|
-
db.close();
|
|
5807
|
-
}
|
|
5808
|
-
}
|
|
5809
|
-
function insertBatch(db, table2, entries) {
|
|
5810
|
-
const insert = db.query(`INSERT INTO ${table2.name} (${table2.keyColumn}, row_json) VALUES (?, ?)` + ` ON CONFLICT (${table2.keyColumn}) DO NOTHING`);
|
|
5811
|
-
const insertAll = db.transaction(() => entries.reduce((appended, { key, body }) => appended + insert.run(key, body).changes, 0));
|
|
5812
|
-
return insertAll.immediate();
|
|
5813
|
-
}
|
|
5814
|
-
function writeSqliteStore(path, rowCount, empty, insert) {
|
|
5815
|
-
const exists = existsSync6(path);
|
|
5816
|
-
if (rowCount > 0)
|
|
5817
|
-
return withSqliteStore(path, !exists, insert);
|
|
5818
|
-
if (exists)
|
|
5819
|
-
withSqliteStore(path, false, () => {
|
|
5820
|
-
return;
|
|
5821
|
-
});
|
|
5822
|
-
return empty;
|
|
5823
|
-
}
|
|
5824
|
-
function appendKind2(path, kind, rows2) {
|
|
5825
|
-
const entries = batchEntries(kind, rows2);
|
|
5826
|
-
const table2 = KIND_TABLES[kind];
|
|
5827
|
-
const appended = writeSqliteStore(path, entries.length, 0, (db) => insertBatch(db, table2, entries));
|
|
5828
|
-
return { path, appended, skipped: entries.length - appended };
|
|
5829
|
-
}
|
|
5830
|
-
function keysOfKind2(path, kind) {
|
|
5831
|
-
if (!existsSync6(path))
|
|
5832
|
-
return new Set;
|
|
5833
|
-
const { name: name2, keyColumn } = KIND_TABLES[kind];
|
|
5834
|
-
const keys = withSqliteStore(path, false, (db) => db.query(`SELECT ${keyColumn} AS key FROM ${name2} ORDER BY seq`).all());
|
|
5835
|
-
return new Set(keys.map(({ key }) => key));
|
|
5836
|
-
}
|
|
5837
|
-
function parsedObject(body) {
|
|
5838
|
-
try {
|
|
5839
|
-
const value = JSON.parse(body);
|
|
5840
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
5841
|
-
} catch {
|
|
5842
|
-
return null;
|
|
5843
|
-
}
|
|
5844
|
-
}
|
|
5845
|
-
function rowOf(body, where) {
|
|
5846
|
-
const value = parsedObject(body);
|
|
5847
|
-
if (value === null) {
|
|
5848
|
-
throw new Error(`effort store: ${where} does not hold a JSON object;` + " no append writes one");
|
|
5849
|
-
}
|
|
5850
|
-
return value;
|
|
5851
|
-
}
|
|
5852
|
-
function readKind2(path, kind) {
|
|
5853
|
-
if (!existsSync6(path))
|
|
5854
|
-
return [];
|
|
5855
|
-
const { name: name2 } = KIND_TABLES[kind];
|
|
5856
|
-
const stored = withSqliteStore(path, false, (db) => db.query(`SELECT seq, row_json AS body FROM ${name2} ORDER BY seq`).all());
|
|
5857
|
-
return stored.map(({ seq, body }) => rowOf(body, `${path}: ${name2} row ${seq}`));
|
|
5858
|
-
}
|
|
5859
|
-
function openSqliteStore(repoRoot) {
|
|
5860
|
-
const path = sqliteStorePath(repoRoot);
|
|
5861
|
-
return {
|
|
5862
|
-
append: (kind, rows2) => appendKind2(path, kind, rows2),
|
|
5863
|
-
keys: (kind) => keysOfKind2(path, kind),
|
|
5864
|
-
read: (kind) => readKind2(path, kind),
|
|
5865
|
-
path: () => path
|
|
5866
|
-
};
|
|
5867
|
-
}
|
|
5868
|
-
var STORE_FILE_NAME = "effort.sqlite", SQLITE_MIGRATIONS, SQLITE_SCHEMA_VERSION, KIND_TABLES, LONE_SURROGATE;
|
|
5869
|
-
var init_sqlite = __esm(() => {
|
|
5870
|
-
init_store();
|
|
5871
|
-
init_types2();
|
|
5787
|
+
// src/effort/store/migrations.ts
|
|
5788
|
+
var SQLITE_MIGRATIONS, SQLITE_SCHEMA_VERSION;
|
|
5789
|
+
var init_migrations = __esm(() => {
|
|
5872
5790
|
SQLITE_MIGRATIONS = [
|
|
5873
5791
|
`
|
|
5874
5792
|
CREATE TABLE sessions (
|
|
@@ -6044,9 +5962,155 @@ var init_sqlite = __esm(() => {
|
|
|
6044
5962
|
|
|
6045
5963
|
CREATE UNIQUE INDEX skill_invocations_by_use
|
|
6046
5964
|
ON skill_invocations (session_id, ifnull(name, ''), ifnull(sidechain, -1));
|
|
5965
|
+
`,
|
|
5966
|
+
`
|
|
5967
|
+
ALTER TABLE task_reports
|
|
5968
|
+
ADD COLUMN skills_used TEXT CHECK (skills_used IS NULL OR json_type(skills_used) = 'array');
|
|
5969
|
+
`,
|
|
5970
|
+
`
|
|
5971
|
+
CREATE TABLE plan_ci (
|
|
5972
|
+
seq INTEGER PRIMARY KEY,
|
|
5973
|
+
plan_stub TEXT NOT NULL CHECK (plan_stub <> ''),
|
|
5974
|
+
pr INTEGER NOT NULL CHECK (typeof(pr) = 'integer' AND pr > 0),
|
|
5975
|
+
head_sha TEXT NOT NULL CHECK (head_sha <> ''),
|
|
5976
|
+
verdict TEXT NOT NULL CHECK (verdict IN ('green', 'red', 'none')),
|
|
5977
|
+
failing TEXT NOT NULL CHECK (json_valid(failing) AND json_type(failing) = 'array'),
|
|
5978
|
+
read_at TEXT NOT NULL CHECK (read_at <> ''),
|
|
5979
|
+
UNIQUE (pr, head_sha, read_at),
|
|
5980
|
+
CHECK ((verdict = 'red') = (json_array_length(failing) > 0))
|
|
5981
|
+
);
|
|
6047
5982
|
`
|
|
6048
5983
|
];
|
|
6049
5984
|
SQLITE_SCHEMA_VERSION = SQLITE_MIGRATIONS.length;
|
|
5985
|
+
});
|
|
5986
|
+
|
|
5987
|
+
// src/effort/store/sqlite.ts
|
|
5988
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync4 } from "fs";
|
|
5989
|
+
import { dirname as dirname8, join as join13 } from "path";
|
|
5990
|
+
import { Database } from "bun:sqlite";
|
|
5991
|
+
function sqliteStorePath(repoRoot) {
|
|
5992
|
+
return join13(repoRoot, EFFORT_STORE_DIR, STORE_FILE_NAME);
|
|
5993
|
+
}
|
|
5994
|
+
function hasKey(entry) {
|
|
5995
|
+
return entry.key !== null;
|
|
5996
|
+
}
|
|
5997
|
+
function refused2(index, length, reason) {
|
|
5998
|
+
return new Error(`effort store: row ${index} of ${length} ${reason}; batch refused`);
|
|
5999
|
+
}
|
|
6000
|
+
function batchEntries(kind, rows2) {
|
|
6001
|
+
const keyOf = EFFORT_KEY_PROJECTIONS[kind];
|
|
6002
|
+
const projected = rows2.map((row2) => ({ key: keyOf(row2), row: row2 }));
|
|
6003
|
+
const keyed = projected.filter(hasKey);
|
|
6004
|
+
if (keyed.length < projected.length) {
|
|
6005
|
+
const keylessAt = projected.findIndex((entry) => !hasKey(entry));
|
|
6006
|
+
throw refused2(keylessAt, rows2.length, "carries no key");
|
|
6007
|
+
}
|
|
6008
|
+
const unholdableAt = keyed.findIndex(({ key }) => LONE_SURROGATE.test(key));
|
|
6009
|
+
if (unholdableAt !== -1) {
|
|
6010
|
+
const reason = "carries a key with a lone UTF-16 surrogate," + " which SQLite text cannot hold";
|
|
6011
|
+
throw refused2(unholdableAt, rows2.length, reason);
|
|
6012
|
+
}
|
|
6013
|
+
return keyed.map(({ key, row: row2 }) => ({ key, body: JSON.stringify(row2) }));
|
|
6014
|
+
}
|
|
6015
|
+
function userVersion(db) {
|
|
6016
|
+
const row2 = db.query("PRAGMA user_version").get();
|
|
6017
|
+
return row2?.user_version ?? 0;
|
|
6018
|
+
}
|
|
6019
|
+
function checkedVersion(db, path, latest) {
|
|
6020
|
+
const version2 = userVersion(db);
|
|
6021
|
+
if (version2 > latest) {
|
|
6022
|
+
throw new Error(`effort store: ${path} is at schema version ${version2}, past the` + ` ${latest} this rafa knows; refusing to read or write it`);
|
|
6023
|
+
}
|
|
6024
|
+
return version2;
|
|
6025
|
+
}
|
|
6026
|
+
function migrateSchema(db, path, migrations = SQLITE_MIGRATIONS) {
|
|
6027
|
+
const latest = migrations.length;
|
|
6028
|
+
if (checkedVersion(db, path, latest) === latest)
|
|
6029
|
+
return;
|
|
6030
|
+
const applyPending = db.transaction(() => {
|
|
6031
|
+
const from = checkedVersion(db, path, latest);
|
|
6032
|
+
for (const sql of migrations.slice(from))
|
|
6033
|
+
db.run(sql);
|
|
6034
|
+
db.run(`PRAGMA user_version = ${latest}`);
|
|
6035
|
+
});
|
|
6036
|
+
applyPending.immediate();
|
|
6037
|
+
}
|
|
6038
|
+
function withSqliteStore(path, create, use) {
|
|
6039
|
+
if (create)
|
|
6040
|
+
mkdirSync4(dirname8(path), { recursive: true });
|
|
6041
|
+
const db = new Database(path, { readwrite: true, create });
|
|
6042
|
+
try {
|
|
6043
|
+
migrateSchema(db, path);
|
|
6044
|
+
return use(db);
|
|
6045
|
+
} finally {
|
|
6046
|
+
db.close();
|
|
6047
|
+
}
|
|
6048
|
+
}
|
|
6049
|
+
function insertBatch(db, table2, entries) {
|
|
6050
|
+
const insert = db.query(`INSERT INTO ${table2.name} (${table2.keyColumn}, row_json) VALUES (?, ?)` + ` ON CONFLICT (${table2.keyColumn}) DO NOTHING`);
|
|
6051
|
+
const insertAll = db.transaction(() => entries.reduce((appended, { key, body }) => appended + insert.run(key, body).changes, 0));
|
|
6052
|
+
return insertAll.immediate();
|
|
6053
|
+
}
|
|
6054
|
+
function writeSqliteStore(path, rowCount, empty, insert) {
|
|
6055
|
+
const exists = existsSync6(path);
|
|
6056
|
+
if (rowCount > 0)
|
|
6057
|
+
return withSqliteStore(path, !exists, insert);
|
|
6058
|
+
if (exists)
|
|
6059
|
+
withSqliteStore(path, false, () => {
|
|
6060
|
+
return;
|
|
6061
|
+
});
|
|
6062
|
+
return empty;
|
|
6063
|
+
}
|
|
6064
|
+
function appendKind2(path, kind, rows2) {
|
|
6065
|
+
const entries = batchEntries(kind, rows2);
|
|
6066
|
+
const table2 = KIND_TABLES[kind];
|
|
6067
|
+
const appended = writeSqliteStore(path, entries.length, 0, (db) => insertBatch(db, table2, entries));
|
|
6068
|
+
return { path, appended, skipped: entries.length - appended };
|
|
6069
|
+
}
|
|
6070
|
+
function keysOfKind2(path, kind) {
|
|
6071
|
+
if (!existsSync6(path))
|
|
6072
|
+
return new Set;
|
|
6073
|
+
const { name: name2, keyColumn } = KIND_TABLES[kind];
|
|
6074
|
+
const keys = withSqliteStore(path, false, (db) => db.query(`SELECT ${keyColumn} AS key FROM ${name2} ORDER BY seq`).all());
|
|
6075
|
+
return new Set(keys.map(({ key }) => key));
|
|
6076
|
+
}
|
|
6077
|
+
function parsedObject(body) {
|
|
6078
|
+
try {
|
|
6079
|
+
const value = JSON.parse(body);
|
|
6080
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
6081
|
+
} catch {
|
|
6082
|
+
return null;
|
|
6083
|
+
}
|
|
6084
|
+
}
|
|
6085
|
+
function rowOf(body, where) {
|
|
6086
|
+
const value = parsedObject(body);
|
|
6087
|
+
if (value === null) {
|
|
6088
|
+
throw new Error(`effort store: ${where} does not hold a JSON object;` + " no append writes one");
|
|
6089
|
+
}
|
|
6090
|
+
return value;
|
|
6091
|
+
}
|
|
6092
|
+
function readKind2(path, kind) {
|
|
6093
|
+
if (!existsSync6(path))
|
|
6094
|
+
return [];
|
|
6095
|
+
const { name: name2 } = KIND_TABLES[kind];
|
|
6096
|
+
const stored = withSqliteStore(path, false, (db) => db.query(`SELECT seq, row_json AS body FROM ${name2} ORDER BY seq`).all());
|
|
6097
|
+
return stored.map(({ seq, body }) => rowOf(body, `${path}: ${name2} row ${seq}`));
|
|
6098
|
+
}
|
|
6099
|
+
function openSqliteStore(repoRoot) {
|
|
6100
|
+
const path = sqliteStorePath(repoRoot);
|
|
6101
|
+
return {
|
|
6102
|
+
append: (kind, rows2) => appendKind2(path, kind, rows2),
|
|
6103
|
+
keys: (kind) => keysOfKind2(path, kind),
|
|
6104
|
+
read: (kind) => readKind2(path, kind),
|
|
6105
|
+
path: () => path
|
|
6106
|
+
};
|
|
6107
|
+
}
|
|
6108
|
+
var STORE_FILE_NAME = "effort.sqlite", KIND_TABLES, LONE_SURROGATE;
|
|
6109
|
+
var init_sqlite = __esm(() => {
|
|
6110
|
+
init_store();
|
|
6111
|
+
init_migrations();
|
|
6112
|
+
init_types2();
|
|
6113
|
+
init_migrations();
|
|
6050
6114
|
KIND_TABLES = {
|
|
6051
6115
|
sessions: { name: "sessions", keyColumn: "session_id" },
|
|
6052
6116
|
commits: { name: "commits", keyColumn: "sha" }
|
|
@@ -12488,9 +12552,21 @@ function checkStatus(status) {
|
|
|
12488
12552
|
const expected2 = REPORT_STATUSES.join(", ");
|
|
12489
12553
|
throw refusedWrite5(`has status ${describeValue7(status)}, not null or one of ${expected2}`);
|
|
12490
12554
|
}
|
|
12555
|
+
function checkSkillsUsed(skills) {
|
|
12556
|
+
if (skills === undefined || skills === null)
|
|
12557
|
+
return;
|
|
12558
|
+
const isName = (name2) => typeof name2 === "string" && name2.trim().length > 0;
|
|
12559
|
+
if (Array.isArray(skills) && skills.every(isName))
|
|
12560
|
+
return;
|
|
12561
|
+
throw refusedWrite5(`has skills used ${describeValue7(skills)}, not null or a list of non-blank strings`);
|
|
12562
|
+
}
|
|
12563
|
+
function skillsUsedJson(skills) {
|
|
12564
|
+
return skills === undefined || skills === null ? null : JSON.stringify(skills);
|
|
12565
|
+
}
|
|
12491
12566
|
function writeTaskReport(repoRoot, write, seams = {}) {
|
|
12492
12567
|
checkDispatch("task report", write.dispatch, write.outcome);
|
|
12493
12568
|
checkStatus(write.report.status);
|
|
12569
|
+
checkSkillsUsed(write.report.skillsUsed);
|
|
12494
12570
|
const path = sqliteStorePath(repoRoot);
|
|
12495
12571
|
const { sessionId, planStub, taskLine: taskLine2 } = write.dispatch;
|
|
12496
12572
|
const collectedAt = (seams.now ?? (() => new Date))().toISOString();
|
|
@@ -12502,7 +12578,8 @@ function writeTaskReport(repoRoot, write, seams = {}) {
|
|
|
12502
12578
|
taskLine2,
|
|
12503
12579
|
write.report.status,
|
|
12504
12580
|
write.outcome,
|
|
12505
|
-
collectedAt
|
|
12581
|
+
collectedAt,
|
|
12582
|
+
skillsUsedJson(write.report.skillsUsed)
|
|
12506
12583
|
];
|
|
12507
12584
|
const appended = writeSqliteStore(path, ROWS_PER_WRITE2, 0, (db) => db.query(INSERT_REPORT).run(...values).changes);
|
|
12508
12585
|
return { path, appended, skipped: ROWS_PER_WRITE2 - appended };
|
|
@@ -12519,19 +12596,45 @@ function readTaskReportTallies(repoRoot) {
|
|
|
12519
12596
|
reports: row2.reports
|
|
12520
12597
|
}));
|
|
12521
12598
|
}
|
|
12599
|
+
function parseSkillsUsed(sessionId, json) {
|
|
12600
|
+
if (json === null)
|
|
12601
|
+
return null;
|
|
12602
|
+
const list = JSON.parse(json);
|
|
12603
|
+
if (Array.isArray(list) && list.every((name2) => typeof name2 === "string"))
|
|
12604
|
+
return list;
|
|
12605
|
+
throw new Error(`effort store: task report of session ${sessionId} holds skills_used ${json}, not a list of names`);
|
|
12606
|
+
}
|
|
12607
|
+
function readReportedSkills(repoRoot) {
|
|
12608
|
+
const path = sqliteStorePath(repoRoot);
|
|
12609
|
+
if (!existsSync14(path))
|
|
12610
|
+
return [];
|
|
12611
|
+
const rows2 = withSqliteStore(path, false, (db) => db.query(SELECT_REPORTED_SKILLS).all());
|
|
12612
|
+
return rows2.map((row2) => ({
|
|
12613
|
+
sessionId: row2.session_id,
|
|
12614
|
+
planStub: row2.plan_stub,
|
|
12615
|
+
taskLine: row2.task_line,
|
|
12616
|
+
outcome: row2.outcome,
|
|
12617
|
+
skillsUsed: parseSkillsUsed(row2.session_id, row2.skills_used)
|
|
12618
|
+
}));
|
|
12619
|
+
}
|
|
12522
12620
|
var ROWS_PER_WRITE2 = 1, INSERT_REPORT = `
|
|
12523
12621
|
INSERT INTO task_reports (
|
|
12524
12622
|
id, session_id, plan_stub, task_line,
|
|
12525
12623
|
status,
|
|
12526
|
-
outcome, collected_at
|
|
12624
|
+
outcome, collected_at,
|
|
12625
|
+
skills_used
|
|
12527
12626
|
)
|
|
12528
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
12627
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
12529
12628
|
ON CONFLICT (session_id) DO NOTHING
|
|
12530
12629
|
`, SELECT_TALLIES = `
|
|
12531
12630
|
SELECT plan_stub, status, outcome, COUNT(*) AS reports
|
|
12532
12631
|
FROM task_reports
|
|
12533
12632
|
GROUP BY plan_stub, status, outcome
|
|
12534
12633
|
ORDER BY plan_stub, status, outcome
|
|
12634
|
+
`, SELECT_REPORTED_SKILLS = `
|
|
12635
|
+
SELECT session_id, plan_stub, task_line, outcome, skills_used
|
|
12636
|
+
FROM task_reports
|
|
12637
|
+
ORDER BY seq
|
|
12535
12638
|
`;
|
|
12536
12639
|
var init_reports = __esm(() => {
|
|
12537
12640
|
init_parse();
|
|
@@ -25888,6 +25991,80 @@ var init_fix_schema2 = __esm(() => {
|
|
|
25888
25991
|
fix_schema_default = createFixSchemaCommand();
|
|
25889
25992
|
});
|
|
25890
25993
|
|
|
25994
|
+
// src/effort/report-args.ts
|
|
25995
|
+
function splitList(raw) {
|
|
25996
|
+
return raw.split(",").map((part) => part.trim()).filter((part) => part.length > 0);
|
|
25997
|
+
}
|
|
25998
|
+
function asSessionKind(value) {
|
|
25999
|
+
return SESSION_KINDS.find((kind) => kind === value) ?? null;
|
|
26000
|
+
}
|
|
26001
|
+
function combinationErrors(skills, planTyped, filters) {
|
|
26002
|
+
if (!skills) {
|
|
26003
|
+
return planTyped ? ["--plan narrows the skills report and needs --skills"] : [];
|
|
26004
|
+
}
|
|
26005
|
+
return filters.map((flag2) => `${flag2} narrows the session tables, which --skills does not print`);
|
|
26006
|
+
}
|
|
26007
|
+
function parseReportArgs(args) {
|
|
26008
|
+
const errors = [];
|
|
26009
|
+
const kinds = [];
|
|
26010
|
+
const entrypoints = [];
|
|
26011
|
+
const plans = [];
|
|
26012
|
+
const filters = [];
|
|
26013
|
+
let json = false;
|
|
26014
|
+
let skills = false;
|
|
26015
|
+
let planTyped = false;
|
|
26016
|
+
for (const arg of args) {
|
|
26017
|
+
if (arg === "--json") {
|
|
26018
|
+
json = true;
|
|
26019
|
+
} else if (arg === "--skills") {
|
|
26020
|
+
skills = true;
|
|
26021
|
+
} else if (arg === "--kind" || arg === "--entrypoint" || arg === "--plan") {
|
|
26022
|
+
errors.push(`${arg} takes a value, as ${arg}=<value>`);
|
|
26023
|
+
} else if (arg.startsWith("--plan=")) {
|
|
26024
|
+
planTyped = true;
|
|
26025
|
+
const stubs = splitList(arg.slice("--plan=".length));
|
|
26026
|
+
if (stubs.length === 0)
|
|
26027
|
+
errors.push(`--plan names no plan stub: ${arg}`);
|
|
26028
|
+
for (const stub of stubs) {
|
|
26029
|
+
if (!plans.includes(stub))
|
|
26030
|
+
plans.push(stub);
|
|
26031
|
+
}
|
|
26032
|
+
} else if (arg.startsWith("--kind=")) {
|
|
26033
|
+
if (!filters.includes("--kind"))
|
|
26034
|
+
filters.push("--kind");
|
|
26035
|
+
for (const value of splitList(arg.slice("--kind=".length))) {
|
|
26036
|
+
const kind = asSessionKind(value);
|
|
26037
|
+
if (kind === null) {
|
|
26038
|
+
errors.push(`--kind value is not a session kind: ${value}` + ` (one of ${SESSION_KINDS.join(", ")})`);
|
|
26039
|
+
} else if (!kinds.includes(kind)) {
|
|
26040
|
+
kinds.push(kind);
|
|
26041
|
+
}
|
|
26042
|
+
}
|
|
26043
|
+
} else if (arg.startsWith("--entrypoint=")) {
|
|
26044
|
+
if (!filters.includes("--entrypoint"))
|
|
26045
|
+
filters.push("--entrypoint");
|
|
26046
|
+
for (const value of splitList(arg.slice("--entrypoint=".length))) {
|
|
26047
|
+
if (!entrypoints.includes(value))
|
|
26048
|
+
entrypoints.push(value);
|
|
26049
|
+
}
|
|
26050
|
+
} else {
|
|
26051
|
+
errors.push(`unrecognised argument: ${arg}`);
|
|
26052
|
+
}
|
|
26053
|
+
}
|
|
26054
|
+
errors.push(...combinationErrors(skills, planTyped, filters));
|
|
26055
|
+
return {
|
|
26056
|
+
json,
|
|
26057
|
+
kinds: kinds.length === 0 ? null : kinds,
|
|
26058
|
+
entrypoints: entrypoints.length === 0 ? null : entrypoints,
|
|
26059
|
+
skills,
|
|
26060
|
+
plans: plans.length === 0 ? null : plans,
|
|
26061
|
+
errors
|
|
26062
|
+
};
|
|
26063
|
+
}
|
|
26064
|
+
var init_report_args = __esm(() => {
|
|
26065
|
+
init_report();
|
|
26066
|
+
});
|
|
26067
|
+
|
|
25891
26068
|
// src/effort/report-budgets.ts
|
|
25892
26069
|
function usageOf2(row3) {
|
|
25893
26070
|
const { usage } = row3;
|
|
@@ -26110,6 +26287,607 @@ var init_report_format = __esm(() => {
|
|
|
26110
26287
|
BUDGET_RIGHT_ALIGNED = new Set(BUDGET_COLUMNS.slice(2));
|
|
26111
26288
|
});
|
|
26112
26289
|
|
|
26290
|
+
// src/effort/report-skills-format.ts
|
|
26291
|
+
function matchedCell(matches) {
|
|
26292
|
+
const texts = [...new Set(matches.map(({ text: text2 }) => oneLine5(text2)))];
|
|
26293
|
+
return texts.length === 0 ? "-" : texts.join(" / ");
|
|
26294
|
+
}
|
|
26295
|
+
function skillSignalCell(row3) {
|
|
26296
|
+
if (row3.signal === null)
|
|
26297
|
+
return "unknown";
|
|
26298
|
+
if (row3.signal === "unmeasured")
|
|
26299
|
+
return `invoked ${row3.uptake}/${row3.offered}, recurrence not declared`;
|
|
26300
|
+
return row3.signal;
|
|
26301
|
+
}
|
|
26302
|
+
function skillCells(row3) {
|
|
26303
|
+
return [
|
|
26304
|
+
row3.name,
|
|
26305
|
+
formatCount(row3.offered),
|
|
26306
|
+
formatCount(row3.invoked),
|
|
26307
|
+
formatCount(row3.reported),
|
|
26308
|
+
formatCount(row3.recurred),
|
|
26309
|
+
matchedCell(row3.matches),
|
|
26310
|
+
skillSignalCell(row3)
|
|
26311
|
+
];
|
|
26312
|
+
}
|
|
26313
|
+
function lessonCells(row3) {
|
|
26314
|
+
return [
|
|
26315
|
+
row3.id,
|
|
26316
|
+
row3.artifact === null ? "unknown" : oneLine5(row3.artifact),
|
|
26317
|
+
formatCount(row3.injected),
|
|
26318
|
+
formatCount(row3.recurred),
|
|
26319
|
+
matchedCell(row3.matches),
|
|
26320
|
+
row3.signal
|
|
26321
|
+
];
|
|
26322
|
+
}
|
|
26323
|
+
function neverOfferedLine(tallies) {
|
|
26324
|
+
if (tallies.length === 0)
|
|
26325
|
+
return "never offered: none";
|
|
26326
|
+
const entries = tallies.map((tally2) => `${tally2.name} (invoked ${formatCount(tally2.invoked)}, recurred ${formatCount(tally2.recurred)})`);
|
|
26327
|
+
return `never offered: ${entries.join(", ")}`;
|
|
26328
|
+
}
|
|
26329
|
+
function formatMetric(value) {
|
|
26330
|
+
const percent = value.percent === null ? "-" : `${value.percent.toFixed(PERCENT_DECIMALS)}%`;
|
|
26331
|
+
return `${formatCount(value.numerator)}/${formatCount(value.denominator)}, ${percent}`;
|
|
26332
|
+
}
|
|
26333
|
+
function formatPlanCi(reading2) {
|
|
26334
|
+
if (reading2 === null)
|
|
26335
|
+
return `${PLAN_CI_LABEL}: not read`;
|
|
26336
|
+
const failing = reading2.failing.length === 0 ? "" : `, failing: ${reading2.failing.map(oneLine5).join(", ")}`;
|
|
26337
|
+
const sha = reading2.headSha.slice(0, SHORT_SHA_LENGTH);
|
|
26338
|
+
return `${PLAN_CI_LABEL}: ${reading2.verdict} on #${reading2.pr} at ${sha}, read ${reading2.readAt}${failing}`;
|
|
26339
|
+
}
|
|
26340
|
+
function resolverName(resolver) {
|
|
26341
|
+
return resolver ?? "not recorded";
|
|
26342
|
+
}
|
|
26343
|
+
function formatSkillsArm(arm) {
|
|
26344
|
+
const skills = arm.skills.length === 0 ? ["skills: none offered"] : alignRows(SKILL_COLUMNS, arm.skills.map(skillCells), COUNT_COLUMNS);
|
|
26345
|
+
const lessons = arm.lessons.length === 0 ? ["lessons: none injected"] : alignRows(LESSON_COLUMNS, arm.lessons.map(lessonCells), COUNT_COLUMNS);
|
|
26346
|
+
const unknown = arm.unknownSessions === 0 ? [] : [`note: ${formatCount(arm.unknownSessions)} of ${formatCount(arm.sessions)} sessions have unknown invocations, left out of M1 and M2`];
|
|
26347
|
+
return [
|
|
26348
|
+
...skills,
|
|
26349
|
+
neverOfferedLine(arm.neverOffered),
|
|
26350
|
+
"",
|
|
26351
|
+
...lessons,
|
|
26352
|
+
"",
|
|
26353
|
+
`M1 ${formatMetric(arm.m1)} (task lines invoking a skill)`,
|
|
26354
|
+
`M2 ${formatMetric(arm.m2)} (offered skills invoked)`,
|
|
26355
|
+
...unknown
|
|
26356
|
+
];
|
|
26357
|
+
}
|
|
26358
|
+
function indented(indent, line) {
|
|
26359
|
+
return line === "" ? "" : `${indent}${line}`;
|
|
26360
|
+
}
|
|
26361
|
+
function formatSkillsPlan(plan) {
|
|
26362
|
+
const name2 = plan.planStub === null ? "no plan" : `plan ${plan.planStub}`;
|
|
26363
|
+
const sessions = `${formatCount(plan.sessions)} sessions`;
|
|
26364
|
+
const [only] = plan.resolvers;
|
|
26365
|
+
if (plan.resolvers.length === 1 && only !== undefined) {
|
|
26366
|
+
return [
|
|
26367
|
+
`${name2}: ${sessions}, resolver ${resolverName(only.resolver)}`,
|
|
26368
|
+
formatPlanCi(plan.planCi),
|
|
26369
|
+
"",
|
|
26370
|
+
...formatSkillsArm(only)
|
|
26371
|
+
];
|
|
26372
|
+
}
|
|
26373
|
+
const arms = plan.resolvers.flatMap((arm) => [
|
|
26374
|
+
"",
|
|
26375
|
+
`${ARM_INDENT}resolver ${resolverName(arm.resolver)}: ${formatCount(arm.sessions)} sessions`,
|
|
26376
|
+
...formatSkillsArm(arm).map((line) => indented(`${ARM_INDENT}${ARM_INDENT}`, line))
|
|
26377
|
+
]);
|
|
26378
|
+
return [`${name2}: ${sessions}, ${plan.resolvers.length} resolvers`, formatPlanCi(plan.planCi), ...arms];
|
|
26379
|
+
}
|
|
26380
|
+
function formatSkillsReport(report) {
|
|
26381
|
+
const plans = report.plans.length === 0 ? ["", "no task sessions recorded for the plans read"] : report.plans.flatMap((plan) => ["", ...formatSkillsPlan(plan)]);
|
|
26382
|
+
return [SKILLS_REPORT_HEADER, ...plans, "", ...PROBE_FOOTNOTE];
|
|
26383
|
+
}
|
|
26384
|
+
var SKILLS_REPORT_HEADER = "Co-occurrence, not cause: a skill can be invoked and its failure recur for reasons the skill does not cover.", PROBE_FOOTNOTE, PLAN_CI_LABEL = "plan CI", SKILL_COLUMNS, LESSON_COLUMNS, COUNT_COLUMNS, SHORT_SHA_LENGTH = 7, PERCENT_DECIMALS = 1, ARM_INDENT = " ";
|
|
26385
|
+
var init_report_skills_format = __esm(() => {
|
|
26386
|
+
init_report_format();
|
|
26387
|
+
PROBE_FOOTNOTE = [
|
|
26388
|
+
"note: invoked counts are read from each session's own log. Claude Code's",
|
|
26389
|
+
" own usage record (pluginUsage in ~/.claude/.claude.json) counts per",
|
|
26390
|
+
" plugin and never a project skill, so it has no count to agree with."
|
|
26391
|
+
];
|
|
26392
|
+
SKILL_COLUMNS = ["skill", "offered", "invoked", "reported", "recurred", "matched", "signal"];
|
|
26393
|
+
LESSON_COLUMNS = ["lesson", "artifact", "injected", "recurred", "matched", "signal"];
|
|
26394
|
+
COUNT_COLUMNS = new Set(["offered", "invoked", "reported", "recurred", "injected"]);
|
|
26395
|
+
});
|
|
26396
|
+
|
|
26397
|
+
// src/effort/recurrence.ts
|
|
26398
|
+
function findingTexts(fact, finding2) {
|
|
26399
|
+
return FINDING_FIELDS.map((field5) => ({
|
|
26400
|
+
source: "finding",
|
|
26401
|
+
sessionId: fact.sessionId,
|
|
26402
|
+
taskLine: fact.taskLine,
|
|
26403
|
+
field: field5,
|
|
26404
|
+
text: finding2[field5]
|
|
26405
|
+
}));
|
|
26406
|
+
}
|
|
26407
|
+
function entryTexts(fact, source, entry) {
|
|
26408
|
+
return ENTRY_FIELDS.map((field5) => ({
|
|
26409
|
+
source,
|
|
26410
|
+
sessionId: fact.sessionId,
|
|
26411
|
+
taskLine: fact.taskLine,
|
|
26412
|
+
field: field5,
|
|
26413
|
+
text: entry[field5]
|
|
26414
|
+
}));
|
|
26415
|
+
}
|
|
26416
|
+
function taskTexts(fact) {
|
|
26417
|
+
return [
|
|
26418
|
+
...fact.findings.flatMap((finding2) => findingTexts(fact, finding2)),
|
|
26419
|
+
...fact.blockers.flatMap((entry) => entryTexts(fact, "blocker", entry)),
|
|
26420
|
+
...fact.outOfScopeBugs.flatMap((entry) => entryTexts(fact, "out-of-scope-bug", entry))
|
|
26421
|
+
];
|
|
26422
|
+
}
|
|
26423
|
+
function tasksFrom(facts, fromIndex) {
|
|
26424
|
+
const task = facts[fromIndex];
|
|
26425
|
+
if (!Number.isInteger(fromIndex) || task === undefined) {
|
|
26426
|
+
throw new RangeError(`recurrence: fromIndex ${fromIndex} is not a row of ${facts.length} fact rows`);
|
|
26427
|
+
}
|
|
26428
|
+
if (task.planStub === null)
|
|
26429
|
+
return [task];
|
|
26430
|
+
return facts.slice(fromIndex).filter(({ planStub: planStub2 }) => planStub2 === task.planStub);
|
|
26431
|
+
}
|
|
26432
|
+
function failingNames(planStub2, planCi) {
|
|
26433
|
+
if (planStub2 === null)
|
|
26434
|
+
return [];
|
|
26435
|
+
const names = new Set(planCi.filter((row3) => row3.planStub === planStub2).flatMap(({ failing }) => failing));
|
|
26436
|
+
return [...names].map((text2) => ({ source: "plan-ci", sessionId: null, taskLine: null, field: "failing", text: text2 }));
|
|
26437
|
+
}
|
|
26438
|
+
function findRecurrences(strings, facts, fromIndex, planCi) {
|
|
26439
|
+
const tasks = tasksFrom(facts, fromIndex);
|
|
26440
|
+
const searched = [...new Set(strings)].filter((string) => string !== "");
|
|
26441
|
+
const haystacks = [...tasks.flatMap(taskTexts), ...failingNames(tasks[0]?.planStub ?? null, planCi)];
|
|
26442
|
+
return haystacks.flatMap(({ text: text2, ...where }) => {
|
|
26443
|
+
if (text2 === null)
|
|
26444
|
+
return [];
|
|
26445
|
+
return searched.filter((string) => text2.includes(string)).map((string) => ({ string, ...where, text: text2 }));
|
|
26446
|
+
});
|
|
26447
|
+
}
|
|
26448
|
+
var FINDING_FIELDS, ENTRY_FIELDS;
|
|
26449
|
+
var init_recurrence = __esm(() => {
|
|
26450
|
+
FINDING_FIELDS = ["trigger", "what", "cause", "artifact"];
|
|
26451
|
+
ENTRY_FIELDS = ["what", "artifact"];
|
|
26452
|
+
});
|
|
26453
|
+
|
|
26454
|
+
// src/effort/store/plan-ci.ts
|
|
26455
|
+
import { existsSync as existsSync29, readdirSync as readdirSync10 } from "fs";
|
|
26456
|
+
import { resolve as resolve17 } from "path";
|
|
26457
|
+
function refusedWrite7(reason) {
|
|
26458
|
+
return new Error(`effort store: plan CI write ${reason}; nothing written`);
|
|
26459
|
+
}
|
|
26460
|
+
function checkText3(name2, value) {
|
|
26461
|
+
const problem = value === null ? "is null" : textProblem(value);
|
|
26462
|
+
if (problem !== null)
|
|
26463
|
+
throw refusedWrite7(`has a ${name2} that ${problem}`);
|
|
26464
|
+
}
|
|
26465
|
+
function checkRow(row3) {
|
|
26466
|
+
checkText3("plan stub", row3.planStub);
|
|
26467
|
+
checkText3("head sha", row3.headSha);
|
|
26468
|
+
checkText3("read time", row3.readAt);
|
|
26469
|
+
if (!Number.isSafeInteger(row3.pr) || row3.pr <= 0) {
|
|
26470
|
+
throw refusedWrite7(`has pull request ${describeValue7(row3.pr)}, not a whole number above zero`);
|
|
26471
|
+
}
|
|
26472
|
+
const verdict = row3.verdict;
|
|
26473
|
+
if (!PLAN_CI_VERDICTS.some((known) => known === verdict)) {
|
|
26474
|
+
throw refusedWrite7(`has verdict ${describeValue7(verdict)}, not one of ${PLAN_CI_VERDICTS.join(", ")}`);
|
|
26475
|
+
}
|
|
26476
|
+
const failing = row3.failing;
|
|
26477
|
+
if (!Array.isArray(failing))
|
|
26478
|
+
throw refusedWrite7(`has failing ${describeValue7(failing)}, not a list`);
|
|
26479
|
+
for (const name2 of failing)
|
|
26480
|
+
checkText3("failing check name", name2);
|
|
26481
|
+
if (row3.verdict === "red" !== failing.length > 0) {
|
|
26482
|
+
throw refusedWrite7(`has verdict ${row3.verdict} beside ${failing.length} failing checks`);
|
|
26483
|
+
}
|
|
26484
|
+
}
|
|
26485
|
+
function planStubOfBranch(headRefName, planStubs) {
|
|
26486
|
+
const branchStub = attributeBranch(headRefName).stub;
|
|
26487
|
+
if (branchStub === null)
|
|
26488
|
+
return null;
|
|
26489
|
+
const resolution = resolvePlanStub(branchStub, planStubs);
|
|
26490
|
+
if (resolution.stub !== null)
|
|
26491
|
+
return resolution.stub;
|
|
26492
|
+
return resolution.match === "ambiguous" ? null : branchStub;
|
|
26493
|
+
}
|
|
26494
|
+
function planCiReading(pullRequest, rows2, planStubs, readAt) {
|
|
26495
|
+
const verdict = verdictOf2(rows2);
|
|
26496
|
+
if (verdict === "pending") {
|
|
26497
|
+
return { row: null, skipped: `the checks of #${pullRequest.number} are still running` };
|
|
26498
|
+
}
|
|
26499
|
+
const planStub2 = planStubOfBranch(pullRequest.headRefName, planStubs);
|
|
26500
|
+
if (planStub2 === null) {
|
|
26501
|
+
return { row: null, skipped: `the branch "${pullRequest.headRefName}" of #${pullRequest.number} resolves to no plan` };
|
|
26502
|
+
}
|
|
26503
|
+
const failing = failingRows(rows2).map(({ name: name2 }) => name2);
|
|
26504
|
+
return {
|
|
26505
|
+
row: { planStub: planStub2, pr: pullRequest.number, headSha: pullRequest.headRefOid, verdict, failing, readAt },
|
|
26506
|
+
skipped: null
|
|
26507
|
+
};
|
|
26508
|
+
}
|
|
26509
|
+
function writePlanCi(repoRoot, row3) {
|
|
26510
|
+
checkRow(row3);
|
|
26511
|
+
const path4 = sqliteStorePath(repoRoot);
|
|
26512
|
+
const values = [row3.planStub, row3.pr, row3.headSha, row3.verdict, JSON.stringify(row3.failing), row3.readAt];
|
|
26513
|
+
const appended2 = writeSqliteStore(path4, 1, 0, (db) => db.query(INSERT_PLAN_CI).run(...values).changes);
|
|
26514
|
+
return { path: path4, appended: appended2 };
|
|
26515
|
+
}
|
|
26516
|
+
function rowOf4(stored) {
|
|
26517
|
+
const failing = JSON.parse(stored.failing);
|
|
26518
|
+
return {
|
|
26519
|
+
planStub: stored.plan_stub,
|
|
26520
|
+
pr: stored.pr,
|
|
26521
|
+
headSha: stored.head_sha,
|
|
26522
|
+
verdict: stored.verdict,
|
|
26523
|
+
failing: Array.isArray(failing) ? failing.map(String) : [],
|
|
26524
|
+
readAt: stored.read_at
|
|
26525
|
+
};
|
|
26526
|
+
}
|
|
26527
|
+
function readPlanCi(repoRoot, planStub2) {
|
|
26528
|
+
const path4 = sqliteStorePath(repoRoot);
|
|
26529
|
+
if (!existsSync29(path4))
|
|
26530
|
+
return [];
|
|
26531
|
+
const rows2 = withSqliteStore(path4, false, (db) => planStub2 === undefined ? db.query(`${SELECT_COLUMNS} ORDER BY seq`).all() : db.query(`${SELECT_COLUMNS} WHERE plan_stub = ? ORDER BY seq`).all(planStub2));
|
|
26532
|
+
return rows2.map(rowOf4);
|
|
26533
|
+
}
|
|
26534
|
+
function planStubsUnder(repoRoot, planDir) {
|
|
26535
|
+
const dir = resolve17(repoRoot, planDir);
|
|
26536
|
+
return existsSync29(dir) ? planStubsFromFileNames(readdirSync10(dir)) : [];
|
|
26537
|
+
}
|
|
26538
|
+
function messageOf12(error) {
|
|
26539
|
+
return error instanceof Error ? error.message : String(error);
|
|
26540
|
+
}
|
|
26541
|
+
function recordPlanCi(input) {
|
|
26542
|
+
const now = input.now ?? (() => new Date);
|
|
26543
|
+
let row3 = null;
|
|
26544
|
+
try {
|
|
26545
|
+
const planStubs = planStubsUnder(input.repoRoot, input.planDir);
|
|
26546
|
+
const reading2 = planCiReading(input.pullRequest, input.rows, planStubs, now().toISOString());
|
|
26547
|
+
if (reading2.row === null)
|
|
26548
|
+
return { row: null, skipped: reading2.skipped, appended: 0, problem: null };
|
|
26549
|
+
row3 = reading2.row;
|
|
26550
|
+
const { appended: appended2 } = writePlanCi(input.repoRoot, row3);
|
|
26551
|
+
return { row: row3, skipped: null, appended: appended2, problem: null };
|
|
26552
|
+
} catch (error) {
|
|
26553
|
+
const problem = `the CI reading of #${input.pullRequest.number} was not stored: ${messageOf12(error)}`;
|
|
26554
|
+
input.warn(problem);
|
|
26555
|
+
return { row: row3, skipped: null, appended: 0, problem };
|
|
26556
|
+
}
|
|
26557
|
+
}
|
|
26558
|
+
var PLAN_CI_VERDICTS, INSERT_PLAN_CI = `
|
|
26559
|
+
INSERT INTO plan_ci (plan_stub, pr, head_sha, verdict, failing, read_at)
|
|
26560
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
26561
|
+
ON CONFLICT (pr, head_sha, read_at) DO NOTHING
|
|
26562
|
+
`, SELECT_COLUMNS = "SELECT plan_stub, pr, head_sha, verdict, failing, read_at FROM plan_ci";
|
|
26563
|
+
var init_plan_ci = __esm(() => {
|
|
26564
|
+
init_checks();
|
|
26565
|
+
init_attribution();
|
|
26566
|
+
init_findings();
|
|
26567
|
+
init_sqlite();
|
|
26568
|
+
PLAN_CI_VERDICTS = ["green", "red", "none"];
|
|
26569
|
+
});
|
|
26570
|
+
|
|
26571
|
+
// src/effort/skill-facts.ts
|
|
26572
|
+
import { existsSync as existsSync30 } from "fs";
|
|
26573
|
+
function selectEntries(table2) {
|
|
26574
|
+
return `SELECT session_id, what, artifact FROM ${table2} ORDER BY seq`;
|
|
26575
|
+
}
|
|
26576
|
+
function parseNames(column, sessionId, json) {
|
|
26577
|
+
if (json === null)
|
|
26578
|
+
return null;
|
|
26579
|
+
const list = JSON.parse(json);
|
|
26580
|
+
if (Array.isArray(list) && list.every((name2) => typeof name2 === "string"))
|
|
26581
|
+
return list;
|
|
26582
|
+
throw new Error(`effort store: ${column} of session ${sessionId} holds ${json}, not a list of names`);
|
|
26583
|
+
}
|
|
26584
|
+
function bySession(rows2, toEntry) {
|
|
26585
|
+
const groups = new Map;
|
|
26586
|
+
for (const row3 of rows2) {
|
|
26587
|
+
const group = groups.get(row3.session_id) ?? [];
|
|
26588
|
+
groups.set(row3.session_id, [...group, toEntry(row3)]);
|
|
26589
|
+
}
|
|
26590
|
+
return groups;
|
|
26591
|
+
}
|
|
26592
|
+
function entryOf({ what, artifact }) {
|
|
26593
|
+
return { what, artifact };
|
|
26594
|
+
}
|
|
26595
|
+
function findingOf(row3) {
|
|
26596
|
+
return {
|
|
26597
|
+
kind: row3.kind,
|
|
26598
|
+
trigger: row3.trigger,
|
|
26599
|
+
what: row3.what,
|
|
26600
|
+
cause: row3.cause,
|
|
26601
|
+
resolution: row3.resolution,
|
|
26602
|
+
artifact: row3.artifact,
|
|
26603
|
+
signal: row3.signal
|
|
26604
|
+
};
|
|
26605
|
+
}
|
|
26606
|
+
function readSessionRows(path4) {
|
|
26607
|
+
return withSqliteStore(path4, false, (db) => {
|
|
26608
|
+
const offers = db.query(SELECT_OFFERS).all();
|
|
26609
|
+
return {
|
|
26610
|
+
offers: new Map(offers.map((row3) => [row3.session_id, {
|
|
26611
|
+
resolver: row3.resolver,
|
|
26612
|
+
skillsOffered: parseNames("skills_offered", row3.session_id, row3.skills_offered),
|
|
26613
|
+
lessonsOffered: parseNames("lessons_offered", row3.session_id, row3.lessons_offered)
|
|
26614
|
+
}])),
|
|
26615
|
+
findings: bySession(db.query(SELECT_FINDINGS2).all(), findingOf),
|
|
26616
|
+
blockers: bySession(db.query(selectEntries("blockers")).all(), entryOf),
|
|
26617
|
+
outOfScopeBugs: bySession(db.query(selectEntries("out_of_scope_bugs")).all(), entryOf)
|
|
26618
|
+
};
|
|
26619
|
+
});
|
|
26620
|
+
}
|
|
26621
|
+
function invocationsBySession(invocations) {
|
|
26622
|
+
const sessions = new Map;
|
|
26623
|
+
for (const invocation of invocations) {
|
|
26624
|
+
const held = sessions.get(invocation.sessionId) ?? [];
|
|
26625
|
+
if (held === UNKNOWN_SKILL_COUNT || invocation.count === UNKNOWN_SKILL_COUNT) {
|
|
26626
|
+
sessions.set(invocation.sessionId, UNKNOWN_SKILL_COUNT);
|
|
26627
|
+
continue;
|
|
26628
|
+
}
|
|
26629
|
+
const { name: name2, count: count2 } = invocation;
|
|
26630
|
+
const counted5 = held.some((use) => use.name === name2) ? held.map((use) => use.name === name2 ? { name: name2, count: use.count + count2 } : use) : [...held, { name: name2, count: count2 }];
|
|
26631
|
+
sessions.set(invocation.sessionId, counted5);
|
|
26632
|
+
}
|
|
26633
|
+
return sessions;
|
|
26634
|
+
}
|
|
26635
|
+
function bareNames(names) {
|
|
26636
|
+
return names === null ? null : [...new Set(names.map((name2) => bareSkillName(name2)))];
|
|
26637
|
+
}
|
|
26638
|
+
function orderedReports(reports, plans) {
|
|
26639
|
+
const order = plans === undefined ? [...new Set(reports.map(({ planStub: planStub2 }) => planStub2))] : [...new Set(plans)];
|
|
26640
|
+
return order.flatMap((plan) => reports.filter(({ planStub: planStub2 }) => planStub2 === plan));
|
|
26641
|
+
}
|
|
26642
|
+
function readSkillFacts(repoRoot, plans) {
|
|
26643
|
+
if (!existsSync30(sqliteStorePath(repoRoot)))
|
|
26644
|
+
return [];
|
|
26645
|
+
const reports = orderedReports(readReportedSkills(repoRoot), plans);
|
|
26646
|
+
if (reports.length === 0)
|
|
26647
|
+
return [];
|
|
26648
|
+
const rows2 = readSessionRows(sqliteStorePath(repoRoot));
|
|
26649
|
+
const invoked = invocationsBySession(readSkillInvocations(repoRoot));
|
|
26650
|
+
const planCi = new Map;
|
|
26651
|
+
for (const row3 of readPlanCi(repoRoot))
|
|
26652
|
+
planCi.set(row3.planStub, [...planCi.get(row3.planStub) ?? [], row3]);
|
|
26653
|
+
return reports.map((report) => {
|
|
26654
|
+
const offer = rows2.offers.get(report.sessionId);
|
|
26655
|
+
return {
|
|
26656
|
+
sessionId: report.sessionId,
|
|
26657
|
+
planStub: report.planStub,
|
|
26658
|
+
taskLine: report.taskLine,
|
|
26659
|
+
outcome: report.outcome,
|
|
26660
|
+
skillsUsed: bareNames(report.skillsUsed),
|
|
26661
|
+
resolver: offer?.resolver ?? null,
|
|
26662
|
+
skillsOffered: offer?.skillsOffered ?? null,
|
|
26663
|
+
lessonsOffered: offer?.lessonsOffered ?? null,
|
|
26664
|
+
invoked: invoked.get(report.sessionId) ?? [],
|
|
26665
|
+
findings: rows2.findings.get(report.sessionId) ?? [],
|
|
26666
|
+
blockers: rows2.blockers.get(report.sessionId) ?? [],
|
|
26667
|
+
outOfScopeBugs: rows2.outOfScopeBugs.get(report.sessionId) ?? [],
|
|
26668
|
+
planCi: report.planStub === null ? [] : planCi.get(report.planStub) ?? []
|
|
26669
|
+
};
|
|
26670
|
+
});
|
|
26671
|
+
}
|
|
26672
|
+
var SELECT_OFFERS = "SELECT session_id, resolver, skills_offered, lessons_offered FROM dispatches ORDER BY seq", SELECT_FINDINGS2 = `
|
|
26673
|
+
SELECT session_id, kind, trigger, what, cause, resolution, artifact, signal
|
|
26674
|
+
FROM findings
|
|
26675
|
+
ORDER BY seq
|
|
26676
|
+
`;
|
|
26677
|
+
var init_skill_facts = __esm(() => {
|
|
26678
|
+
init_skill_names();
|
|
26679
|
+
init_plan_ci();
|
|
26680
|
+
init_reports();
|
|
26681
|
+
init_skill_invocations();
|
|
26682
|
+
init_sqlite();
|
|
26683
|
+
});
|
|
26684
|
+
|
|
26685
|
+
// src/effort/skill-signals.ts
|
|
26686
|
+
function invokedNames(fact) {
|
|
26687
|
+
return fact.invoked === UNKNOWN_SKILL_COUNT ? [] : fact.invoked.map(({ name: name2 }) => name2);
|
|
26688
|
+
}
|
|
26689
|
+
function unique(names) {
|
|
26690
|
+
return [...new Set(names)];
|
|
26691
|
+
}
|
|
26692
|
+
function rowsWhere(facts, holds) {
|
|
26693
|
+
return facts.filter(holds).length;
|
|
26694
|
+
}
|
|
26695
|
+
function indicesWhere(facts, holds) {
|
|
26696
|
+
return facts.flatMap((fact, index) => holds(fact) ? [index] : []);
|
|
26697
|
+
}
|
|
26698
|
+
function recurrencesFrom(strings, facts, from, match) {
|
|
26699
|
+
if (strings.length === 0)
|
|
26700
|
+
return { recurred: 0, matches: [] };
|
|
26701
|
+
const found = from.map((index) => match(strings, facts, index, facts[index]?.planCi ?? []));
|
|
26702
|
+
const matches = new Map;
|
|
26703
|
+
for (const recurrence of found.flat()) {
|
|
26704
|
+
const { string, source, sessionId, field: field5, text: text2 } = recurrence;
|
|
26705
|
+
const key = JSON.stringify([string, source, sessionId, field5, text2]);
|
|
26706
|
+
if (!matches.has(key))
|
|
26707
|
+
matches.set(key, recurrence);
|
|
26708
|
+
}
|
|
26709
|
+
return {
|
|
26710
|
+
recurred: found.filter((answer3) => answer3.length > 0).length,
|
|
26711
|
+
matches: [...matches.values()]
|
|
26712
|
+
};
|
|
26713
|
+
}
|
|
26714
|
+
function tallySkill(name2, facts, strings, match) {
|
|
26715
|
+
const offers = (fact) => fact.skillsOffered?.includes(name2) ?? false;
|
|
26716
|
+
const invokes = (fact) => invokedNames(fact).includes(name2);
|
|
26717
|
+
return {
|
|
26718
|
+
name: name2,
|
|
26719
|
+
offered: rowsWhere(facts, offers),
|
|
26720
|
+
invoked: rowsWhere(facts, invokes),
|
|
26721
|
+
uptake: rowsWhere(facts, (fact) => offers(fact) && invokes(fact)),
|
|
26722
|
+
reported: rowsWhere(facts, (fact) => fact.skillsUsed?.includes(name2) ?? false),
|
|
26723
|
+
unknown: rowsWhere(facts, (fact) => offers(fact) && fact.invoked === UNKNOWN_SKILL_COUNT),
|
|
26724
|
+
...recurrencesFrom(strings, facts, indicesWhere(facts, invokes), match)
|
|
26725
|
+
};
|
|
26726
|
+
}
|
|
26727
|
+
function skillSignalOf(tally2, declared) {
|
|
26728
|
+
if (tally2.recurred > 0)
|
|
26729
|
+
return "recurring";
|
|
26730
|
+
if (tally2.invoked > 0 && !declared)
|
|
26731
|
+
return "unmeasured";
|
|
26732
|
+
if (tally2.invoked > 0)
|
|
26733
|
+
return "earning";
|
|
26734
|
+
if (tally2.unknown > 0)
|
|
26735
|
+
return null;
|
|
26736
|
+
return "ignored";
|
|
26737
|
+
}
|
|
26738
|
+
function skillSignals(facts, match, failureStrings) {
|
|
26739
|
+
const names = unique(facts.flatMap((fact) => [...fact.skillsOffered ?? [], ...invokedNames(fact)]));
|
|
26740
|
+
const tallies = names.map((name2) => tallySkill(name2, facts, failureStrings.get(name2) ?? [], match));
|
|
26741
|
+
return {
|
|
26742
|
+
skills: tallies.filter(({ offered: offered2 }) => offered2 > 0).map((tally2) => ({
|
|
26743
|
+
...tally2,
|
|
26744
|
+
signal: skillSignalOf(tally2, (failureStrings.get(tally2.name) ?? []).length > 0)
|
|
26745
|
+
})),
|
|
26746
|
+
neverOffered: tallies.filter(({ offered: offered2 }) => offered2 === 0)
|
|
26747
|
+
};
|
|
26748
|
+
}
|
|
26749
|
+
function lessonSignals(facts, match, artifacts) {
|
|
26750
|
+
const ids = unique(facts.flatMap((fact) => fact.lessonsOffered ?? []));
|
|
26751
|
+
return ids.map((id) => {
|
|
26752
|
+
const artifact = artifacts.get(id) ?? null;
|
|
26753
|
+
const injects = (fact) => fact.lessonsOffered?.includes(id) ?? false;
|
|
26754
|
+
const found = recurrencesFrom(artifact === null ? [] : [artifact], facts, indicesWhere(facts, injects), match);
|
|
26755
|
+
return {
|
|
26756
|
+
id,
|
|
26757
|
+
artifact,
|
|
26758
|
+
injected: rowsWhere(facts, injects),
|
|
26759
|
+
...found,
|
|
26760
|
+
signal: found.recurred > 0 ? "injected-recurring" : "injected"
|
|
26761
|
+
};
|
|
26762
|
+
});
|
|
26763
|
+
}
|
|
26764
|
+
var init_skill_signals = __esm(() => {
|
|
26765
|
+
init_skill_invocations();
|
|
26766
|
+
});
|
|
26767
|
+
|
|
26768
|
+
// src/effort/report-skills.ts
|
|
26769
|
+
import { readFileSync as readFileSync33 } from "fs";
|
|
26770
|
+
function readTextFile2(path4) {
|
|
26771
|
+
try {
|
|
26772
|
+
return readFileSync33(path4, "utf8");
|
|
26773
|
+
} catch {
|
|
26774
|
+
return null;
|
|
26775
|
+
}
|
|
26776
|
+
}
|
|
26777
|
+
function declaredStrings(text2) {
|
|
26778
|
+
const data = text2 === null ? null : readFrontmatter(text2);
|
|
26779
|
+
const value = data?.[FAILURE_STRINGS_KEY];
|
|
26780
|
+
if (!Array.isArray(value))
|
|
26781
|
+
return [];
|
|
26782
|
+
return value.filter((entry) => typeof entry === "string" && entry !== "");
|
|
26783
|
+
}
|
|
26784
|
+
function failureStringsOf(resolution, readText7 = readTextFile2) {
|
|
26785
|
+
const declared = new Map;
|
|
26786
|
+
for (const item of resolution.items) {
|
|
26787
|
+
if (item.kind !== "skill" || item.state !== "served")
|
|
26788
|
+
continue;
|
|
26789
|
+
const strings = declaredStrings(readText7(item.winner.path));
|
|
26790
|
+
if (strings.length > 0)
|
|
26791
|
+
declared.set(item.name, strings);
|
|
26792
|
+
}
|
|
26793
|
+
return declared;
|
|
26794
|
+
}
|
|
26795
|
+
function lessonArtifactsOf(lessons) {
|
|
26796
|
+
const artifacts = new Map;
|
|
26797
|
+
const seen = new Set;
|
|
26798
|
+
for (const { id, artifact } of lessons) {
|
|
26799
|
+
if (seen.has(id))
|
|
26800
|
+
continue;
|
|
26801
|
+
seen.add(id);
|
|
26802
|
+
if (artifact !== null)
|
|
26803
|
+
artifacts.set(id, artifact);
|
|
26804
|
+
}
|
|
26805
|
+
return artifacts;
|
|
26806
|
+
}
|
|
26807
|
+
function readHeldLessons(seams) {
|
|
26808
|
+
return readScopes(seams).flatMap((listing2) => listing2.records.flatMap(({ instinct }) => instinct === null ? [] : [{ id: instinct.id, artifact: instinct.artifact }]));
|
|
26809
|
+
}
|
|
26810
|
+
function groupBy(values, key) {
|
|
26811
|
+
const groups = new Map;
|
|
26812
|
+
for (const value of values) {
|
|
26813
|
+
const group = groups.get(key(value)) ?? [];
|
|
26814
|
+
groups.set(key(value), [...group, value]);
|
|
26815
|
+
}
|
|
26816
|
+
return groups;
|
|
26817
|
+
}
|
|
26818
|
+
function metric(numerator, denominator) {
|
|
26819
|
+
return {
|
|
26820
|
+
numerator,
|
|
26821
|
+
denominator,
|
|
26822
|
+
percent: denominator === 0 ? null : numerator / denominator * 100
|
|
26823
|
+
};
|
|
26824
|
+
}
|
|
26825
|
+
function invokedNames2(fact) {
|
|
26826
|
+
return fact.invoked === UNKNOWN_SKILL_COUNT ? [] : [...new Set(fact.invoked.map(({ name: name2 }) => name2))];
|
|
26827
|
+
}
|
|
26828
|
+
function m1Of(known) {
|
|
26829
|
+
const pairs = new Set(known.flatMap((fact) => invokedNames2(fact).map((name2) => JSON.stringify([fact.taskLine, name2]))));
|
|
26830
|
+
return metric(pairs.size, new Set(known.map(({ taskLine: taskLine2 }) => taskLine2)).size);
|
|
26831
|
+
}
|
|
26832
|
+
function m2Of(known) {
|
|
26833
|
+
const offered2 = known.flatMap((fact) => [...new Set(fact.skillsOffered ?? [])].map((name2) => ({ fact, name: name2 })));
|
|
26834
|
+
const taken = offered2.filter(({ fact, name: name2 }) => invokedNames2(fact).includes(name2));
|
|
26835
|
+
return metric(taken.length, offered2.length);
|
|
26836
|
+
}
|
|
26837
|
+
function planMatcher(planFacts) {
|
|
26838
|
+
const indices = new Map(planFacts.map((fact, index) => [fact, index]));
|
|
26839
|
+
return (strings, facts, fromIndex, planCi) => {
|
|
26840
|
+
const row3 = facts[fromIndex];
|
|
26841
|
+
const index = row3 === undefined ? undefined : indices.get(row3);
|
|
26842
|
+
if (index === undefined) {
|
|
26843
|
+
throw new RangeError(`skills report: fromIndex ${fromIndex} is not a row of the plan's ${planFacts.length}`);
|
|
26844
|
+
}
|
|
26845
|
+
return findRecurrences(strings, planFacts, index, planCi);
|
|
26846
|
+
};
|
|
26847
|
+
}
|
|
26848
|
+
function armOf(resolver, facts, match, failureStrings, artifacts) {
|
|
26849
|
+
const known = facts.filter((fact) => fact.invoked !== UNKNOWN_SKILL_COUNT);
|
|
26850
|
+
const { skills, neverOffered } = skillSignals(facts, match, failureStrings);
|
|
26851
|
+
return {
|
|
26852
|
+
resolver,
|
|
26853
|
+
sessions: facts.length,
|
|
26854
|
+
unknownSessions: facts.length - known.length,
|
|
26855
|
+
skills,
|
|
26856
|
+
neverOffered,
|
|
26857
|
+
lessons: lessonSignals(facts, match, artifacts),
|
|
26858
|
+
m1: m1Of(known),
|
|
26859
|
+
m2: m2Of(known)
|
|
26860
|
+
};
|
|
26861
|
+
}
|
|
26862
|
+
function latestReading(readings) {
|
|
26863
|
+
return readings.reduce((latest, reading2) => latest === null || reading2.readAt >= latest.readAt ? reading2 : latest, null);
|
|
26864
|
+
}
|
|
26865
|
+
function skillsReportOf(facts, failureStrings, artifacts) {
|
|
26866
|
+
const plans = [...groupBy(facts, ({ planStub: planStub2 }) => planStub2)].map(([planStub2, planFacts]) => {
|
|
26867
|
+
const match = planMatcher(planFacts);
|
|
26868
|
+
const arms = [...groupBy(planFacts, ({ resolver }) => resolver)];
|
|
26869
|
+
return {
|
|
26870
|
+
planStub: planStub2,
|
|
26871
|
+
sessions: planFacts.length,
|
|
26872
|
+
planCi: latestReading(planFacts[0]?.planCi ?? []),
|
|
26873
|
+
resolvers: arms.map(([resolver, armFacts]) => armOf(resolver, armFacts, match, failureStrings, artifacts))
|
|
26874
|
+
};
|
|
26875
|
+
});
|
|
26876
|
+
return { plans };
|
|
26877
|
+
}
|
|
26878
|
+
function buildSkillsReport(input) {
|
|
26879
|
+
const facts = readSkillFacts(input.repoRoot, input.plans);
|
|
26880
|
+
return skillsReportOf(facts, failureStringsOf(input.resolution, input.readText ?? readTextFile2), lessonArtifactsOf(input.lessons));
|
|
26881
|
+
}
|
|
26882
|
+
var FAILURE_STRINGS_KEY = "failure_strings";
|
|
26883
|
+
var init_report_skills = __esm(() => {
|
|
26884
|
+
init_instinct_records();
|
|
26885
|
+
init_recurrence();
|
|
26886
|
+
init_skill_facts();
|
|
26887
|
+
init_skill_signals();
|
|
26888
|
+
init_skill_invocations();
|
|
26889
|
+
});
|
|
26890
|
+
|
|
26113
26891
|
// src/effort/report.ts
|
|
26114
26892
|
import { homedir as homedir5 } from "os";
|
|
26115
26893
|
function asReportRows(rows2) {
|
|
@@ -26270,47 +27048,6 @@ function summariseSessions(rows2, filters = { kinds: null, entrypoints: null },
|
|
|
26270
27048
|
budgets: budgetedSessions(rows2, budgets)
|
|
26271
27049
|
};
|
|
26272
27050
|
}
|
|
26273
|
-
function splitList(raw) {
|
|
26274
|
-
return raw.split(",").map((part) => part.trim()).filter((part) => part.length > 0);
|
|
26275
|
-
}
|
|
26276
|
-
function asSessionKind(value) {
|
|
26277
|
-
return SESSION_KINDS.find((kind) => kind === value) ?? null;
|
|
26278
|
-
}
|
|
26279
|
-
function parseReportArgs(args) {
|
|
26280
|
-
const errors = [];
|
|
26281
|
-
const kinds = [];
|
|
26282
|
-
const entrypoints = [];
|
|
26283
|
-
let json = false;
|
|
26284
|
-
for (const arg of args) {
|
|
26285
|
-
if (arg === "--json") {
|
|
26286
|
-
json = true;
|
|
26287
|
-
} else if (arg === "--kind" || arg === "--entrypoint") {
|
|
26288
|
-
errors.push(`${arg} takes a value, as ${arg}=<value>`);
|
|
26289
|
-
} else if (arg.startsWith("--kind=")) {
|
|
26290
|
-
for (const value of splitList(arg.slice("--kind=".length))) {
|
|
26291
|
-
const kind = asSessionKind(value);
|
|
26292
|
-
if (kind === null) {
|
|
26293
|
-
errors.push(`--kind value is not a session kind: ${value}` + ` (one of ${SESSION_KINDS.join(", ")})`);
|
|
26294
|
-
} else if (!kinds.includes(kind)) {
|
|
26295
|
-
kinds.push(kind);
|
|
26296
|
-
}
|
|
26297
|
-
}
|
|
26298
|
-
} else if (arg.startsWith("--entrypoint=")) {
|
|
26299
|
-
for (const value of splitList(arg.slice("--entrypoint=".length))) {
|
|
26300
|
-
if (!entrypoints.includes(value))
|
|
26301
|
-
entrypoints.push(value);
|
|
26302
|
-
}
|
|
26303
|
-
} else {
|
|
26304
|
-
errors.push(`unrecognised argument: ${arg}`);
|
|
26305
|
-
}
|
|
26306
|
-
}
|
|
26307
|
-
return {
|
|
26308
|
-
json,
|
|
26309
|
-
kinds: kinds.length === 0 ? null : kinds,
|
|
26310
|
-
entrypoints: entrypoints.length === 0 ? null : entrypoints,
|
|
26311
|
-
errors
|
|
26312
|
-
};
|
|
26313
|
-
}
|
|
26314
27051
|
function resolveStore(store, roots) {
|
|
26315
27052
|
if (store !== undefined)
|
|
26316
27053
|
return store;
|
|
@@ -26325,14 +27062,50 @@ function buildReport(options) {
|
|
|
26325
27062
|
entrypoints: options.entrypoints ?? null
|
|
26326
27063
|
}, readTaskReportTallies(repoRoot), readPreflightHalts(repoRoot), readSessionBudgets(repoRoot));
|
|
26327
27064
|
}
|
|
27065
|
+
function readSkillsReport(options) {
|
|
27066
|
+
const { repoRoot: root, home, entry } = options;
|
|
27067
|
+
const { config } = loadConfig({ root, home });
|
|
27068
|
+
const pinned = entry === undefined ? {} : { entry };
|
|
27069
|
+
return buildSkillsReport({
|
|
27070
|
+
repoRoot: root,
|
|
27071
|
+
...options.plans === null || options.plans === undefined ? {} : { plans: options.plans },
|
|
27072
|
+
resolution: resolveSessionTiers({ root, home, settings: config, ...pinned }),
|
|
27073
|
+
lessons: readHeldLessons({ home, projectRoot: root, ...pinned })
|
|
27074
|
+
});
|
|
27075
|
+
}
|
|
26328
27076
|
function refuse4(problems) {
|
|
26329
27077
|
throw new CommandExit(1, problems.map((problem) => `rafa effort report: ${problem}`).join(`
|
|
26330
27078
|
`));
|
|
26331
27079
|
}
|
|
27080
|
+
function writeSkillsReport(plans, json, repoRoot) {
|
|
27081
|
+
let built;
|
|
27082
|
+
try {
|
|
27083
|
+
built = readSkillsReport({ repoRoot, home: homedir5(), plans });
|
|
27084
|
+
} catch (error) {
|
|
27085
|
+
if (!(error instanceof ConfigError))
|
|
27086
|
+
throw error;
|
|
27087
|
+
refuse4(error.problems);
|
|
27088
|
+
}
|
|
27089
|
+
const output = activeOutput();
|
|
27090
|
+
if (activeOutputMode() === "json") {
|
|
27091
|
+
output.result(built);
|
|
27092
|
+
return;
|
|
27093
|
+
}
|
|
27094
|
+
if (json) {
|
|
27095
|
+
output.info(JSON.stringify(built, null, 2));
|
|
27096
|
+
return;
|
|
27097
|
+
}
|
|
27098
|
+
for (const line of formatSkillsReport(built))
|
|
27099
|
+
output.info(line);
|
|
27100
|
+
}
|
|
26332
27101
|
async function report(args, repoRoot) {
|
|
26333
27102
|
const parsed = parseReportArgs(args);
|
|
26334
27103
|
if (parsed.errors.length > 0)
|
|
26335
27104
|
refuse4(parsed.errors);
|
|
27105
|
+
if (parsed.skills) {
|
|
27106
|
+
writeSkillsReport(parsed.plans, parsed.json, repoRoot);
|
|
27107
|
+
return;
|
|
27108
|
+
}
|
|
26336
27109
|
let built;
|
|
26337
27110
|
try {
|
|
26338
27111
|
built = buildReport({
|
|
@@ -26372,9 +27145,13 @@ var init_report = __esm(() => {
|
|
|
26372
27145
|
init_command();
|
|
26373
27146
|
init_config_load();
|
|
26374
27147
|
init_config();
|
|
27148
|
+
init_serving();
|
|
26375
27149
|
init_classify();
|
|
26376
27150
|
init_commits();
|
|
27151
|
+
init_report_args();
|
|
26377
27152
|
init_report_format();
|
|
27153
|
+
init_report_skills_format();
|
|
27154
|
+
init_report_skills();
|
|
26378
27155
|
init_dispatches();
|
|
26379
27156
|
init_store2();
|
|
26380
27157
|
init_preflight();
|
|
@@ -26394,7 +27171,7 @@ var init_report2 = __esm(() => {
|
|
|
26394
27171
|
subject: "effort",
|
|
26395
27172
|
action: "report",
|
|
26396
27173
|
summary: "roll the stored session rows up per plan, then tally the task reports and list preflight halts",
|
|
26397
|
-
description: "Rolls the session rows `rafa effort collect` stored up per plan, or per branch for a" + " session no plan claims, then tallies the stored task reports by plan, status and outcome, and" + " lists the runs whose preflight halted, one row per required item that failed. It" + " reads only what is stored, so two runs over an unchanged store print the same bytes. With" + " `--output=json` the report is the data of the terminal result event. An unrecognised argument" + " and a config the loop cannot run on are each refused, one line per problem.",
|
|
27174
|
+
description: "Rolls the session rows `rafa effort collect` stored up per plan, or per branch for a" + " session no plan claims, then tallies the stored task reports by plan, status and outcome, and" + " lists the runs whose preflight halted, one row per required item that failed. It" + " reads only what is stored, so two runs over an unchanged store print the same bytes. With" + " `--output=json` the report is the data of the terminal result event. With `--skills` it prints" + " the skills report instead: per plan, and per resolver within one, whether each offered skill and" + " injected lesson co-occurred with a recurrence of the failure it should prevent, read from the stored" + " rows and the skills' frontmatter, never from a session log. An unrecognised argument" + " and a config the loop cannot run on are each refused, one line per problem.",
|
|
26398
27175
|
args: [],
|
|
26399
27176
|
flags: [
|
|
26400
27177
|
{
|
|
@@ -26407,6 +27184,16 @@ var init_report2 = __esm(() => {
|
|
|
26407
27184
|
description: "Keeps only the sessions whose dominant entrypoint is one of these, comma-separated." + " `sdk-cli` is the loop.",
|
|
26408
27185
|
type: "string"
|
|
26409
27186
|
},
|
|
27187
|
+
{
|
|
27188
|
+
name: "skills",
|
|
27189
|
+
description: "Prints the skills report in place of the session tables: per plan and per resolver," + " each skill's and lesson's signal, the skills invoked and never offered, M1, M2 and plan CI." + " Refused beside `--kind` or `--entrypoint`, which narrow session rows it does not read.",
|
|
27190
|
+
type: "boolean"
|
|
27191
|
+
},
|
|
27192
|
+
{
|
|
27193
|
+
name: "plan",
|
|
27194
|
+
description: "Keeps only these plan stubs in the skills report, comma-separated, and may be" + " repeated. A stub the store holds no row for reads as no plan. Refused without `--skills`.",
|
|
27195
|
+
type: "string"
|
|
27196
|
+
},
|
|
26410
27197
|
{
|
|
26411
27198
|
name: "json",
|
|
26412
27199
|
description: "Deprecated: the phase 0 spelling of `--output=json`, read as that flag after one" + " deprecation line on stderr.",
|
|
@@ -26419,6 +27206,10 @@ var init_report2 = __esm(() => {
|
|
|
26419
27206
|
cmd: "rafa effort report",
|
|
26420
27207
|
note: "Prints the per-plan tables, the task report tallies, then the preflight halts."
|
|
26421
27208
|
},
|
|
27209
|
+
{
|
|
27210
|
+
cmd: "rafa effort report --skills --plan=rafa-24-know-which-skills-earn",
|
|
27211
|
+
note: "Prints one plan's skills and lessons with their signals, per resolver, under the fixed" + " co-occurrence line."
|
|
27212
|
+
},
|
|
26422
27213
|
{
|
|
26423
27214
|
cmd: "rafa effort report --entrypoint=sdk-cli --kind=task --output=json",
|
|
26424
27215
|
note: "Writes a start event, then a result event whose data is the report of the task sessions" + " the loop ran."
|
|
@@ -26429,12 +27220,12 @@ var init_report2 = __esm(() => {
|
|
|
26429
27220
|
});
|
|
26430
27221
|
|
|
26431
27222
|
// src/agents/vendorable.ts
|
|
26432
|
-
import { readdirSync as
|
|
27223
|
+
import { readdirSync as readdirSync11, readFileSync as readFileSync34 } from "fs";
|
|
26433
27224
|
import { isAbsolute as isAbsolute10, join as join41 } from "path";
|
|
26434
27225
|
function planFiles(dir) {
|
|
26435
27226
|
let entries;
|
|
26436
27227
|
try {
|
|
26437
|
-
entries =
|
|
27228
|
+
entries = readdirSync11(dir, { withFileTypes: true });
|
|
26438
27229
|
} catch {
|
|
26439
27230
|
return [];
|
|
26440
27231
|
}
|
|
@@ -26442,7 +27233,7 @@ function planFiles(dir) {
|
|
|
26442
27233
|
}
|
|
26443
27234
|
function readText7(path4) {
|
|
26444
27235
|
try {
|
|
26445
|
-
return
|
|
27236
|
+
return readFileSync34(path4, "utf8");
|
|
26446
27237
|
} catch {
|
|
26447
27238
|
return null;
|
|
26448
27239
|
}
|
|
@@ -26491,7 +27282,7 @@ var init_vendorable = __esm(() => {
|
|
|
26491
27282
|
|
|
26492
27283
|
// src/project/gitignore.ts
|
|
26493
27284
|
import { createHash as createHash5 } from "crypto";
|
|
26494
|
-
import { existsSync as
|
|
27285
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync11, readFileSync as readFileSync35, writeFileSync as writeFileSync10 } from "fs";
|
|
26495
27286
|
import { dirname as dirname15, isAbsolute as isAbsolute11, join as join42 } from "path";
|
|
26496
27287
|
function trackingEntry(flags) {
|
|
26497
27288
|
if (flags.trackingAll) {
|
|
@@ -26561,9 +27352,9 @@ function attempt2(file, failure6, act) {
|
|
|
26561
27352
|
}
|
|
26562
27353
|
}
|
|
26563
27354
|
function readIfPresent4(file) {
|
|
26564
|
-
if (!
|
|
27355
|
+
if (!existsSync31(file))
|
|
26565
27356
|
return null;
|
|
26566
|
-
return attempt2(file, "cannot be read", () =>
|
|
27357
|
+
return attempt2(file, "cannot be read", () => readFileSync35(file, "utf8"));
|
|
26567
27358
|
}
|
|
26568
27359
|
function writeTrackingGitignore(root, flags) {
|
|
26569
27360
|
requireAbsolute2(root);
|
|
@@ -26640,8 +27431,8 @@ var init_gitignore = __esm(() => {
|
|
|
26640
27431
|
|
|
26641
27432
|
// src/project/roots.ts
|
|
26642
27433
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
26643
|
-
import { accessSync, constants, readFileSync as
|
|
26644
|
-
import { isAbsolute as isAbsolute12, join as join43, resolve as
|
|
27434
|
+
import { accessSync, constants, readFileSync as readFileSync36, statSync as statSync19 } from "fs";
|
|
27435
|
+
import { isAbsolute as isAbsolute12, join as join43, resolve as resolve18 } from "path";
|
|
26645
27436
|
function gitToplevel(dir) {
|
|
26646
27437
|
const result = spawnSync4("git", ["rev-parse", "--show-toplevel"], {
|
|
26647
27438
|
cwd: dir,
|
|
@@ -26674,7 +27465,7 @@ function realOrSpelled(path4, fs3) {
|
|
|
26674
27465
|
try {
|
|
26675
27466
|
return fs3.realpath(path4);
|
|
26676
27467
|
} catch {
|
|
26677
|
-
return
|
|
27468
|
+
return resolve18(path4);
|
|
26678
27469
|
}
|
|
26679
27470
|
}
|
|
26680
27471
|
function namedRoots(home, fs3) {
|
|
@@ -26716,7 +27507,7 @@ function writeRefusal(given, real, fs3) {
|
|
|
26716
27507
|
}
|
|
26717
27508
|
function refusalOf2(given, named, fs3) {
|
|
26718
27509
|
const resolved = resolveReal(given, fs3);
|
|
26719
|
-
const byName2 = namedRefusal(given, resolved.real ??
|
|
27510
|
+
const byName2 = namedRefusal(given, resolved.real ?? resolve18(given), named);
|
|
26720
27511
|
if (byName2 !== null)
|
|
26721
27512
|
return byName2;
|
|
26722
27513
|
if (resolved.real === null) {
|
|
@@ -26797,7 +27588,7 @@ var init_roots = __esm(() => {
|
|
|
26797
27588
|
]);
|
|
26798
27589
|
DISK_ROOTS_FILE_SYSTEM = Object.freeze({
|
|
26799
27590
|
...DISK_FILE_SYSTEM,
|
|
26800
|
-
readFile: (path4) =>
|
|
27591
|
+
readFile: (path4) => readFileSync36(path4, "utf8"),
|
|
26801
27592
|
isDirectory: (path4) => statSync19(path4).isDirectory(),
|
|
26802
27593
|
assertWritable: (path4) => accessSync(path4, constants.W_OK)
|
|
26803
27594
|
});
|
|
@@ -26810,7 +27601,7 @@ var init_roots = __esm(() => {
|
|
|
26810
27601
|
});
|
|
26811
27602
|
|
|
26812
27603
|
// src/project/root-choice.ts
|
|
26813
|
-
import { resolve as
|
|
27604
|
+
import { resolve as resolve19 } from "path";
|
|
26814
27605
|
function chosen(path4, source) {
|
|
26815
27606
|
return { root: { path: path4, source }, problem: null };
|
|
26816
27607
|
}
|
|
@@ -26843,7 +27634,7 @@ function firstCandidate(found) {
|
|
|
26843
27634
|
return first.refusal === null ? chosen(first.path, first.source) : problem(first.refusal.reason);
|
|
26844
27635
|
}
|
|
26845
27636
|
function namedRoot(typed, start, source, seams) {
|
|
26846
|
-
const path4 =
|
|
27637
|
+
const path4 = resolve19(start, typed);
|
|
26847
27638
|
const refusal5 = rootRefusal(path4, seams);
|
|
26848
27639
|
if (refusal5 !== null)
|
|
26849
27640
|
return problem(refusal5.reason);
|
|
@@ -26893,7 +27684,7 @@ var init_root_choice = __esm(() => {
|
|
|
26893
27684
|
});
|
|
26894
27685
|
|
|
26895
27686
|
// src/project/scaffold.ts
|
|
26896
|
-
import { existsSync as
|
|
27687
|
+
import { existsSync as existsSync32, lstatSync as lstatSync2, mkdirSync as mkdirSync12, statSync as statSync20, writeFileSync as writeFileSync11 } from "fs";
|
|
26897
27688
|
import { join as join44 } from "path";
|
|
26898
27689
|
function configText(header) {
|
|
26899
27690
|
return [...header, VERSION_LINE, ...CONFIG_SETTINGS_LINES, ""].join(`
|
|
@@ -26918,7 +27709,7 @@ function isDirectory2(path4) {
|
|
|
26918
27709
|
function directoryConflict(dir) {
|
|
26919
27710
|
if (!occupied(dir) || isDirectory2(dir))
|
|
26920
27711
|
return null;
|
|
26921
|
-
return
|
|
27712
|
+
return existsSync32(dir) ? `${dir} is not a directory` : `${dir} is a link to nothing`;
|
|
26922
27713
|
}
|
|
26923
27714
|
function layoutConflicts(layout) {
|
|
26924
27715
|
const [scopeDir, ...tree] = layout.dirs;
|
|
@@ -26926,7 +27717,7 @@ function layoutConflicts(layout) {
|
|
|
26926
27717
|
if (opening !== null)
|
|
26927
27718
|
return [opening];
|
|
26928
27719
|
const dirs = tree.flatMap((dir) => directoryConflict(dir) ?? []);
|
|
26929
|
-
const file = occupied(layout.configFile) && !
|
|
27720
|
+
const file = occupied(layout.configFile) && !existsSync32(layout.configFile) ? [`${layout.configFile} is a link to nothing`] : [];
|
|
26930
27721
|
return [...dirs, ...file];
|
|
26931
27722
|
}
|
|
26932
27723
|
function scaffoldConflicts(root, home) {
|
|
@@ -26940,7 +27731,7 @@ function attempt3(path4, failure6, act) {
|
|
|
26940
27731
|
}
|
|
26941
27732
|
}
|
|
26942
27733
|
function ensureDirectory(path4) {
|
|
26943
|
-
if (
|
|
27734
|
+
if (existsSync32(path4))
|
|
26944
27735
|
return { path: path4, kind: "directory", change: "unchanged" };
|
|
26945
27736
|
attempt3(path4, "cannot be created", () => {
|
|
26946
27737
|
mkdirSync12(path4, { recursive: true });
|
|
@@ -26948,7 +27739,7 @@ function ensureDirectory(path4) {
|
|
|
26948
27739
|
return { path: path4, kind: "directory", change: "created" };
|
|
26949
27740
|
}
|
|
26950
27741
|
function ensureFile(path4, text2) {
|
|
26951
|
-
if (
|
|
27742
|
+
if (existsSync32(path4))
|
|
26952
27743
|
return { path: path4, kind: "file", change: "unchanged" };
|
|
26953
27744
|
attempt3(path4, "cannot be written", () => {
|
|
26954
27745
|
writeFileSync11(path4, text2, { encoding: "utf8", flag: "wx" });
|
|
@@ -27063,7 +27854,7 @@ var init_scaffold = __esm(() => {
|
|
|
27063
27854
|
|
|
27064
27855
|
// src/release/enabled.ts
|
|
27065
27856
|
import { statSync as statSync21 } from "fs";
|
|
27066
|
-
import { resolve as
|
|
27857
|
+
import { resolve as resolve20 } from "path";
|
|
27067
27858
|
function isRegularFile(full) {
|
|
27068
27859
|
try {
|
|
27069
27860
|
return statSync21(full).isFile();
|
|
@@ -27072,7 +27863,7 @@ function isRegularFile(full) {
|
|
|
27072
27863
|
}
|
|
27073
27864
|
}
|
|
27074
27865
|
function readFile5(repoRoot, path4) {
|
|
27075
|
-
const resolved =
|
|
27866
|
+
const resolved = resolve20(repoRoot, path4);
|
|
27076
27867
|
return { path: path4, resolved, present: isRegularFile(resolved) };
|
|
27077
27868
|
}
|
|
27078
27869
|
function resolveReleaseEnabled(settings, repoRoot) {
|
|
@@ -27093,7 +27884,7 @@ var init_enabled = __esm(() => {
|
|
|
27093
27884
|
});
|
|
27094
27885
|
|
|
27095
27886
|
// src/release/setting.ts
|
|
27096
|
-
import { readFileSync as
|
|
27887
|
+
import { readFileSync as readFileSync37 } from "fs";
|
|
27097
27888
|
function releaseEnabledIn(text2, path4) {
|
|
27098
27889
|
return parseConfigText(text2, path4).values.releaseEnabled ?? null;
|
|
27099
27890
|
}
|
|
@@ -27101,7 +27892,7 @@ function readReleaseSetting(root) {
|
|
|
27101
27892
|
const path4 = configFilePath(root);
|
|
27102
27893
|
let text2;
|
|
27103
27894
|
try {
|
|
27104
|
-
text2 =
|
|
27895
|
+
text2 = readFileSync37(path4, "utf8");
|
|
27105
27896
|
} catch (error) {
|
|
27106
27897
|
return { enabled: null, text: "", problem: `${path4} could not be read: ${messageOf(error)}` };
|
|
27107
27898
|
}
|
|
@@ -27281,7 +28072,7 @@ var init_init_release = __esm(() => {
|
|
|
27281
28072
|
});
|
|
27282
28073
|
|
|
27283
28074
|
// src/commands/init.ts
|
|
27284
|
-
import { existsSync as
|
|
28075
|
+
import { existsSync as existsSync33, readFileSync as readFileSync38 } from "fs";
|
|
27285
28076
|
import { homedir as homedir6 } from "os";
|
|
27286
28077
|
import { join as join45, relative as relative11, sep as sep4 } from "path";
|
|
27287
28078
|
function refusal5(lines2) {
|
|
@@ -27374,7 +28165,7 @@ function resolvedConfig3(root, home, warn) {
|
|
|
27374
28165
|
function checkGitignore(root, flags) {
|
|
27375
28166
|
const file = join45(root, GITIGNORE_FILE);
|
|
27376
28167
|
try {
|
|
27377
|
-
const text2 =
|
|
28168
|
+
const text2 = existsSync33(file) ? readFileSync38(file, "utf8") : null;
|
|
27378
28169
|
withTrackingBlock(text2, flags, file);
|
|
27379
28170
|
} catch (error) {
|
|
27380
28171
|
const message = error instanceof GitignoreError ? error.message : `rafa init: ${file} cannot be read (${messageOf(error)})`;
|
|
@@ -27405,8 +28196,8 @@ function initialise(root, start, home, context, entry) {
|
|
|
27405
28196
|
checkConflicts(root.path, home);
|
|
27406
28197
|
const config = resolvedConfig3(root.path, home, warn);
|
|
27407
28198
|
checkGitignore(root.path, config);
|
|
27408
|
-
const configExisted =
|
|
27409
|
-
const digestExisted =
|
|
28199
|
+
const configExisted = existsSync33(configFilePath(root.path));
|
|
28200
|
+
const digestExisted = existsSync33(join45(root.path, TRACKING_DIGEST_FILE));
|
|
27410
28201
|
const project = writeProjectScope(root.path);
|
|
27411
28202
|
const tracking = applyTracking(root.path, config, warn);
|
|
27412
28203
|
const writes = [...project, ...trackingWrites(tracking, digestExisted), ...writeUserScope(home)];
|
|
@@ -27597,7 +28388,7 @@ var init_init = __esm(() => {
|
|
|
27597
28388
|
});
|
|
27598
28389
|
|
|
27599
28390
|
// src/commands/check-report.ts
|
|
27600
|
-
import { resolve as
|
|
28391
|
+
import { resolve as resolve21 } from "path";
|
|
27601
28392
|
function readCheckDirectory(args, usage, cwd) {
|
|
27602
28393
|
const [dir, extra] = args;
|
|
27603
28394
|
if (dir === undefined) {
|
|
@@ -27608,7 +28399,7 @@ Usage: ${usage}`);
|
|
|
27608
28399
|
throw new CommandExit(1, `\u274C Expected one directory, and read "${extra}" as a second
|
|
27609
28400
|
Usage: ${usage}`);
|
|
27610
28401
|
}
|
|
27611
|
-
return
|
|
28402
|
+
return resolve21(cwd(), dir);
|
|
27612
28403
|
}
|
|
27613
28404
|
function readFix(value, usage) {
|
|
27614
28405
|
if (value === undefined || value === false || value === "false")
|
|
@@ -27625,7 +28416,7 @@ function readProjectRoot(value, usage, cwd) {
|
|
|
27625
28416
|
throw new CommandExit(1, `\u274C --project needs a path, and the line gave it none
|
|
27626
28417
|
Usage: ${usage}`);
|
|
27627
28418
|
}
|
|
27628
|
-
return
|
|
28419
|
+
return resolve21(cwd(), value);
|
|
27629
28420
|
}
|
|
27630
28421
|
function reportMarker(report2) {
|
|
27631
28422
|
if (report2.failed)
|
|
@@ -28297,8 +29088,8 @@ var init_show3 = __esm(() => {
|
|
|
28297
29088
|
});
|
|
28298
29089
|
|
|
28299
29090
|
// src/commands/issue/check.ts
|
|
28300
|
-
import { readdirSync as
|
|
28301
|
-
import { join as join46, resolve as
|
|
29091
|
+
import { readdirSync as readdirSync12, readFileSync as readFileSync39, statSync as statSync22 } from "fs";
|
|
29092
|
+
import { join as join46, resolve as resolve22 } from "path";
|
|
28302
29093
|
function readCheckIssue(args) {
|
|
28303
29094
|
if (args.length > 1) {
|
|
28304
29095
|
throw lineRefusal2(`Expected one issue number, got ${String(args.length)}: ${args.join(" ")}`, CHECK_USAGE);
|
|
@@ -28318,7 +29109,7 @@ function missingCopyMessage(issue4, specsDir) {
|
|
|
28318
29109
|
function copyNames(dir, issue4) {
|
|
28319
29110
|
let names;
|
|
28320
29111
|
try {
|
|
28321
|
-
names =
|
|
29112
|
+
names = readdirSync12(dir);
|
|
28322
29113
|
} catch (error) {
|
|
28323
29114
|
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
28324
29115
|
return [];
|
|
@@ -28329,7 +29120,7 @@ function copyNames(dir, issue4) {
|
|
|
28329
29120
|
return names.filter((name2) => name2.startsWith(prefix) && name2.endsWith(SPEC_EXTENSION) && name2 !== notes).filter((name2) => name2.length > prefix.length + SPEC_EXTENSION.length).filter((name2) => statSync22(join46(dir, name2)).isFile()).sort();
|
|
28330
29121
|
}
|
|
28331
29122
|
function findSavedCopy(root, specsDir, issue4) {
|
|
28332
|
-
const names = copyNames(
|
|
29123
|
+
const names = copyNames(resolve22(root, specsDir), issue4);
|
|
28333
29124
|
const [only] = names;
|
|
28334
29125
|
if (only === undefined)
|
|
28335
29126
|
throw new CommandExit(1, missingCopyMessage(issue4, specsDir));
|
|
@@ -28341,7 +29132,7 @@ function findSavedCopy(root, specsDir, issue4) {
|
|
|
28341
29132
|
`));
|
|
28342
29133
|
}
|
|
28343
29134
|
const path4 = join46(specsDir, only);
|
|
28344
|
-
return { path: path4, absolute:
|
|
29135
|
+
return { path: path4, absolute: resolve22(root, path4) };
|
|
28345
29136
|
}
|
|
28346
29137
|
function liveText(live) {
|
|
28347
29138
|
return live.kind === "unreadable" ? "unreadable" : fingerprintText(live);
|
|
@@ -28389,7 +29180,7 @@ async function readReferences(absolute, issue4, verify, stamp2) {
|
|
|
28389
29180
|
return rows2.map((row3) => checkedRef(row3, row3.stamp));
|
|
28390
29181
|
}
|
|
28391
29182
|
const once2 = memoiseVerifier(verify);
|
|
28392
|
-
const before = await readRefsText({ copy:
|
|
29183
|
+
const before = await readRefsText({ copy: readFileSync39(absolute, "utf8"), issue: issue4, verify: once2 });
|
|
28393
29184
|
const after = await restampCopyRefs({ path: absolute, issue: issue4, verify: once2 });
|
|
28394
29185
|
return before.rows.map((row3, index) => checkedRef(row3, after.rows[index]?.stamp ?? null));
|
|
28395
29186
|
}
|
|
@@ -28541,7 +29332,7 @@ var init_comment = __esm(() => {
|
|
|
28541
29332
|
|
|
28542
29333
|
// src/effort/store/tracker-refs.ts
|
|
28543
29334
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
28544
|
-
import { existsSync as
|
|
29335
|
+
import { existsSync as existsSync34 } from "fs";
|
|
28545
29336
|
function refused3(call, reason) {
|
|
28546
29337
|
return new Error(`effort store: tracker ref ${call} ${reason}; ${REFUSAL_TAILS[call]}`);
|
|
28547
29338
|
}
|
|
@@ -28636,7 +29427,7 @@ function writeTrackerRef(repoRoot, write, seams = {}) {
|
|
|
28636
29427
|
wanted.json,
|
|
28637
29428
|
collectedAt
|
|
28638
29429
|
];
|
|
28639
|
-
const [action, stored] = withSqliteStore(path4, !
|
|
29430
|
+
const [action, stored] = withSqliteStore(path4, !existsSync34(path4), (db) => {
|
|
28640
29431
|
const place2 = db.transaction(() => placeRef(db, path4, write, wanted, insertValues));
|
|
28641
29432
|
return place2.immediate();
|
|
28642
29433
|
});
|
|
@@ -28645,7 +29436,7 @@ function writeTrackerRef(repoRoot, write, seams = {}) {
|
|
|
28645
29436
|
function readTrackerRef(repoRoot, artifact) {
|
|
28646
29437
|
checkArtifact2("read", artifact);
|
|
28647
29438
|
const path4 = sqliteStorePath(repoRoot);
|
|
28648
|
-
if (!
|
|
29439
|
+
if (!existsSync34(path4))
|
|
28649
29440
|
return null;
|
|
28650
29441
|
const oldest = withSqliteStore(path4, false, (db) => db.query(SELECT_OLDEST).get(artifact));
|
|
28651
29442
|
return oldest === null ? null : heldRefOf(path4, oldest.seq, oldest.tracker_ref).ref;
|
|
@@ -29184,14 +29975,14 @@ var init_roadmap_board = __esm(() => {
|
|
|
29184
29975
|
});
|
|
29185
29976
|
|
|
29186
29977
|
// src/board/roadmap-rows.ts
|
|
29187
|
-
import { readdirSync as
|
|
29978
|
+
import { readdirSync as readdirSync13 } from "fs";
|
|
29188
29979
|
function isMissing2(error) {
|
|
29189
29980
|
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
29190
29981
|
}
|
|
29191
29982
|
function createPlanDirNames(dir) {
|
|
29192
29983
|
return () => {
|
|
29193
29984
|
try {
|
|
29194
|
-
return Object.freeze(
|
|
29985
|
+
return Object.freeze(readdirSync13(dir));
|
|
29195
29986
|
} catch (error) {
|
|
29196
29987
|
if (isMissing2(error))
|
|
29197
29988
|
return Object.freeze([]);
|
|
@@ -29302,7 +30093,7 @@ function viewOf3(issues) {
|
|
|
29302
30093
|
known: new Set(issues.map((issue4) => issue4.number))
|
|
29303
30094
|
};
|
|
29304
30095
|
}
|
|
29305
|
-
function
|
|
30096
|
+
function rowOf5(line, board, has, refs) {
|
|
29306
30097
|
const issue4 = board?.byNumber.get(line.issue);
|
|
29307
30098
|
if (board === null || issue4 === undefined) {
|
|
29308
30099
|
return Object.freeze({ line, issue: null, spec: null, blocked: null, blockers: Object.freeze([]), has, refs });
|
|
@@ -29329,7 +30120,7 @@ async function readRoadmapRows2(options) {
|
|
|
29329
30120
|
const refs = await readOrWarn(() => options.refs(issues), new Map, "the saved copies could not be read, so the refs column is empty");
|
|
29330
30121
|
const board = viewOf3(listed3.issues);
|
|
29331
30122
|
const sources = { planNames: plans.value, refs: scan2.refs, pulls: pulls.value };
|
|
29332
|
-
const rows2 = lines2.map((line) =>
|
|
30123
|
+
const rows2 = lines2.map((line) => rowOf5(line, board, readHasColumn(line.issue, sources), refs.value.get(line.issue) ?? null));
|
|
29333
30124
|
const warnings = [listed3.warning, ...scan2.problems, pulls.warning, plans.warning, refs.warning, ...refsWarnings(refs.value)].filter((warning) => warning !== null);
|
|
29334
30125
|
return Object.freeze({ roadmap, rows: Object.freeze(rows2), warnings: Object.freeze(warnings) });
|
|
29335
30126
|
}
|
|
@@ -30663,9 +31454,9 @@ var init_run_config = __esm(() => {
|
|
|
30663
31454
|
});
|
|
30664
31455
|
|
|
30665
31456
|
// src/start/runtime.ts
|
|
30666
|
-
import { existsSync as
|
|
31457
|
+
import { existsSync as existsSync35, readdirSync as readdirSync14, realpathSync as realpathSync8, statSync as statSync23 } from "fs";
|
|
30667
31458
|
import { homedir as homedir7 } from "os";
|
|
30668
|
-
import { isAbsolute as isAbsolute13, join as join48, relative as relative13, resolve as
|
|
31459
|
+
import { isAbsolute as isAbsolute13, join as join48, relative as relative13, resolve as resolve23, sep as sep5 } from "path";
|
|
30669
31460
|
function runtimeFlagValue(args) {
|
|
30670
31461
|
return args.includes(RUNTIME_FLAG) ? "" : argValue(args, RUNTIME_FLAG);
|
|
30671
31462
|
}
|
|
@@ -30687,14 +31478,14 @@ function resolveRuntime(value, places) {
|
|
|
30687
31478
|
throw refusal6([`\u274C Refusing to start: \`--runtime\` names no runtime. Spell it ${SPELLING}.`]);
|
|
30688
31479
|
}
|
|
30689
31480
|
const isVersion = VERSION_SHAPE.test(value);
|
|
30690
|
-
const named = isVersion ? join48(places.home, RUNTIME_SUBDIR, value, RUNTIME_ENTRY) :
|
|
31481
|
+
const named = isVersion ? join48(places.home, RUNTIME_SUBDIR, value, RUNTIME_ENTRY) : resolve23(places.cwd, value);
|
|
30691
31482
|
refuseInsideSource(value, named, places);
|
|
30692
|
-
const entry =
|
|
31483
|
+
const entry = entryOf2(value, named, isVersion, places.home);
|
|
30693
31484
|
const real = realpathSync8(entry);
|
|
30694
31485
|
refuseInsideSource(value, real, places);
|
|
30695
31486
|
return real;
|
|
30696
31487
|
}
|
|
30697
|
-
function
|
|
31488
|
+
function entryOf2(value, named, isVersion, home) {
|
|
30698
31489
|
if (isVersion) {
|
|
30699
31490
|
if (isFile3(named))
|
|
30700
31491
|
return named;
|
|
@@ -30726,7 +31517,7 @@ function refuseInsideSource(value, path4, places) {
|
|
|
30726
31517
|
}
|
|
30727
31518
|
function sourceDirs({ cwd, root }) {
|
|
30728
31519
|
const dirs = [join48(cwd, SOURCE_DIR), join48(root, SOURCE_DIR)];
|
|
30729
|
-
const real = dirs.filter((dir) =>
|
|
31520
|
+
const real = dirs.filter((dir) => existsSync35(dir)).map((dir) => realpathSync8(dir));
|
|
30730
31521
|
return [...new Set([...dirs, ...real])];
|
|
30731
31522
|
}
|
|
30732
31523
|
function isInside3(path4, dir) {
|
|
@@ -30735,7 +31526,7 @@ function isInside3(path4, dir) {
|
|
|
30735
31526
|
}
|
|
30736
31527
|
function installedVersions(root) {
|
|
30737
31528
|
try {
|
|
30738
|
-
return
|
|
31529
|
+
return readdirSync14(root).filter((name2) => isFile3(join48(root, name2, RUNTIME_ENTRY))).sort((a, b) => a.localeCompare(b));
|
|
30739
31530
|
} catch {
|
|
30740
31531
|
return [];
|
|
30741
31532
|
}
|
|
@@ -30780,7 +31571,7 @@ function realOrResolved(path4) {
|
|
|
30780
31571
|
try {
|
|
30781
31572
|
return realpathSync8(path4);
|
|
30782
31573
|
} catch {
|
|
30783
|
-
return
|
|
31574
|
+
return resolve23(path4);
|
|
30784
31575
|
}
|
|
30785
31576
|
}
|
|
30786
31577
|
async function runRuntime(entry, words, run) {
|
|
@@ -30877,7 +31668,7 @@ var init_runtime = __esm(() => {
|
|
|
30877
31668
|
});
|
|
30878
31669
|
|
|
30879
31670
|
// src/notices/notices.ts
|
|
30880
|
-
import { mkdirSync as mkdirSync13, readFileSync as
|
|
31671
|
+
import { mkdirSync as mkdirSync13, readFileSync as readFileSync40, writeFileSync as writeFileSync13 } from "fs";
|
|
30881
31672
|
import { dirname as dirname16, join as join49 } from "path";
|
|
30882
31673
|
function noticesPath(home) {
|
|
30883
31674
|
return join49(home, ".rafa", "notices.json");
|
|
@@ -30888,7 +31679,7 @@ function isNoticeId(value) {
|
|
|
30888
31679
|
function readDismissed(home) {
|
|
30889
31680
|
let raw;
|
|
30890
31681
|
try {
|
|
30891
|
-
raw =
|
|
31682
|
+
raw = readFileSync40(noticesPath(home), "utf8");
|
|
30892
31683
|
} catch {
|
|
30893
31684
|
return [];
|
|
30894
31685
|
}
|
|
@@ -31729,7 +32520,7 @@ var init_level = __esm(() => {
|
|
|
31729
32520
|
});
|
|
31730
32521
|
|
|
31731
32522
|
// src/release/version.ts
|
|
31732
|
-
import { readFileSync as
|
|
32523
|
+
import { readFileSync as readFileSync41, writeFileSync as writeFileSync14 } from "fs";
|
|
31733
32524
|
function parseSemanticVersion(raw) {
|
|
31734
32525
|
const found = VERSION_SHAPE2.exec(raw);
|
|
31735
32526
|
if (found === null)
|
|
@@ -31817,7 +32608,7 @@ function writeManifestVersion(path4, next) {
|
|
|
31817
32608
|
const unwritten = { path: path4, written: false, previous: null, version: next };
|
|
31818
32609
|
let text2;
|
|
31819
32610
|
try {
|
|
31820
|
-
text2 =
|
|
32611
|
+
text2 = readFileSync41(path4, "utf8");
|
|
31821
32612
|
} catch (error) {
|
|
31822
32613
|
return { ...unwritten, problem: `${path4} could not be read: ${messageOf(error)}` };
|
|
31823
32614
|
}
|
|
@@ -31872,7 +32663,7 @@ var init_version2 = __esm(() => {
|
|
|
31872
32663
|
});
|
|
31873
32664
|
|
|
31874
32665
|
// src/release/prepare.ts
|
|
31875
|
-
import { readFileSync as
|
|
32666
|
+
import { readFileSync as readFileSync42, writeFileSync as writeFileSync15 } from "fs";
|
|
31876
32667
|
function levelFields(reading2) {
|
|
31877
32668
|
return { level: reading2.level, levelSource: reading2.source, notesLevel: reading2.notesLevel };
|
|
31878
32669
|
}
|
|
@@ -31928,7 +32719,7 @@ function planVersion(input, versionFile, level) {
|
|
|
31928
32719
|
}
|
|
31929
32720
|
function textOf(path4) {
|
|
31930
32721
|
try {
|
|
31931
|
-
return
|
|
32722
|
+
return readFileSync42(path4, "utf8");
|
|
31932
32723
|
} catch {
|
|
31933
32724
|
return null;
|
|
31934
32725
|
}
|
|
@@ -32048,7 +32839,7 @@ var init_prepare = __esm(() => {
|
|
|
32048
32839
|
});
|
|
32049
32840
|
|
|
32050
32841
|
// src/release/verify.ts
|
|
32051
|
-
import { readFileSync as
|
|
32842
|
+
import { readFileSync as readFileSync43, writeFileSync as writeFileSync16 } from "fs";
|
|
32052
32843
|
function changelogInsertionSpan(before, after) {
|
|
32053
32844
|
const beforeLines = before.split(`
|
|
32054
32845
|
`);
|
|
@@ -32065,7 +32856,7 @@ function changelogInsertionSpan(before, after) {
|
|
|
32065
32856
|
}
|
|
32066
32857
|
function textOf2(path4) {
|
|
32067
32858
|
try {
|
|
32068
|
-
return
|
|
32859
|
+
return readFileSync43(path4, "utf8");
|
|
32069
32860
|
} catch {
|
|
32070
32861
|
return null;
|
|
32071
32862
|
}
|
|
@@ -32465,9 +33256,9 @@ function describeStartTriage(result) {
|
|
|
32465
33256
|
};
|
|
32466
33257
|
}
|
|
32467
33258
|
async function resolvePublicTracker(options, redact) {
|
|
32468
|
-
const
|
|
33259
|
+
const resolve24 = options.resolve ?? resolveTracker;
|
|
32469
33260
|
try {
|
|
32470
|
-
const { tracker, attempts } = await
|
|
33261
|
+
const { tracker, attempts } = await resolve24({
|
|
32471
33262
|
config: options.config,
|
|
32472
33263
|
context: { repoRoot: options.repoRoot }
|
|
32473
33264
|
});
|
|
@@ -32877,7 +33668,7 @@ async function openPullRequestNumber(branch) {
|
|
|
32877
33668
|
return null;
|
|
32878
33669
|
}
|
|
32879
33670
|
}
|
|
32880
|
-
function
|
|
33671
|
+
function messageOf13(error) {
|
|
32881
33672
|
return error instanceof Error ? error.message : String(error);
|
|
32882
33673
|
}
|
|
32883
33674
|
function wrapUpAdapter(learning) {
|
|
@@ -32898,7 +33689,7 @@ async function lessonsToPromote(learning) {
|
|
|
32898
33689
|
minConfidence: learning.promoteMinConfidence
|
|
32899
33690
|
});
|
|
32900
33691
|
} catch (error) {
|
|
32901
|
-
activeOutput().warn(` The wrap-up lists no lesson to promote: the \`${learning.kind}\` learning adapter answered no blessed set: ${
|
|
33692
|
+
activeOutput().warn(` The wrap-up lists no lesson to promote: the \`${learning.kind}\` learning adapter answered no blessed set: ${messageOf13(error)}`);
|
|
32902
33693
|
return [];
|
|
32903
33694
|
}
|
|
32904
33695
|
}
|
|
@@ -32964,8 +33755,8 @@ function msUntil(startAt, now = new Date) {
|
|
|
32964
33755
|
return target.getTime() - now.getTime();
|
|
32965
33756
|
}
|
|
32966
33757
|
function sleepFor(ms) {
|
|
32967
|
-
return new Promise((
|
|
32968
|
-
setTimeout(
|
|
33758
|
+
return new Promise((resolve24) => {
|
|
33759
|
+
setTimeout(resolve24, ms);
|
|
32969
33760
|
});
|
|
32970
33761
|
}
|
|
32971
33762
|
async function deferUntil(startAt, now = new Date, sleep = sleepFor) {
|
|
@@ -34459,8 +35250,8 @@ var init_create2 = __esm(() => {
|
|
|
34459
35250
|
});
|
|
34460
35251
|
|
|
34461
35252
|
// src/commands/plan/risk.ts
|
|
34462
|
-
import { readFileSync as
|
|
34463
|
-
import { resolve as
|
|
35253
|
+
import { readFileSync as readFileSync44 } from "fs";
|
|
35254
|
+
import { resolve as resolve24 } from "path";
|
|
34464
35255
|
function spawningRunners2(root) {
|
|
34465
35256
|
return { git: createGitRunner(root), gh: createGhRunner({ cwd: root }) };
|
|
34466
35257
|
}
|
|
@@ -34470,7 +35261,7 @@ function riskPlanPath(root, planDir, typed) {
|
|
|
34470
35261
|
return path7;
|
|
34471
35262
|
if (typed !== null)
|
|
34472
35263
|
throw new CommandExit(1, `\u274C Plan file not found: ${path7}`);
|
|
34473
|
-
const lookedFor = [...new Set([
|
|
35264
|
+
const lookedFor = [...new Set([resolve24(root, planDir, DEFAULT_PLAN_FILE), resolve24(root, DEFAULT_PLAN_FILE)])];
|
|
34474
35265
|
throw new CommandExit(1, `\u274C No plan named, and no default plan at ${lookedFor.join(" or ")}
|
|
34475
35266
|
Usage: ${USAGE24}`);
|
|
34476
35267
|
}
|
|
@@ -34484,7 +35275,7 @@ function strictRefusal(report2) {
|
|
|
34484
35275
|
}
|
|
34485
35276
|
async function readRisk(path7, project, config, context, seams) {
|
|
34486
35277
|
const makeRunners = seams.runners ?? spawningRunners2;
|
|
34487
|
-
return assessPlanRisk({ path: path7, text:
|
|
35278
|
+
return assessPlanRisk({ path: path7, text: readFileSync44(path7, "utf8") }, {
|
|
34488
35279
|
repoRoot: project.root,
|
|
34489
35280
|
home: project.home,
|
|
34490
35281
|
settingSources: config.settingSources,
|
|
@@ -34577,7 +35368,7 @@ var init_risk2 = __esm(() => {
|
|
|
34577
35368
|
});
|
|
34578
35369
|
|
|
34579
35370
|
// src/commands/plan/show.ts
|
|
34580
|
-
import { readFileSync as
|
|
35371
|
+
import { readFileSync as readFileSync45 } from "fs";
|
|
34581
35372
|
import { join as join50 } from "path";
|
|
34582
35373
|
function readTrackerFlag(value) {
|
|
34583
35374
|
if (value === undefined || value === false || value === "false")
|
|
@@ -34597,7 +35388,7 @@ function showPlan(plans, stub, tracker) {
|
|
|
34597
35388
|
const file = join50(plans.path, name2);
|
|
34598
35389
|
if (!isFile2(file))
|
|
34599
35390
|
throw new CommandExit(1, missingText(stub, tracker, join50(plans.label, name2)));
|
|
34600
|
-
const model = parsePlan(
|
|
35391
|
+
const model = parsePlan(readFileSync45(file, "utf8"));
|
|
34601
35392
|
const { header } = model;
|
|
34602
35393
|
return {
|
|
34603
35394
|
stub,
|
|
@@ -34771,6 +35562,7 @@ function openPrContext(context, seams = DEFAULT_PR_SEAMS) {
|
|
|
34771
35562
|
resolveBudget: config.prResolveBudget,
|
|
34772
35563
|
trustedAuthors: config.boardTrustedAuthors,
|
|
34773
35564
|
roadmapIssue: config.roadmapIssue,
|
|
35565
|
+
planDir: config.planDir,
|
|
34774
35566
|
readBranch: () => readBranch2(project.root)
|
|
34775
35567
|
};
|
|
34776
35568
|
}
|
|
@@ -34992,7 +35784,7 @@ async function probe(call) {
|
|
|
34992
35784
|
return { value: null, problem: messageOf(error) };
|
|
34993
35785
|
}
|
|
34994
35786
|
}
|
|
34995
|
-
async function
|
|
35787
|
+
async function rowOf6(pulls, pull) {
|
|
34996
35788
|
const [checks, detail] = await Promise.all([
|
|
34997
35789
|
probe(() => pulls.checks(pull.number)),
|
|
34998
35790
|
probe(() => pulls.get(pull.number))
|
|
@@ -35010,7 +35802,7 @@ async function readList2(context, seams, now) {
|
|
|
35010
35802
|
expectNoArguments(context.args, USAGE27);
|
|
35011
35803
|
const pr = openPrContext(context, seams);
|
|
35012
35804
|
const open = await onProvider("list the open pull requests", () => pr.pulls.list());
|
|
35013
|
-
const rows2 = await mapWithLimit(open, PROBE_LIMIT, (pull) =>
|
|
35805
|
+
const rows2 = await mapWithLimit(open, PROBE_LIMIT, (pull) => rowOf6(pr.pulls, pull));
|
|
35014
35806
|
return { rows: rows2, text: renderList(rows2, now) };
|
|
35015
35807
|
}
|
|
35016
35808
|
function createPrListCommand(seams = DEFAULT_PR_SEAMS) {
|
|
@@ -35209,17 +36001,17 @@ var init_roadmap_tick = __esm(() => {
|
|
|
35209
36001
|
import {
|
|
35210
36002
|
chmodSync,
|
|
35211
36003
|
copyFileSync as copyFileSync3,
|
|
35212
|
-
existsSync as
|
|
36004
|
+
existsSync as existsSync36,
|
|
35213
36005
|
mkdirSync as mkdirSync14,
|
|
35214
|
-
readdirSync as
|
|
35215
|
-
readFileSync as
|
|
36006
|
+
readdirSync as readdirSync15,
|
|
36007
|
+
readFileSync as readFileSync46,
|
|
35216
36008
|
realpathSync as realpathSync9,
|
|
35217
36009
|
renameSync as renameSync4,
|
|
35218
36010
|
rmSync as rmSync5,
|
|
35219
36011
|
statSync as statSync24,
|
|
35220
36012
|
symlinkSync
|
|
35221
36013
|
} from "fs";
|
|
35222
|
-
import { basename as basename16, delimiter as delimiter4, dirname as dirname17, join as join51, relative as relative15, resolve as
|
|
36014
|
+
import { basename as basename16, delimiter as delimiter4, dirname as dirname17, join as join51, relative as relative15, resolve as resolve25 } from "path";
|
|
35223
36015
|
function exitCodeFor(outcome2) {
|
|
35224
36016
|
switch (outcome2.kind) {
|
|
35225
36017
|
case "done":
|
|
@@ -35257,17 +36049,17 @@ function runtimeRefusalLines(runtimeDir, version2) {
|
|
|
35257
36049
|
];
|
|
35258
36050
|
}
|
|
35259
36051
|
function listTrackers(repoRoot, planDir) {
|
|
35260
|
-
const dir =
|
|
36052
|
+
const dir = resolve25(repoRoot, planDir);
|
|
35261
36053
|
return entryNames(dir).filter((entry) => TRACKER_NAME.test(entry)).sort((a, b) => a.localeCompare(b)).map((entry) => join51(dir, entry)).filter((path7) => statSync24(path7).isFile()).map((path7) => relative15(repoRoot, path7));
|
|
35262
36054
|
}
|
|
35263
36055
|
function openTrackers(repoRoot, planDir) {
|
|
35264
36056
|
return listTrackers(repoRoot, planDir).flatMap((path7) => {
|
|
35265
|
-
const task = findNextTask(
|
|
36057
|
+
const task = findNextTask(readFileSync46(join51(repoRoot, path7), "utf8"));
|
|
35266
36058
|
return task ? [{ path: path7, task }] : [];
|
|
35267
36059
|
});
|
|
35268
36060
|
}
|
|
35269
36061
|
function readManifestVersion2(repoRoot) {
|
|
35270
|
-
const manifest = JSON.parse(
|
|
36062
|
+
const manifest = JSON.parse(readFileSync46(join51(repoRoot, "package.json"), "utf8"));
|
|
35271
36063
|
const record = typeof manifest === "object" && manifest !== null ? manifest : {};
|
|
35272
36064
|
if (record["name"] !== name) {
|
|
35273
36065
|
throw new Error(`${join51(repoRoot, "package.json")} names ${JSON.stringify(record["name"])}, not ${name}: this is no rafa checkout`);
|
|
@@ -35281,7 +36073,7 @@ function readManifestVersion2(repoRoot) {
|
|
|
35281
36073
|
function copyTree(from, to) {
|
|
35282
36074
|
mkdirSync14(to, { recursive: true });
|
|
35283
36075
|
let copied = 0;
|
|
35284
|
-
const entries =
|
|
36076
|
+
const entries = readdirSync15(from, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
35285
36077
|
for (const entry of entries) {
|
|
35286
36078
|
const source = join51(from, entry.name);
|
|
35287
36079
|
const target = join51(to, entry.name);
|
|
@@ -35309,7 +36101,7 @@ function replaceTree(from, to) {
|
|
|
35309
36101
|
}
|
|
35310
36102
|
}
|
|
35311
36103
|
function swapIn2(staging, to) {
|
|
35312
|
-
if (!
|
|
36104
|
+
if (!existsSync36(to)) {
|
|
35313
36105
|
renameSync4(staging, to);
|
|
35314
36106
|
return;
|
|
35315
36107
|
}
|
|
@@ -35385,14 +36177,14 @@ function runInstall(seams, options) {
|
|
|
35385
36177
|
log(`runtime root: ${runtimeRoot}`);
|
|
35386
36178
|
log(`link: ${linkPath}`);
|
|
35387
36179
|
const version2 = inStage("manifest", () => readManifestVersion2(repoRoot));
|
|
35388
|
-
const planDir = inStage("config", () =>
|
|
36180
|
+
const planDir = inStage("config", () => resolve25(repoRoot, loadConfig({ root: repoRoot, home }, {}, seams.warn).config.planDir));
|
|
35389
36181
|
log(`plan dir: ${planDir}`);
|
|
35390
36182
|
const open = inStage("trackers", () => openTrackers(repoRoot, planDir));
|
|
35391
36183
|
if (open.length > 0)
|
|
35392
36184
|
return { kind: "refused", reason: "trackers", planDir, trackers: open };
|
|
35393
36185
|
const distDir = join51(repoRoot, "dist");
|
|
35394
36186
|
const runtimeDir = join51(runtimeRoot, version2);
|
|
35395
|
-
const installed =
|
|
36187
|
+
const installed = existsSync36(runtimeDir);
|
|
35396
36188
|
if (installed && options.force !== true) {
|
|
35397
36189
|
return { kind: "refused", reason: "runtime-exists", version: version2, runtimeDir };
|
|
35398
36190
|
}
|
|
@@ -35400,7 +36192,7 @@ function runInstall(seams, options) {
|
|
|
35400
36192
|
const code = inStage("build", () => seams.build(repoRoot));
|
|
35401
36193
|
if (code !== 0)
|
|
35402
36194
|
throw new StageFailure("build", `the build exited ${code}`);
|
|
35403
|
-
if (!
|
|
36195
|
+
if (!existsSync36(join51(distDir, RUNTIME_ENTRY))) {
|
|
35404
36196
|
throw new StageFailure("build", `the build exited 0 and left no ${join51(distDir, RUNTIME_ENTRY)}`);
|
|
35405
36197
|
}
|
|
35406
36198
|
log(installed ? `copying ${distDir} over ${runtimeDir}, replacing it whole` : `copying ${distDir} into ${runtimeDir}`);
|
|
@@ -35421,7 +36213,7 @@ function inStage(stage, run) {
|
|
|
35421
36213
|
}
|
|
35422
36214
|
function entryNames(dir) {
|
|
35423
36215
|
try {
|
|
35424
|
-
return
|
|
36216
|
+
return readdirSync15(dir);
|
|
35425
36217
|
} catch (err) {
|
|
35426
36218
|
if (typeof err === "object" && err !== null && "code" in err && err.code === "ENOENT")
|
|
35427
36219
|
return [];
|
|
@@ -35692,7 +36484,7 @@ var init_merge_unchecked = __esm(() => {
|
|
|
35692
36484
|
});
|
|
35693
36485
|
|
|
35694
36486
|
// src/commands/pr/merge.ts
|
|
35695
|
-
import { existsSync as
|
|
36487
|
+
import { existsSync as existsSync37, readFileSync as readFileSync47 } from "fs";
|
|
35696
36488
|
import { join as join52 } from "path";
|
|
35697
36489
|
function refusal8(lines2) {
|
|
35698
36490
|
return new CommandExit(1, lines2.join(`
|
|
@@ -35770,7 +36562,7 @@ function remoteHoldsBranch(git, branch, warn) {
|
|
|
35770
36562
|
}
|
|
35771
36563
|
function textOf3(path7) {
|
|
35772
36564
|
try {
|
|
35773
|
-
return
|
|
36565
|
+
return readFileSync47(path7, "utf8");
|
|
35774
36566
|
} catch {
|
|
35775
36567
|
return "";
|
|
35776
36568
|
}
|
|
@@ -35784,7 +36576,7 @@ function followUpsFor(pr, git) {
|
|
|
35784
36576
|
version: facts.version,
|
|
35785
36577
|
tagged: tags.ok && tags.stdout.trim() !== "",
|
|
35786
36578
|
rafaCheckout: facts.rafaCheckout,
|
|
35787
|
-
runtimeInstalled:
|
|
36579
|
+
runtimeInstalled: existsSync37(join52(pr.project.home, RUNTIME_SUBDIR, facts.version))
|
|
35788
36580
|
});
|
|
35789
36581
|
}
|
|
35790
36582
|
function openGh(pr, seams) {
|
|
@@ -35909,6 +36701,15 @@ async function runMerge(context, seams) {
|
|
|
35909
36701
|
throw lineRefusal4(`No pull request #${pick.number} at ${pr.project.root}`, USAGE28);
|
|
35910
36702
|
}
|
|
35911
36703
|
const checks = await onProvider(`read the checks of #${pick.number}`, () => pr.pulls.checks(pick.number));
|
|
36704
|
+
recordPlanCi({
|
|
36705
|
+
repoRoot: pr.project.root,
|
|
36706
|
+
planDir: pr.planDir,
|
|
36707
|
+
pullRequest: detail,
|
|
36708
|
+
rows: checks.rows,
|
|
36709
|
+
warn: (message) => {
|
|
36710
|
+
context.output.warn(message);
|
|
36711
|
+
}
|
|
36712
|
+
});
|
|
35912
36713
|
refuseFromGit(git, detail, checks, skipChecks);
|
|
35913
36714
|
const summary = summaryLine2(detail, method);
|
|
35914
36715
|
const answer4 = await askToMerge(context, pr, seams, { number: detail.number, summary, yes, skipChecks });
|
|
@@ -36030,6 +36831,7 @@ var init_merge3 = __esm(() => {
|
|
|
36030
36831
|
init_roadmap_tick();
|
|
36031
36832
|
init_command();
|
|
36032
36833
|
init_confirm();
|
|
36834
|
+
init_plan_ci();
|
|
36033
36835
|
init_ending();
|
|
36034
36836
|
init_pr();
|
|
36035
36837
|
init_runtime();
|
|
@@ -37010,8 +37812,8 @@ function describeAge(updatedAt, now) {
|
|
|
37010
37812
|
return `${plural6(hours, "hour", "hours")} ago`;
|
|
37011
37813
|
return `${plural6(Math.floor(age / DAY_MS2), "day", "days")} ago`;
|
|
37012
37814
|
}
|
|
37013
|
-
function triageCommand(number,
|
|
37014
|
-
return
|
|
37815
|
+
function triageCommand(number, resolve26 = false) {
|
|
37816
|
+
return resolve26 ? `rafa pr triage ${number} --resolve` : `rafa pr triage ${number}`;
|
|
37015
37817
|
}
|
|
37016
37818
|
function joinNumbers(pulls) {
|
|
37017
37819
|
const names = pulls.map((pull) => `#${pull.number}`);
|
|
@@ -37022,14 +37824,14 @@ function joinNumbers(pulls) {
|
|
|
37022
37824
|
function byNumber(pulls) {
|
|
37023
37825
|
return Object.freeze([...pulls].sort((left, right) => left.number - right.number));
|
|
37024
37826
|
}
|
|
37025
|
-
function skipped2(pull, now,
|
|
37827
|
+
function skipped2(pull, now, resolve26) {
|
|
37026
37828
|
return Object.freeze({
|
|
37027
37829
|
number: pull.number,
|
|
37028
37830
|
title: pull.title,
|
|
37029
37831
|
updatedAt: pull.updatedAt,
|
|
37030
37832
|
age: describeAge(pull.updatedAt, now),
|
|
37031
37833
|
fresh: isFreshCandidate(pull.updatedAt, now),
|
|
37032
|
-
command: triageCommand(pull.number,
|
|
37834
|
+
command: triageCommand(pull.number, resolve26)
|
|
37033
37835
|
});
|
|
37034
37836
|
}
|
|
37035
37837
|
function skippedLine(one) {
|
|
@@ -37073,15 +37875,15 @@ function listReading(rest, count2) {
|
|
|
37073
37875
|
return listing2("list", Object.freeze([]), rest, headline);
|
|
37074
37876
|
}
|
|
37075
37877
|
function selectTriagePullRequests(input) {
|
|
37076
|
-
const
|
|
37878
|
+
const resolve26 = input.resolve === true;
|
|
37077
37879
|
const { current, now } = input;
|
|
37078
37880
|
if (current !== null) {
|
|
37079
37881
|
return plain("branch", Object.freeze([current]), `assessing #${current.number}, the pull request open on ${current.headRefName}`);
|
|
37080
37882
|
}
|
|
37081
37883
|
const candidates = byNumber(input.candidates);
|
|
37082
37884
|
const count2 = candidates.length;
|
|
37083
|
-
const lines2 = candidates.map((pull) => skipped2(pull, now,
|
|
37084
|
-
if (
|
|
37885
|
+
const lines2 = candidates.map((pull) => skipped2(pull, now, resolve26));
|
|
37886
|
+
if (resolve26 && count2 > 1)
|
|
37085
37887
|
return refusal9(lines2, count2);
|
|
37086
37888
|
if (count2 === 0) {
|
|
37087
37889
|
return plain("none", Object.freeze([]), "no red pull request to triage, and no pull request on the current branch");
|
|
@@ -37442,7 +38244,7 @@ var init_budget2 = __esm(() => {
|
|
|
37442
38244
|
});
|
|
37443
38245
|
|
|
37444
38246
|
// src/pr/plans/load.ts
|
|
37445
|
-
import { existsSync as
|
|
38247
|
+
import { existsSync as existsSync38, readFileSync as readFileSync48 } from "fs";
|
|
37446
38248
|
import { dirname as dirname18, join as join53 } from "path";
|
|
37447
38249
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
37448
38250
|
function pinnedPlanFileName(triageClass) {
|
|
@@ -37463,11 +38265,11 @@ function readPinnedPlan(triageClass, lookup = {}) {
|
|
|
37463
38265
|
throw new Error(`No pinned resolve plan ships for ${triageClass}; ` + `one ships for ${PINNED_PLAN_CLASSES.join(", ")}`);
|
|
37464
38266
|
}
|
|
37465
38267
|
const candidates = pinnedPlanCandidates(lookup.moduleDir ?? MODULE_DIR2, triageClass);
|
|
37466
|
-
const found = candidates.find((candidate) =>
|
|
38268
|
+
const found = candidates.find((candidate) => existsSync38(candidate));
|
|
37467
38269
|
if (found === undefined) {
|
|
37468
38270
|
throw new Error(`The pinned resolve plan for ${triageClass} is missing: ` + `no file at ${candidates.join(" or ")}`);
|
|
37469
38271
|
}
|
|
37470
|
-
return
|
|
38272
|
+
return readFileSync48(found, "utf8");
|
|
37471
38273
|
}
|
|
37472
38274
|
function fillPinnedPlan(template, values) {
|
|
37473
38275
|
const missing2 = [];
|
|
@@ -38044,16 +38846,16 @@ async function redPullRequests(pr) {
|
|
|
38044
38846
|
}
|
|
38045
38847
|
return red;
|
|
38046
38848
|
}
|
|
38047
|
-
async function selectTargets(pr, warn, now,
|
|
38849
|
+
async function selectTargets(pr, warn, now, resolve26) {
|
|
38048
38850
|
const branch = readBranchOrNone(pr, warn);
|
|
38049
38851
|
const current = branch === null ? null : await onProvider(`read the open pull request for the branch "${branch}"`, () => pr.pulls.findOpen(branch));
|
|
38050
38852
|
if (current !== null)
|
|
38051
|
-
return selectTriagePullRequests({ current, candidates: [], now, resolve:
|
|
38853
|
+
return selectTriagePullRequests({ current, candidates: [], now, resolve: resolve26 });
|
|
38052
38854
|
return selectTriagePullRequests({
|
|
38053
38855
|
current: null,
|
|
38054
38856
|
candidates: await redPullRequests(pr),
|
|
38055
38857
|
now,
|
|
38056
|
-
resolve:
|
|
38858
|
+
resolve: resolve26
|
|
38057
38859
|
});
|
|
38058
38860
|
}
|
|
38059
38861
|
async function detailOf12(pr, number) {
|
|
@@ -38115,6 +38917,14 @@ async function assessOne(options) {
|
|
|
38115
38917
|
const { git, maxAttempts, number, pr } = options;
|
|
38116
38918
|
const detail = await detailOf12(pr, number);
|
|
38117
38919
|
const checks = await onProvider(`read the checks of #${number}`, () => pr.pulls.checks(number));
|
|
38920
|
+
recordPlanCi({
|
|
38921
|
+
repoRoot: pr.project.root,
|
|
38922
|
+
planDir: pr.planDir,
|
|
38923
|
+
pullRequest: detail,
|
|
38924
|
+
rows: checks.rows,
|
|
38925
|
+
warn: options.warn,
|
|
38926
|
+
now: () => new Date(options.at)
|
|
38927
|
+
});
|
|
38118
38928
|
const found = await triageCommentOf(options, detail);
|
|
38119
38929
|
const existing = found.comment;
|
|
38120
38930
|
const rerun = readTriageRerun({
|
|
@@ -38174,7 +38984,7 @@ async function runTriage(context, seams) {
|
|
|
38174
38984
|
}
|
|
38175
38985
|
const numbers = asked === null ? (selection?.assess ?? []).map((one) => one.number) : [asked];
|
|
38176
38986
|
const readings = [];
|
|
38177
|
-
let
|
|
38987
|
+
let resolve26 = null;
|
|
38178
38988
|
for (const number of numbers) {
|
|
38179
38989
|
const assess = () => assessOne({
|
|
38180
38990
|
pr,
|
|
@@ -38183,14 +38993,17 @@ async function runTriage(context, seams) {
|
|
|
38183
38993
|
wantsComment,
|
|
38184
38994
|
maxAttempts,
|
|
38185
38995
|
at: now(),
|
|
38186
|
-
permissions
|
|
38996
|
+
permissions,
|
|
38997
|
+
warn: (message) => {
|
|
38998
|
+
context.output.warn(message);
|
|
38999
|
+
}
|
|
38187
39000
|
});
|
|
38188
39001
|
const reading2 = await assess();
|
|
38189
39002
|
if (!wantsResolve) {
|
|
38190
39003
|
readings.push(reading2);
|
|
38191
39004
|
continue;
|
|
38192
39005
|
}
|
|
38193
|
-
|
|
39006
|
+
resolve26 = await resolvePullRequest({
|
|
38194
39007
|
trust: {
|
|
38195
39008
|
permissions,
|
|
38196
39009
|
trustedAuthors: pr.trustedAuthors,
|
|
@@ -38211,16 +39024,16 @@ async function runTriage(context, seams) {
|
|
|
38211
39024
|
...seams.clock === undefined ? {} : { clock: seams.clock },
|
|
38212
39025
|
...seams.sleep === undefined ? {} : { sleep: seams.sleep }
|
|
38213
39026
|
});
|
|
38214
|
-
readings.push(
|
|
39027
|
+
readings.push(resolve26.reading);
|
|
38215
39028
|
}
|
|
38216
39029
|
const text2 = [
|
|
38217
39030
|
...selection === null ? [] : [selection.message],
|
|
38218
39031
|
...readings.length === 0 ? [] : [renderTriages(readings)],
|
|
38219
|
-
...
|
|
39032
|
+
...resolve26 === null ? [] : resolve26.lines
|
|
38220
39033
|
].join(`
|
|
38221
39034
|
|
|
38222
39035
|
`);
|
|
38223
|
-
return { selection, readings, resolve:
|
|
39036
|
+
return { selection, readings, resolve: resolve26, text: text2, exitCode: resolve26?.exitCode ?? 0 };
|
|
38224
39037
|
}
|
|
38225
39038
|
function createPrTriageCommand(seams = DEFAULT_TRIAGE_SEAMS) {
|
|
38226
39039
|
const command = {
|
|
@@ -38295,6 +39108,7 @@ var USAGE30, DEFAULT_MAX_ATTEMPTS = 2, DETACHED_HEAD2 = "HEAD", RESOLVED = false
|
|
|
38295
39108
|
var init_triage4 = __esm(() => {
|
|
38296
39109
|
init_command();
|
|
38297
39110
|
init_config_sections();
|
|
39111
|
+
init_plan_ci();
|
|
38298
39112
|
init_ending();
|
|
38299
39113
|
init_pr();
|
|
38300
39114
|
init_classify3();
|
|
@@ -38539,7 +39353,7 @@ var init_wait = __esm(() => {
|
|
|
38539
39353
|
});
|
|
38540
39354
|
|
|
38541
39355
|
// src/commands/release/status.ts
|
|
38542
|
-
import { existsSync as
|
|
39356
|
+
import { existsSync as existsSync39, readdirSync as readdirSync16, readFileSync as readFileSync49 } from "fs";
|
|
38543
39357
|
import { join as join55 } from "path";
|
|
38544
39358
|
function compareIdentifiers(left, right) {
|
|
38545
39359
|
const leftNumeric = NUMERIC_IDENTIFIER.test(left);
|
|
@@ -38630,7 +39444,7 @@ function untaggedVersions(released, tags) {
|
|
|
38630
39444
|
}
|
|
38631
39445
|
function textOf4(path7) {
|
|
38632
39446
|
try {
|
|
38633
|
-
return
|
|
39447
|
+
return readFileSync49(path7, "utf8");
|
|
38634
39448
|
} catch {
|
|
38635
39449
|
return null;
|
|
38636
39450
|
}
|
|
@@ -38671,12 +39485,12 @@ function readBranch2(git) {
|
|
|
38671
39485
|
const branch = result.stdout.trim();
|
|
38672
39486
|
return result.ok && branch !== "" && branch !== "HEAD" ? branch : null;
|
|
38673
39487
|
}
|
|
38674
|
-
function
|
|
39488
|
+
function planStubsUnder2(root, planDir) {
|
|
38675
39489
|
const resolved = join55(root, planDir);
|
|
38676
|
-
if (!
|
|
39490
|
+
if (!existsSync39(resolved))
|
|
38677
39491
|
return [];
|
|
38678
39492
|
try {
|
|
38679
|
-
return planStubsFromFileNames(
|
|
39493
|
+
return planStubsFromFileNames(readdirSync16(resolved));
|
|
38680
39494
|
} catch {
|
|
38681
39495
|
return [];
|
|
38682
39496
|
}
|
|
@@ -38829,7 +39643,7 @@ function readStatus(context, seams = DEFAULT_RELEASE_SEAMS) {
|
|
|
38829
39643
|
versionFile: readVersionFile(project.root, config.versionFile),
|
|
38830
39644
|
tags,
|
|
38831
39645
|
untagged: readUntagged(project.root, config.changelog, tags.tags),
|
|
38832
|
-
plan: readPending(project.root, asked, readBranch2(git),
|
|
39646
|
+
plan: readPending(project.root, asked, readBranch2(git), planStubsUnder2(project.root, config.planDir), readNotes)
|
|
38833
39647
|
};
|
|
38834
39648
|
return { reading: reading2, text: renderStatus2(reading2) };
|
|
38835
39649
|
}
|
|
@@ -38893,7 +39707,7 @@ var init_status3 = __esm(() => {
|
|
|
38893
39707
|
});
|
|
38894
39708
|
|
|
38895
39709
|
// src/commands/release/tag.ts
|
|
38896
|
-
import { readFileSync as
|
|
39710
|
+
import { readFileSync as readFileSync50 } from "fs";
|
|
38897
39711
|
import { join as join56 } from "path";
|
|
38898
39712
|
function readBranch3(git) {
|
|
38899
39713
|
const result = git(["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
@@ -38908,7 +39722,7 @@ function readBranch3(git) {
|
|
|
38908
39722
|
}
|
|
38909
39723
|
function textOf5(path7) {
|
|
38910
39724
|
try {
|
|
38911
|
-
return
|
|
39725
|
+
return readFileSync50(path7, "utf8");
|
|
38912
39726
|
} catch {
|
|
38913
39727
|
return null;
|
|
38914
39728
|
}
|
|
@@ -39244,7 +40058,7 @@ var init_self_update = __esm(() => {
|
|
|
39244
40058
|
});
|
|
39245
40059
|
|
|
39246
40060
|
// src/backfill/proposal-file.ts
|
|
39247
|
-
import { readdirSync as
|
|
40061
|
+
import { readdirSync as readdirSync17, readFileSync as readFileSync51 } from "fs";
|
|
39248
40062
|
import { join as join57 } from "path";
|
|
39249
40063
|
function proposalPath(dir, batch) {
|
|
39250
40064
|
return join57(dir, `${PROPOSAL_FILE_PREFIX}${String(batch).padStart(2, "0")}${PROPOSAL_FILE_EXTENSION}`);
|
|
@@ -39378,14 +40192,14 @@ function parseProposalFile(text2) {
|
|
|
39378
40192
|
function readProposalFiles(dir) {
|
|
39379
40193
|
let names;
|
|
39380
40194
|
try {
|
|
39381
|
-
names =
|
|
40195
|
+
names = readdirSync17(dir);
|
|
39382
40196
|
} catch {
|
|
39383
40197
|
return [];
|
|
39384
40198
|
}
|
|
39385
40199
|
return names.filter((name2) => isProposalFileName(name2)).sort((left, right) => left.localeCompare(right)).map((name2) => {
|
|
39386
40200
|
const path7 = join57(dir, name2);
|
|
39387
40201
|
try {
|
|
39388
|
-
return { path: path7, result: parseProposalFile(
|
|
40202
|
+
return { path: path7, result: parseProposalFile(readFileSync51(path7, "utf8")) };
|
|
39389
40203
|
} catch (error) {
|
|
39390
40204
|
return { path: path7, result: unreadable2(`the file cannot be read (${error instanceof Error ? error.message : String(error)})`) };
|
|
39391
40205
|
}
|
|
@@ -39416,19 +40230,19 @@ var init_proposal_file = __esm(() => {
|
|
|
39416
40230
|
});
|
|
39417
40231
|
|
|
39418
40232
|
// src/backfill/backup.ts
|
|
39419
|
-
import { copyFileSync as copyFileSync4, existsSync as
|
|
39420
|
-
import { dirname as dirname19, isAbsolute as isAbsolute15, join as join58, relative as relative16, resolve as
|
|
40233
|
+
import { copyFileSync as copyFileSync4, existsSync as existsSync40, mkdirSync as mkdirSync16 } from "fs";
|
|
40234
|
+
import { dirname as dirname19, isAbsolute as isAbsolute15, join as join58, relative as relative16, resolve as resolve26, sep as sep6 } from "path";
|
|
39421
40235
|
function backupDirectory(base) {
|
|
39422
40236
|
return join58(base, BACKUP_PATH);
|
|
39423
40237
|
}
|
|
39424
40238
|
function isUnder(root, path7) {
|
|
39425
|
-
const step2 = relative16(
|
|
40239
|
+
const step2 = relative16(resolve26(root), resolve26(path7));
|
|
39426
40240
|
return step2 === "" || !step2.startsWith(`..${sep6}`) && step2 !== ".." && !isAbsolute15(step2);
|
|
39427
40241
|
}
|
|
39428
40242
|
function backupPathFor(path7, root, backupDir) {
|
|
39429
40243
|
if (!isUnder(root, path7))
|
|
39430
40244
|
return null;
|
|
39431
|
-
return join58(backupDir, relative16(
|
|
40245
|
+
return join58(backupDir, relative16(resolve26(root), resolve26(path7)));
|
|
39432
40246
|
}
|
|
39433
40247
|
function backupFile(path7, options) {
|
|
39434
40248
|
if (options.repoRoot !== null && isUnder(options.repoRoot, path7)) {
|
|
@@ -39437,9 +40251,9 @@ function backupFile(path7, options) {
|
|
|
39437
40251
|
const backup = backupPathFor(path7, options.root, options.backupDir);
|
|
39438
40252
|
if (backup === null)
|
|
39439
40253
|
return { path: path7, kind: "outside", backup: null };
|
|
39440
|
-
if (!
|
|
40254
|
+
if (!existsSync40(path7))
|
|
39441
40255
|
return { path: path7, kind: "missing", backup: null };
|
|
39442
|
-
if (
|
|
40256
|
+
if (existsSync40(backup))
|
|
39443
40257
|
return { path: path7, kind: "kept", backup };
|
|
39444
40258
|
mkdirSync16(dirname19(backup), { recursive: true });
|
|
39445
40259
|
copyFileSync4(path7, backup);
|
|
@@ -39470,7 +40284,7 @@ var init_backup = __esm(() => {
|
|
|
39470
40284
|
});
|
|
39471
40285
|
|
|
39472
40286
|
// src/backfill/derive.ts
|
|
39473
|
-
import { readFileSync as
|
|
40287
|
+
import { readFileSync as readFileSync52, writeFileSync as writeFileSync18 } from "fs";
|
|
39474
40288
|
import { basename as basename17 } from "path";
|
|
39475
40289
|
function renderWhenToUse(trigger, prevents) {
|
|
39476
40290
|
return `${sentenceEnded(trigger)} Prevents: ${prevents}`;
|
|
@@ -39589,7 +40403,7 @@ function planFile(entry, options) {
|
|
|
39589
40403
|
}
|
|
39590
40404
|
let original;
|
|
39591
40405
|
try {
|
|
39592
|
-
original =
|
|
40406
|
+
original = readFileSync52(entry.path, "utf8");
|
|
39593
40407
|
} catch (error) {
|
|
39594
40408
|
return inert(entry, "skipped", `the file cannot be read (${error instanceof Error ? error.message : String(error)})`);
|
|
39595
40409
|
}
|
|
@@ -39633,7 +40447,7 @@ function planDerivation(root, options) {
|
|
|
39633
40447
|
function applyFile(action, options) {
|
|
39634
40448
|
if (action.text === null || action.original === null)
|
|
39635
40449
|
return action;
|
|
39636
|
-
const current =
|
|
40450
|
+
const current = readFileSync52(action.path, "utf8");
|
|
39637
40451
|
if (current !== action.original) {
|
|
39638
40452
|
return {
|
|
39639
40453
|
...action,
|
|
@@ -39911,7 +40725,7 @@ var init_report3 = __esm(() => {
|
|
|
39911
40725
|
});
|
|
39912
40726
|
|
|
39913
40727
|
// src/backfill/proposal-batch.ts
|
|
39914
|
-
import { readFileSync as
|
|
40728
|
+
import { readFileSync as readFileSync53 } from "fs";
|
|
39915
40729
|
import { relative as relative17 } from "path";
|
|
39916
40730
|
function candidateNeeds(data, body) {
|
|
39917
40731
|
const needs = [];
|
|
@@ -39936,7 +40750,7 @@ function readCandidate(root, entry) {
|
|
|
39936
40750
|
return null;
|
|
39937
40751
|
let text2;
|
|
39938
40752
|
try {
|
|
39939
|
-
text2 =
|
|
40753
|
+
text2 = readFileSync53(entry.path, "utf8");
|
|
39940
40754
|
} catch {
|
|
39941
40755
|
return null;
|
|
39942
40756
|
}
|
|
@@ -40086,8 +40900,8 @@ The files:
|
|
|
40086
40900
|
});
|
|
40087
40901
|
|
|
40088
40902
|
// src/backfill/propose.ts
|
|
40089
|
-
import { mkdirSync as mkdirSync17, readFileSync as
|
|
40090
|
-
import { join as join59, resolve as
|
|
40903
|
+
import { mkdirSync as mkdirSync17, readFileSync as readFileSync54, writeFileSync as writeFileSync19 } from "fs";
|
|
40904
|
+
import { join as join59, resolve as resolve27 } from "path";
|
|
40091
40905
|
function unanswered(candidate, note) {
|
|
40092
40906
|
return {
|
|
40093
40907
|
path: candidate.relative,
|
|
@@ -40239,7 +41053,7 @@ function applyRow(root, row3, options) {
|
|
|
40239
41053
|
}
|
|
40240
41054
|
let original;
|
|
40241
41055
|
try {
|
|
40242
|
-
original =
|
|
41056
|
+
original = readFileSync54(path7, "utf8");
|
|
40243
41057
|
} catch {
|
|
40244
41058
|
return inert2(path7, row3, "refused", "the file the row names is gone");
|
|
40245
41059
|
}
|
|
@@ -40253,7 +41067,7 @@ function fileRefusal(file, root) {
|
|
|
40253
41067
|
if (file.status !== REVIEWED_FILE) {
|
|
40254
41068
|
return `the proposal file is still marked ${file.status}: review it and mark it ${REVIEWED_FILE}`;
|
|
40255
41069
|
}
|
|
40256
|
-
return
|
|
41070
|
+
return resolve27(file.skills) === resolve27(root) ? null : `the proposal file names the skills directory ${file.skills}, not ${root}`;
|
|
40257
41071
|
}
|
|
40258
41072
|
function countProposalActions(actions) {
|
|
40259
41073
|
const counts = Object.fromEntries(PROPOSAL_ACTION_KINDS.map((kind) => [kind, 0]));
|
|
@@ -40294,7 +41108,7 @@ var init_propose = __esm(() => {
|
|
|
40294
41108
|
});
|
|
40295
41109
|
|
|
40296
41110
|
// src/demote/select.ts
|
|
40297
|
-
import { readdirSync as
|
|
41111
|
+
import { readdirSync as readdirSync18, readFileSync as readFileSync55, realpathSync as realpathSync10, statSync as statSync25 } from "fs";
|
|
40298
41112
|
import { basename as basename18, dirname as dirname20, join as join60 } from "path";
|
|
40299
41113
|
function realOrSelf(path7) {
|
|
40300
41114
|
try {
|
|
@@ -40341,7 +41155,7 @@ function entryKind2(path7) {
|
|
|
40341
41155
|
}
|
|
40342
41156
|
function visibleNames2(dir) {
|
|
40343
41157
|
try {
|
|
40344
|
-
return
|
|
41158
|
+
return readdirSync18(dir).filter((name2) => !name2.startsWith(".")).sort((left, right) => left.localeCompare(right));
|
|
40345
41159
|
} catch {
|
|
40346
41160
|
return [];
|
|
40347
41161
|
}
|
|
@@ -40350,7 +41164,7 @@ function readSelected(absolute, path7, entries) {
|
|
|
40350
41164
|
let text2;
|
|
40351
41165
|
let mtime;
|
|
40352
41166
|
try {
|
|
40353
|
-
text2 =
|
|
41167
|
+
text2 = readFileSync55(absolute, "utf8");
|
|
40354
41168
|
mtime = statSync25(absolute).mtime.toISOString();
|
|
40355
41169
|
} catch {
|
|
40356
41170
|
return null;
|
|
@@ -40413,7 +41227,7 @@ var init_select3 = __esm(() => {
|
|
|
40413
41227
|
|
|
40414
41228
|
// src/commands/skill/backfill.ts
|
|
40415
41229
|
import { statSync as statSync26 } from "fs";
|
|
40416
|
-
import { join as join61, resolve as
|
|
41230
|
+
import { join as join61, resolve as resolve28 } from "path";
|
|
40417
41231
|
function readSwitch3(name2, value) {
|
|
40418
41232
|
if (value === undefined || value === false || value === "false")
|
|
40419
41233
|
return false;
|
|
@@ -40443,7 +41257,7 @@ Usage: ${BACKFILL_USAGE}`);
|
|
|
40443
41257
|
throw new CommandExit(1, `\u274C Expected one directory, and read "${extra}" as a second
|
|
40444
41258
|
Usage: ${BACKFILL_USAGE}`);
|
|
40445
41259
|
}
|
|
40446
|
-
return
|
|
41260
|
+
return resolve28(cwd(), dir);
|
|
40447
41261
|
}
|
|
40448
41262
|
function readConsumerRoot(value, cwd) {
|
|
40449
41263
|
if (value === undefined || value === false)
|
|
@@ -40452,7 +41266,7 @@ function readConsumerRoot(value, cwd) {
|
|
|
40452
41266
|
throw new CommandExit(1, `\u274C --project needs a path, and the line gave it none
|
|
40453
41267
|
Usage: ${BACKFILL_USAGE}`);
|
|
40454
41268
|
}
|
|
40455
|
-
return
|
|
41269
|
+
return resolve28(cwd(), value);
|
|
40456
41270
|
}
|
|
40457
41271
|
function isDirectory4(path7) {
|
|
40458
41272
|
try {
|
|
@@ -40759,7 +41573,7 @@ var init_check3 = __esm(() => {
|
|
|
40759
41573
|
});
|
|
40760
41574
|
|
|
40761
41575
|
// src/demote/apply.ts
|
|
40762
|
-
import { copyFileSync as copyFileSync5, existsSync as
|
|
41576
|
+
import { copyFileSync as copyFileSync5, existsSync as existsSync41, mkdirSync as mkdirSync18, mkdtempSync as mkdtempSync2, readdirSync as readdirSync19, readFileSync as readFileSync56, renameSync as renameSync5, rmSync as rmSync6, statSync as statSync27, unlinkSync as unlinkSync2, writeFileSync as writeFileSync20 } from "fs";
|
|
40763
41577
|
import { tmpdir as tmpdir2 } from "os";
|
|
40764
41578
|
import { dirname as dirname21, join as join62 } from "path";
|
|
40765
41579
|
function isLearnedPath(path7) {
|
|
@@ -40782,7 +41596,7 @@ function promotedPath(scope, path7) {
|
|
|
40782
41596
|
function takenInstinctIds(dir) {
|
|
40783
41597
|
let names;
|
|
40784
41598
|
try {
|
|
40785
|
-
names =
|
|
41599
|
+
names = readdirSync19(dir);
|
|
40786
41600
|
} catch {
|
|
40787
41601
|
return [];
|
|
40788
41602
|
}
|
|
@@ -40790,7 +41604,7 @@ function takenInstinctIds(dir) {
|
|
|
40790
41604
|
}
|
|
40791
41605
|
function readText9(path7) {
|
|
40792
41606
|
try {
|
|
40793
|
-
return statSync27(path7).isFile() ?
|
|
41607
|
+
return statSync27(path7).isFile() ? readFileSync56(path7, "utf8") : null;
|
|
40794
41608
|
} catch {
|
|
40795
41609
|
return null;
|
|
40796
41610
|
}
|
|
@@ -40818,7 +41632,7 @@ function planKept(scope, row3, file) {
|
|
|
40818
41632
|
return inert3(row3.path, "procedure", "kept", "procedure-shaped: left where it is, for the backfill");
|
|
40819
41633
|
}
|
|
40820
41634
|
const to = promotedPath(scope, row3.path);
|
|
40821
|
-
if (
|
|
41635
|
+
if (existsSync41(to) || existsSync41(dirname21(to))) {
|
|
40822
41636
|
return inert3(row3.path, "procedure", "refused", `kept as a skill, but ${to} is already there`);
|
|
40823
41637
|
}
|
|
40824
41638
|
return {
|
|
@@ -40855,9 +41669,9 @@ function planDemoted(scope, row3, file, context) {
|
|
|
40855
41669
|
}
|
|
40856
41670
|
const destination = join62(scope.instinctsDir, `${id}${MARKDOWN_EXTENSION}`);
|
|
40857
41671
|
const kept = demotedPath(scope, row3.path);
|
|
40858
|
-
if (
|
|
41672
|
+
if (existsSync41(destination))
|
|
40859
41673
|
return inert3(row3.path, "observation", "refused", `${destination} is already there`);
|
|
40860
|
-
if (
|
|
41674
|
+
if (existsSync41(kept))
|
|
40861
41675
|
return inert3(row3.path, "observation", "refused", `${kept} is already there`);
|
|
40862
41676
|
context.taken.push(id);
|
|
40863
41677
|
return {
|
|
@@ -40986,8 +41800,8 @@ var init_draft = __esm(() => {
|
|
|
40986
41800
|
});
|
|
40987
41801
|
|
|
40988
41802
|
// src/commands/skill/demote.ts
|
|
40989
|
-
import { existsSync as
|
|
40990
|
-
import { dirname as dirname22, resolve as
|
|
41803
|
+
import { existsSync as existsSync42, mkdirSync as mkdirSync19, readFileSync as readFileSync57, statSync as statSync28, writeFileSync as writeFileSync21 } from "fs";
|
|
41804
|
+
import { dirname as dirname22, resolve as resolve29 } from "path";
|
|
40991
41805
|
function readApply(value) {
|
|
40992
41806
|
if (value === undefined || value === false || value === "false")
|
|
40993
41807
|
return false;
|
|
@@ -41006,7 +41820,7 @@ Usage: ${DEMOTE_USAGE}`);
|
|
|
41006
41820
|
throw new CommandExit(1, `\u274C Expected one directory, and read "${extra}" as a second
|
|
41007
41821
|
Usage: ${DEMOTE_USAGE}`);
|
|
41008
41822
|
}
|
|
41009
|
-
return
|
|
41823
|
+
return resolve29(cwd(), dir);
|
|
41010
41824
|
}
|
|
41011
41825
|
function isDirectory5(path7) {
|
|
41012
41826
|
try {
|
|
@@ -41038,9 +41852,9 @@ function verdictLine(report3) {
|
|
|
41038
41852
|
return `${String(report3.rows.length)} file(s): ${parts.join(", ")}`;
|
|
41039
41853
|
}
|
|
41040
41854
|
function previousReport(path7, context) {
|
|
41041
|
-
if (!
|
|
41855
|
+
if (!existsSync42(path7))
|
|
41042
41856
|
return null;
|
|
41043
|
-
const parsed = parseDemotionReport(
|
|
41857
|
+
const parsed = parseDemotionReport(readFileSync57(path7, "utf8"));
|
|
41044
41858
|
if (parsed.report !== null)
|
|
41045
41859
|
return parsed.report;
|
|
41046
41860
|
context.output.warn(`the report already at ${path7} does not parse, so no override in it is carried forward:` + ` ${parsed.issues.map((issue5) => `line ${String(issue5.line)} ${issue5.code}`).join(", ")}`);
|
|
@@ -41073,10 +41887,10 @@ function runWrite(context, scope) {
|
|
|
41073
41887
|
context.output.info(line);
|
|
41074
41888
|
}
|
|
41075
41889
|
function reviewedReport(scope) {
|
|
41076
|
-
if (!
|
|
41890
|
+
if (!existsSync42(scope.reportPath)) {
|
|
41077
41891
|
throw new CommandExit(1, `\u274C No report at ${scope.reportPath}; run "rafa skill demote ${scope.dir}" first, then review it`);
|
|
41078
41892
|
}
|
|
41079
|
-
const parsed = parseDemotionReport(
|
|
41893
|
+
const parsed = parseDemotionReport(readFileSync57(scope.reportPath, "utf8"));
|
|
41080
41894
|
if (parsed.report === null) {
|
|
41081
41895
|
const lines2 = parsed.issues.map((issue5) => ` line ${String(issue5.line)} ${issue5.code}: ${issue5.message}`);
|
|
41082
41896
|
throw new CommandExit(1, [`\u274C ${scope.reportPath} does not parse:`, ...lines2].join(`
|
|
@@ -41434,9 +42248,9 @@ function boundedRunner(open, root, deadline) {
|
|
|
41434
42248
|
}
|
|
41435
42249
|
async function networkSection(what, deadline, work) {
|
|
41436
42250
|
let timer;
|
|
41437
|
-
const expired = new Promise((
|
|
42251
|
+
const expired = new Promise((resolve30) => {
|
|
41438
42252
|
timer = setTimeout(() => {
|
|
41439
|
-
|
|
42253
|
+
resolve30(unread2(`the ${what} was not read within the ${String(deadline.ms)}ms network deadline`));
|
|
41440
42254
|
}, Math.max(0, deadline.left()));
|
|
41441
42255
|
});
|
|
41442
42256
|
try {
|
|
@@ -42414,7 +43228,7 @@ init_config_sections();
|
|
|
42414
43228
|
init_sessions();
|
|
42415
43229
|
init_scope();
|
|
42416
43230
|
init_sections2();
|
|
42417
|
-
import { mkdirSync as mkdirSync20, readFileSync as
|
|
43231
|
+
import { mkdirSync as mkdirSync20, readFileSync as readFileSync58, renameSync as renameSync6, writeFileSync as writeFileSync22 } from "fs";
|
|
42418
43232
|
import { dirname as dirname23, join as join63 } from "path";
|
|
42419
43233
|
var SEEN_FILE = "status-seen.json";
|
|
42420
43234
|
var SEEN_VERSION = 1;
|
|
@@ -42474,7 +43288,7 @@ function asSnapshot(value) {
|
|
|
42474
43288
|
function readSeenFile(root) {
|
|
42475
43289
|
let text2;
|
|
42476
43290
|
try {
|
|
42477
|
-
text2 =
|
|
43291
|
+
text2 = readFileSync58(seenFilePath(root), "utf8");
|
|
42478
43292
|
} catch {
|
|
42479
43293
|
return null;
|
|
42480
43294
|
}
|