@gitgov/core 2.8.0 → 2.9.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/dist/src/{agent_runner-D3G5zzGv.d.ts → agent_runner-Cgle_zVX.d.ts} +2 -2
- package/dist/src/fs.d.ts +14 -175
- package/dist/src/fs.js +209 -2157
- package/dist/src/fs.js.map +1 -1
- package/dist/src/github.d.ts +2 -2
- package/dist/src/index.d.ts +482 -333
- package/dist/src/index.js +248 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/memory.d.ts +1 -1
- package/dist/src/prisma.d.ts +1 -1
- package/dist/src/{record_projection.types-B2OZbgoW.d.ts → record_projection.types-CFsl44em.d.ts} +13 -1
- package/dist/src/{sync_state-GmqG3pLj.d.ts → sync_state-B8X4NDKF.d.ts} +2 -2
- package/package.json +1 -1
package/dist/src/index.js
CHANGED
|
@@ -28,6 +28,25 @@ __export(adapters_exports, {
|
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
// src/record_types/common.types.ts
|
|
31
|
+
var RECORD_TYPES = [
|
|
32
|
+
"actor",
|
|
33
|
+
"agent",
|
|
34
|
+
"cycle",
|
|
35
|
+
"task",
|
|
36
|
+
"execution",
|
|
37
|
+
"feedback"
|
|
38
|
+
];
|
|
39
|
+
var DIR_TO_TYPE = {
|
|
40
|
+
"tasks": "task",
|
|
41
|
+
"cycles": "cycle",
|
|
42
|
+
"executions": "execution",
|
|
43
|
+
"feedbacks": "feedback",
|
|
44
|
+
"actors": "actor",
|
|
45
|
+
"agents": "agent"
|
|
46
|
+
};
|
|
47
|
+
var TYPE_TO_DIR = Object.fromEntries(
|
|
48
|
+
Object.entries(DIR_TO_TYPE).map(([dir, type]) => [type, dir])
|
|
49
|
+
);
|
|
31
50
|
var GitGovError = class extends Error {
|
|
32
51
|
constructor(message, code) {
|
|
33
52
|
super(message);
|
|
@@ -921,6 +940,7 @@ var embedded_metadata_schema_default = {
|
|
|
921
940
|
if: {
|
|
922
941
|
properties: {
|
|
923
942
|
header: {
|
|
943
|
+
type: "object",
|
|
924
944
|
properties: {
|
|
925
945
|
type: {
|
|
926
946
|
const: "custom"
|
|
@@ -945,6 +965,7 @@ var embedded_metadata_schema_default = {
|
|
|
945
965
|
if: {
|
|
946
966
|
properties: {
|
|
947
967
|
header: {
|
|
968
|
+
type: "object",
|
|
948
969
|
properties: {
|
|
949
970
|
type: {
|
|
950
971
|
const: "actor"
|
|
@@ -965,6 +986,7 @@ var embedded_metadata_schema_default = {
|
|
|
965
986
|
if: {
|
|
966
987
|
properties: {
|
|
967
988
|
header: {
|
|
989
|
+
type: "object",
|
|
968
990
|
properties: {
|
|
969
991
|
type: {
|
|
970
992
|
const: "agent"
|
|
@@ -985,6 +1007,7 @@ var embedded_metadata_schema_default = {
|
|
|
985
1007
|
if: {
|
|
986
1008
|
properties: {
|
|
987
1009
|
header: {
|
|
1010
|
+
type: "object",
|
|
988
1011
|
properties: {
|
|
989
1012
|
type: {
|
|
990
1013
|
const: "task"
|
|
@@ -1005,6 +1028,7 @@ var embedded_metadata_schema_default = {
|
|
|
1005
1028
|
if: {
|
|
1006
1029
|
properties: {
|
|
1007
1030
|
header: {
|
|
1031
|
+
type: "object",
|
|
1008
1032
|
properties: {
|
|
1009
1033
|
type: {
|
|
1010
1034
|
const: "execution"
|
|
@@ -1025,6 +1049,7 @@ var embedded_metadata_schema_default = {
|
|
|
1025
1049
|
if: {
|
|
1026
1050
|
properties: {
|
|
1027
1051
|
header: {
|
|
1052
|
+
type: "object",
|
|
1028
1053
|
properties: {
|
|
1029
1054
|
type: {
|
|
1030
1055
|
const: "feedback"
|
|
@@ -1045,6 +1070,7 @@ var embedded_metadata_schema_default = {
|
|
|
1045
1070
|
if: {
|
|
1046
1071
|
properties: {
|
|
1047
1072
|
header: {
|
|
1073
|
+
type: "object",
|
|
1048
1074
|
properties: {
|
|
1049
1075
|
type: {
|
|
1050
1076
|
const: "cycle"
|
|
@@ -1065,6 +1091,7 @@ var embedded_metadata_schema_default = {
|
|
|
1065
1091
|
if: {
|
|
1066
1092
|
properties: {
|
|
1067
1093
|
header: {
|
|
1094
|
+
type: "object",
|
|
1068
1095
|
properties: {
|
|
1069
1096
|
type: {
|
|
1070
1097
|
const: "workflow"
|
|
@@ -6742,6 +6769,7 @@ var FsFileLister = class {
|
|
|
6742
6769
|
);
|
|
6743
6770
|
}
|
|
6744
6771
|
}
|
|
6772
|
+
const normalized = patterns.map((p) => p.endsWith("/") ? `${p}**` : p);
|
|
6745
6773
|
const fgOptions = {
|
|
6746
6774
|
cwd: this.cwd,
|
|
6747
6775
|
ignore: options?.ignore ?? [],
|
|
@@ -6752,7 +6780,7 @@ var FsFileLister = class {
|
|
|
6752
6780
|
if (options?.maxDepth !== void 0) {
|
|
6753
6781
|
fgOptions.deep = options.maxDepth;
|
|
6754
6782
|
}
|
|
6755
|
-
return fg(
|
|
6783
|
+
return fg(normalized, fgOptions);
|
|
6756
6784
|
}
|
|
6757
6785
|
/**
|
|
6758
6786
|
* [EARS-FL02] Checks if a file exists.
|
|
@@ -8056,6 +8084,220 @@ function isRebaseAlreadyInProgressError(error) {
|
|
|
8056
8084
|
return error instanceof RebaseAlreadyInProgressError;
|
|
8057
8085
|
}
|
|
8058
8086
|
|
|
8087
|
+
// src/hook_handler/index.ts
|
|
8088
|
+
var hook_handler_exports = {};
|
|
8089
|
+
__export(hook_handler_exports, {
|
|
8090
|
+
HookHandler: () => HookHandler,
|
|
8091
|
+
classifyCommand: () => classifyCommand
|
|
8092
|
+
});
|
|
8093
|
+
|
|
8094
|
+
// src/hook_handler/hook_handler.ts
|
|
8095
|
+
var HookHandler = class {
|
|
8096
|
+
executionAdapter;
|
|
8097
|
+
sessionManager;
|
|
8098
|
+
configManager;
|
|
8099
|
+
constructor(deps) {
|
|
8100
|
+
this.executionAdapter = deps.executionAdapter;
|
|
8101
|
+
this.sessionManager = deps.sessionManager;
|
|
8102
|
+
this.configManager = deps.configManager;
|
|
8103
|
+
}
|
|
8104
|
+
/**
|
|
8105
|
+
* Process a hook event and decide whether to create an ExecutionRecord.
|
|
8106
|
+
* Fail-silent: catches all errors and returns { action: 'skipped', reason }.
|
|
8107
|
+
*/
|
|
8108
|
+
async handleEvent(event, options = {}) {
|
|
8109
|
+
const dryRun = options.dryRun ?? false;
|
|
8110
|
+
try {
|
|
8111
|
+
const config = await this.configManager.loadConfig();
|
|
8112
|
+
if (!config) {
|
|
8113
|
+
return { action: "skipped", reason: "no config" };
|
|
8114
|
+
}
|
|
8115
|
+
if (isFileChangedEvent(event)) {
|
|
8116
|
+
return { action: "skipped", reason: "file changes are not recorded" };
|
|
8117
|
+
}
|
|
8118
|
+
if (isTeammateIdleEvent(event)) {
|
|
8119
|
+
return { action: "skipped", reason: "activity logged" };
|
|
8120
|
+
}
|
|
8121
|
+
const actorId = await this.resolveActorId();
|
|
8122
|
+
const activeTaskId = actorId ? (await this.sessionManager.getActorState(actorId))?.activeTaskId ?? null : null;
|
|
8123
|
+
if (isSessionEndEvent(event)) {
|
|
8124
|
+
return await this.handleSessionEnd(event, actorId, activeTaskId, dryRun);
|
|
8125
|
+
}
|
|
8126
|
+
if (!activeTaskId) {
|
|
8127
|
+
return { action: "skipped", reason: "no active task" };
|
|
8128
|
+
}
|
|
8129
|
+
if (isCommandExecutedEvent(event)) {
|
|
8130
|
+
return await this.handleCommandExecuted(event, actorId, activeTaskId, dryRun);
|
|
8131
|
+
}
|
|
8132
|
+
if (isTaskCompletedEvent(event)) {
|
|
8133
|
+
return await this.handleTaskCompleted(event, actorId, activeTaskId, dryRun);
|
|
8134
|
+
}
|
|
8135
|
+
return { action: "skipped", reason: "unknown event type" };
|
|
8136
|
+
} catch (error) {
|
|
8137
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
8138
|
+
return { action: "skipped", reason: message };
|
|
8139
|
+
}
|
|
8140
|
+
}
|
|
8141
|
+
// ─── Command Executed ──────────────────────────────────────
|
|
8142
|
+
async handleCommandExecuted(event, actorId, activeTaskId, dryRun = false) {
|
|
8143
|
+
if (event.exit_code !== 0) {
|
|
8144
|
+
return { action: "skipped", reason: "command failed" };
|
|
8145
|
+
}
|
|
8146
|
+
const classification = classifyCommand(event.tool_input.command, event.tool_output);
|
|
8147
|
+
if (classification.kind === "unknown") {
|
|
8148
|
+
return { action: "skipped", reason: "unrecognized command" };
|
|
8149
|
+
}
|
|
8150
|
+
const payload = this.buildCommandPayload(classification, activeTaskId);
|
|
8151
|
+
if (dryRun) {
|
|
8152
|
+
return { action: "recorded", executionId: "dry-run" };
|
|
8153
|
+
}
|
|
8154
|
+
const record = await this.executionAdapter.create(payload, actorId);
|
|
8155
|
+
return { action: "recorded", executionId: record.id };
|
|
8156
|
+
}
|
|
8157
|
+
buildCommandPayload(classification, activeTaskId) {
|
|
8158
|
+
switch (classification.kind) {
|
|
8159
|
+
// [EARS-B2]
|
|
8160
|
+
case "commit":
|
|
8161
|
+
return {
|
|
8162
|
+
taskId: activeTaskId,
|
|
8163
|
+
type: "completion",
|
|
8164
|
+
title: `Commit ${classification.hash}`,
|
|
8165
|
+
result: `Commit ${classification.hash}: ${classification.message} (${classification.filesChanged} files changed)`,
|
|
8166
|
+
references: [`commit:${classification.hash}`]
|
|
8167
|
+
};
|
|
8168
|
+
// [EARS-B3]
|
|
8169
|
+
case "pr":
|
|
8170
|
+
return {
|
|
8171
|
+
taskId: activeTaskId,
|
|
8172
|
+
type: "completion",
|
|
8173
|
+
title: `PR #${classification.number} created`,
|
|
8174
|
+
result: `PR #${classification.number} created`,
|
|
8175
|
+
references: [`pr:${classification.number}`]
|
|
8176
|
+
};
|
|
8177
|
+
// [EARS-B4]
|
|
8178
|
+
case "test":
|
|
8179
|
+
return {
|
|
8180
|
+
taskId: activeTaskId,
|
|
8181
|
+
type: "analysis",
|
|
8182
|
+
title: "Test run",
|
|
8183
|
+
result: `Tests: ${classification.passed}/${classification.total} passing, ${classification.failed} failed`,
|
|
8184
|
+
metadata: { tests: { passed: classification.passed, failed: classification.failed, total: classification.total } }
|
|
8185
|
+
};
|
|
8186
|
+
}
|
|
8187
|
+
}
|
|
8188
|
+
// ─── Task Completed ────────────────────────────────────────
|
|
8189
|
+
async handleTaskCompleted(event, actorId, activeTaskId, dryRun = false) {
|
|
8190
|
+
const payload = {
|
|
8191
|
+
taskId: activeTaskId,
|
|
8192
|
+
type: "completion",
|
|
8193
|
+
title: `Task completed: ${event.task.subject}`,
|
|
8194
|
+
result: `Task "${event.task.subject}" completed${event.task.owner ? ` by ${event.task.owner}` : ""}`,
|
|
8195
|
+
references: [`task:${event.task.id}`]
|
|
8196
|
+
};
|
|
8197
|
+
if (dryRun) {
|
|
8198
|
+
return { action: "recorded", executionId: "dry-run" };
|
|
8199
|
+
}
|
|
8200
|
+
const record = await this.executionAdapter.create(payload, actorId);
|
|
8201
|
+
return { action: "recorded", executionId: record.id };
|
|
8202
|
+
}
|
|
8203
|
+
// ─── Session End ───────────────────────────────────────────
|
|
8204
|
+
async handleSessionEnd(event, actorId, activeTaskId, dryRun = false) {
|
|
8205
|
+
if (!actorId) {
|
|
8206
|
+
return { action: "skipped", reason: "no actor" };
|
|
8207
|
+
}
|
|
8208
|
+
if (!activeTaskId) {
|
|
8209
|
+
return { action: "skipped", reason: "no active task" };
|
|
8210
|
+
}
|
|
8211
|
+
const taskId = activeTaskId;
|
|
8212
|
+
const payload = {
|
|
8213
|
+
taskId,
|
|
8214
|
+
type: "analysis",
|
|
8215
|
+
title: "Session ended",
|
|
8216
|
+
result: `Session ended${event.session_id ? ` (${event.session_id})` : ""}`
|
|
8217
|
+
};
|
|
8218
|
+
if (dryRun) {
|
|
8219
|
+
return { action: "recorded", executionId: "dry-run" };
|
|
8220
|
+
}
|
|
8221
|
+
const record = await this.executionAdapter.create(payload, actorId);
|
|
8222
|
+
return { action: "recorded", executionId: record.id };
|
|
8223
|
+
}
|
|
8224
|
+
// ─── Helpers ───────────────────────────────────────────────
|
|
8225
|
+
async resolveActorId() {
|
|
8226
|
+
const lastSession = await this.sessionManager.getLastSession();
|
|
8227
|
+
if (lastSession) return lastSession.actorId;
|
|
8228
|
+
const detectedId = await this.sessionManager.detectActorFromKeyFiles();
|
|
8229
|
+
return detectedId;
|
|
8230
|
+
}
|
|
8231
|
+
};
|
|
8232
|
+
function isCommandExecutedEvent(event) {
|
|
8233
|
+
return "tool_name" in event && event.tool_name === "Bash";
|
|
8234
|
+
}
|
|
8235
|
+
function isFileChangedEvent(event) {
|
|
8236
|
+
return "tool_name" in event && (event.tool_name === "Write" || event.tool_name === "Edit");
|
|
8237
|
+
}
|
|
8238
|
+
function isTaskCompletedEvent(event) {
|
|
8239
|
+
return "hook_type" in event && event.hook_type === "TaskCompleted";
|
|
8240
|
+
}
|
|
8241
|
+
function isTeammateIdleEvent(event) {
|
|
8242
|
+
return "hook_type" in event && event.hook_type === "TeammateIdle";
|
|
8243
|
+
}
|
|
8244
|
+
function isSessionEndEvent(event) {
|
|
8245
|
+
return "hook_type" in event && event.hook_type === "Stop";
|
|
8246
|
+
}
|
|
8247
|
+
function classifyCommand(command, output) {
|
|
8248
|
+
if (/git\s+commit/.test(command)) {
|
|
8249
|
+
return parseCommitOutput(output);
|
|
8250
|
+
}
|
|
8251
|
+
if (/gh\s+pr\s+create/.test(command)) {
|
|
8252
|
+
return parsePrOutput(output);
|
|
8253
|
+
}
|
|
8254
|
+
if (/(?:jest|vitest|pytest|npm\s+test|pnpm\s+test|npx\s+vitest|npx\s+jest)/.test(command)) {
|
|
8255
|
+
return parseTestOutput(output);
|
|
8256
|
+
}
|
|
8257
|
+
return { kind: "unknown" };
|
|
8258
|
+
}
|
|
8259
|
+
function parseCommitOutput(output) {
|
|
8260
|
+
if (!output) return { kind: "commit", hash: "unknown", message: "", filesChanged: 0 };
|
|
8261
|
+
const hashMatch = output.match(/\[[\w/.-]+\s+([a-f0-9]+)\]/);
|
|
8262
|
+
const hash = hashMatch?.[1] ?? "unknown";
|
|
8263
|
+
const messageMatch = output.match(/\]\s+(.+?)(?:\n|$)/);
|
|
8264
|
+
const message = messageMatch?.[1] ?? "";
|
|
8265
|
+
const filesMatch = output.match(/(\d+)\s+files?\s+changed/);
|
|
8266
|
+
const filesChanged = filesMatch?.[1] ? parseInt(filesMatch[1], 10) : 0;
|
|
8267
|
+
return { kind: "commit", hash, message, filesChanged };
|
|
8268
|
+
}
|
|
8269
|
+
function parsePrOutput(output) {
|
|
8270
|
+
if (!output) return { kind: "pr", number: "unknown" };
|
|
8271
|
+
const prMatch = output.match(/\/pull\/(\d+)/);
|
|
8272
|
+
if (prMatch?.[1]) return { kind: "pr", number: prMatch[1] };
|
|
8273
|
+
const numMatch = output.match(/#(\d+)/);
|
|
8274
|
+
return { kind: "pr", number: numMatch?.[1] ?? "unknown" };
|
|
8275
|
+
}
|
|
8276
|
+
function parseTestOutput(output) {
|
|
8277
|
+
if (!output) return { kind: "test", passed: 0, failed: 0, total: 0 };
|
|
8278
|
+
let passed = 0;
|
|
8279
|
+
let failed = 0;
|
|
8280
|
+
let total = 0;
|
|
8281
|
+
const vitestMatch = output.match(/Tests?\s+(\d+)\s+passed/);
|
|
8282
|
+
const failedMatch = output.match(/(\d+)\s+failed/);
|
|
8283
|
+
const totalMatch = output.match(/(\d+)\s+total/);
|
|
8284
|
+
if (vitestMatch?.[1]) passed = parseInt(vitestMatch[1], 10);
|
|
8285
|
+
if (failedMatch?.[1]) failed = parseInt(failedMatch[1], 10);
|
|
8286
|
+
if (totalMatch?.[1]) {
|
|
8287
|
+
total = parseInt(totalMatch[1], 10);
|
|
8288
|
+
} else {
|
|
8289
|
+
total = passed + failed;
|
|
8290
|
+
}
|
|
8291
|
+
if (!vitestMatch) {
|
|
8292
|
+
const pytestPassed = output.match(/(\d+)\s+passed/);
|
|
8293
|
+
const pytestFailed = output.match(/(\d+)\s+failed/);
|
|
8294
|
+
if (pytestPassed?.[1]) passed = parseInt(pytestPassed[1], 10);
|
|
8295
|
+
if (pytestFailed?.[1]) failed = parseInt(pytestFailed[1], 10);
|
|
8296
|
+
total = passed + failed;
|
|
8297
|
+
}
|
|
8298
|
+
return { kind: "test", passed, failed, total };
|
|
8299
|
+
}
|
|
8300
|
+
|
|
8059
8301
|
// src/record_validations/index.ts
|
|
8060
8302
|
var record_validations_exports = {};
|
|
8061
8303
|
__export(record_validations_exports, {
|
|
@@ -8097,7 +8339,10 @@ __export(record_validations_exports, {
|
|
|
8097
8339
|
// src/record_types/index.ts
|
|
8098
8340
|
var record_types_exports = {};
|
|
8099
8341
|
__export(record_types_exports, {
|
|
8100
|
-
|
|
8342
|
+
DIR_TO_TYPE: () => DIR_TO_TYPE,
|
|
8343
|
+
GitGovError: () => GitGovError,
|
|
8344
|
+
RECORD_TYPES: () => RECORD_TYPES,
|
|
8345
|
+
TYPE_TO_DIR: () => TYPE_TO_DIR
|
|
8101
8346
|
});
|
|
8102
8347
|
|
|
8103
8348
|
// src/event_bus/index.ts
|
|
@@ -11044,6 +11289,6 @@ var RecordProjector = class {
|
|
|
11044
11289
|
}
|
|
11045
11290
|
};
|
|
11046
11291
|
|
|
11047
|
-
export { adapters_exports as Adapters, backlog_adapter_exports as BacklogAdapter, config_manager_exports as Config, crypto_exports as Crypto, diagram_generator_exports as DiagramGenerator, event_bus_exports as EventBus, execution_adapter_exports as ExecutionAdapter, record_factories_exports as Factories, feedback_adapter_exports as FeedbackAdapter, file_lister_exports as FileLister, finding_detector_exports as FindingDetector, git_exports as Git, identity_adapter_exports as IdentityAdapter, key_provider_exports as KeyProvider, lint_exports as Lint, logger_exports as Logger, project_adapter_exports as ProjectAdapter, project_initializer_exports as ProjectInitializer, record_metrics_exports as RecordMetrics, record_projection_exports as RecordProjection, record_types_exports as Records, agent_runner_exports as Runner, record_schemas_exports as Schemas, session_manager_exports as Session, source_auditor_exports as SourceAuditor, record_store_exports as Store, sync_state_exports as SyncState, record_validations_exports as Validation, workflow_adapter_exports as WorkflowAdapter };
|
|
11292
|
+
export { adapters_exports as Adapters, backlog_adapter_exports as BacklogAdapter, config_manager_exports as Config, crypto_exports as Crypto, diagram_generator_exports as DiagramGenerator, event_bus_exports as EventBus, execution_adapter_exports as ExecutionAdapter, record_factories_exports as Factories, feedback_adapter_exports as FeedbackAdapter, file_lister_exports as FileLister, finding_detector_exports as FindingDetector, git_exports as Git, hook_handler_exports as HookHandler, identity_adapter_exports as IdentityAdapter, key_provider_exports as KeyProvider, lint_exports as Lint, logger_exports as Logger, project_adapter_exports as ProjectAdapter, project_initializer_exports as ProjectInitializer, record_metrics_exports as RecordMetrics, record_projection_exports as RecordProjection, record_types_exports as Records, agent_runner_exports as Runner, record_schemas_exports as Schemas, session_manager_exports as Session, source_auditor_exports as SourceAuditor, record_store_exports as Store, sync_state_exports as SyncState, record_validations_exports as Validation, workflow_adapter_exports as WorkflowAdapter };
|
|
11048
11293
|
//# sourceMappingURL=index.js.map
|
|
11049
11294
|
//# sourceMappingURL=index.js.map
|