@xn-intenton-z2a/agentic-lib 7.4.15 → 7.4.17
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/.github/workflows/agentic-lib-init.yml +2 -2
- package/.github/workflows/agentic-lib-schedule.yml +2 -2
- package/.github/workflows/agentic-lib-test.yml +3 -3
- package/.github/workflows/agentic-lib-update.yml +2 -2
- package/.github/workflows/agentic-lib-workflow.yml +11 -7
- package/agentic-lib.toml +1 -1
- package/bin/agentic-lib.js +1 -0
- package/package.json +1 -1
- package/src/actions/agentic-step/index.js +3 -0
- package/src/actions/agentic-step/tasks/supervise.js +62 -4
- package/src/actions/commit-if-changed/action.yml +10 -1
- package/src/copilot/github-tools.js +8 -2
- package/src/copilot/state.js +4 -1
- package/src/copilot/telemetry.js +4 -0
- package/src/seeds/zero-package.json +1 -1
|
@@ -145,7 +145,7 @@ jobs:
|
|
|
145
145
|
create-seed-issues: ${{ steps.resolve.outputs.create-seed-issues }}
|
|
146
146
|
steps:
|
|
147
147
|
- id: resolve
|
|
148
|
-
uses: actions/github-script@
|
|
148
|
+
uses: actions/github-script@v8
|
|
149
149
|
with:
|
|
150
150
|
script: |
|
|
151
151
|
core.setOutput('dry-run', context.payload.inputs?.['dry-run'] || 'false');
|
|
@@ -435,7 +435,7 @@ jobs:
|
|
|
435
435
|
|
|
436
436
|
- name: Job Summary
|
|
437
437
|
if: always()
|
|
438
|
-
uses: actions/github-script@
|
|
438
|
+
uses: actions/github-script@v8
|
|
439
439
|
with:
|
|
440
440
|
script: |
|
|
441
441
|
const summary = `## Job: init\n| Key | Value |\n|-----|-------|\n| Status | ${context.job.status || 'completed'} |\n| Mode | ${{ inputs.mode }} |\n| Dry Run | ${{ inputs.dry-run }} |\n| Create Seed Issues | ${{ inputs.create-seed-issues }} |`;
|
|
@@ -88,7 +88,7 @@ jobs:
|
|
|
88
88
|
maintenance: ${{ steps.resolve.outputs.maintenance }}
|
|
89
89
|
steps:
|
|
90
90
|
- id: resolve
|
|
91
|
-
uses: actions/github-script@
|
|
91
|
+
uses: actions/github-script@v8
|
|
92
92
|
with:
|
|
93
93
|
script: |
|
|
94
94
|
const frequency = context.payload.inputs?.['frequency'] || 'off';
|
|
@@ -308,7 +308,7 @@ jobs:
|
|
|
308
308
|
|
|
309
309
|
- name: Job Summary
|
|
310
310
|
if: always()
|
|
311
|
-
uses: actions/github-script@
|
|
311
|
+
uses: actions/github-script@v8
|
|
312
312
|
with:
|
|
313
313
|
script: |
|
|
314
314
|
const summary = `## Job: update-schedule\n| Key | Value |\n|-----|-------|\n| Status | ${context.job.status || 'completed'} |\n| Frequency | ${{ inputs.frequency }} |\n| Model | ${{ inputs.model || 'default' }} |\n| Profile | ${{ inputs.profile || 'default' }} |`;
|
|
@@ -64,7 +64,7 @@ jobs:
|
|
|
64
64
|
dry-run: ${{ steps.resolve.outputs.dry-run }}
|
|
65
65
|
steps:
|
|
66
66
|
- id: resolve
|
|
67
|
-
uses: actions/github-script@
|
|
67
|
+
uses: actions/github-script@v8
|
|
68
68
|
with:
|
|
69
69
|
script: |
|
|
70
70
|
core.setOutput('dry-run', context.payload.inputs?.['dry-run'] || 'false');
|
|
@@ -100,7 +100,7 @@ jobs:
|
|
|
100
100
|
|
|
101
101
|
- name: Job Summary
|
|
102
102
|
if: always()
|
|
103
|
-
uses: actions/github-script@
|
|
103
|
+
uses: actions/github-script@v8
|
|
104
104
|
with:
|
|
105
105
|
script: |
|
|
106
106
|
const summary = `## Job: test\n| Key | Value |\n|-----|-------|\n| Status | ${context.job.status || 'completed'} |`;
|
|
@@ -161,7 +161,7 @@ jobs:
|
|
|
161
161
|
|
|
162
162
|
- name: Job Summary
|
|
163
163
|
if: always()
|
|
164
|
-
uses: actions/github-script@
|
|
164
|
+
uses: actions/github-script@v8
|
|
165
165
|
with:
|
|
166
166
|
script: |
|
|
167
167
|
const summary = `## Job: behaviour\n| Key | Value |\n|-----|-------|\n| Status | ${context.job.status || 'completed'} |\n| Tests Failed | ${{ steps.result.outputs.tests-failed }} |`;
|
|
@@ -43,7 +43,7 @@ jobs:
|
|
|
43
43
|
dry-run: ${{ steps.resolve.outputs.dry-run }}
|
|
44
44
|
steps:
|
|
45
45
|
- id: resolve
|
|
46
|
-
uses: actions/github-script@
|
|
46
|
+
uses: actions/github-script@v8
|
|
47
47
|
with:
|
|
48
48
|
script: |
|
|
49
49
|
core.setOutput('dry-run', context.payload.inputs?.['dry-run'] || 'false');
|
|
@@ -124,7 +124,7 @@ jobs:
|
|
|
124
124
|
|
|
125
125
|
- name: Job Summary
|
|
126
126
|
if: always()
|
|
127
|
-
uses: actions/github-script@
|
|
127
|
+
uses: actions/github-script@v8
|
|
128
128
|
with:
|
|
129
129
|
script: |
|
|
130
130
|
const summary = `## Job: update\n| Key | Value |\n|-----|-------|\n| Status | ${context.job.status || 'completed'} |\n| Dry Run | ${{ inputs.dry-run }} |`;
|
|
@@ -590,6 +590,7 @@ jobs:
|
|
|
590
590
|
LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
|
|
591
591
|
SCREENSHOT_FILE: ${{ needs.params.outputs.screenshot-file }}
|
|
592
592
|
run: |
|
|
593
|
+
git fetch origin "${LOG_BRANCH}" 2>/dev/null || true
|
|
593
594
|
git show "origin/${LOG_BRANCH}:${SCREENSHOT_FILE}" > "${SCREENSHOT_FILE}" 2>/dev/null || true
|
|
594
595
|
git show "origin/${LOG_BRANCH}:agentic-lib-state.toml" > "agentic-lib-state.toml" 2>/dev/null || true
|
|
595
596
|
|
|
@@ -701,7 +702,7 @@ jobs:
|
|
|
701
702
|
if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
|
|
702
703
|
env:
|
|
703
704
|
LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
|
|
704
|
-
run: bash .github/agentic-lib/scripts/push-to-logs.sh agent-log-*.md
|
|
705
|
+
run: bash .github/agentic-lib/scripts/push-to-logs.sh agent-log-*.md agentic-lib-state.toml
|
|
705
706
|
|
|
706
707
|
# ─── Implementation Review: traces mission elements through code/tests/website ──
|
|
707
708
|
implementation-review:
|
|
@@ -725,10 +726,10 @@ jobs:
|
|
|
725
726
|
LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
|
|
726
727
|
SCREENSHOT_FILE: ${{ needs.params.outputs.screenshot-file }}
|
|
727
728
|
run: |
|
|
729
|
+
git fetch origin "${LOG_BRANCH}" 2>/dev/null || true
|
|
728
730
|
git show "origin/${LOG_BRANCH}:${SCREENSHOT_FILE}" > "${SCREENSHOT_FILE}" 2>/dev/null || true
|
|
729
731
|
git show "origin/${LOG_BRANCH}:agentic-lib-state.toml" > "agentic-lib-state.toml" 2>/dev/null || true
|
|
730
732
|
mkdir -p .agent-logs
|
|
731
|
-
git fetch origin "${LOG_BRANCH}" 2>/dev/null || true
|
|
732
733
|
for f in $(git ls-tree --name-only "origin/${LOG_BRANCH}" 2>/dev/null | grep '^agent-log-' || true); do
|
|
733
734
|
git show "origin/${LOG_BRANCH}:${f}" > ".agent-logs/${f}" 2>/dev/null || true
|
|
734
735
|
done
|
|
@@ -767,7 +768,7 @@ jobs:
|
|
|
767
768
|
if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
|
|
768
769
|
env:
|
|
769
770
|
LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
|
|
770
|
-
run: bash .github/agentic-lib/scripts/push-to-logs.sh agent-log-*.md
|
|
771
|
+
run: bash .github/agentic-lib/scripts/push-to-logs.sh agent-log-*.md agentic-lib-state.toml
|
|
771
772
|
|
|
772
773
|
# ─── Director: LLM evaluates mission status (complete/failed/in-progress) ──
|
|
773
774
|
director:
|
|
@@ -791,6 +792,7 @@ jobs:
|
|
|
791
792
|
LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
|
|
792
793
|
SCREENSHOT_FILE: ${{ needs.params.outputs.screenshot-file }}
|
|
793
794
|
run: |
|
|
795
|
+
git fetch origin "${LOG_BRANCH}" 2>/dev/null || true
|
|
794
796
|
git show "origin/${LOG_BRANCH}:${SCREENSHOT_FILE}" > "${SCREENSHOT_FILE}" 2>/dev/null || true
|
|
795
797
|
git show "origin/${LOG_BRANCH}:agentic-lib-state.toml" > "agentic-lib-state.toml" 2>/dev/null || true
|
|
796
798
|
|
|
@@ -829,7 +831,7 @@ jobs:
|
|
|
829
831
|
if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
|
|
830
832
|
env:
|
|
831
833
|
LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
|
|
832
|
-
run: bash .github/agentic-lib/scripts/push-to-logs.sh agent-log-*.md
|
|
834
|
+
run: bash .github/agentic-lib/scripts/push-to-logs.sh agent-log-*.md agentic-lib-state.toml
|
|
833
835
|
|
|
834
836
|
# ─── Supervisor: LLM decides what to do (after director evaluates) ──
|
|
835
837
|
supervisor:
|
|
@@ -854,12 +856,13 @@ jobs:
|
|
|
854
856
|
LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
|
|
855
857
|
SCREENSHOT_FILE: ${{ needs.params.outputs.screenshot-file }}
|
|
856
858
|
run: |
|
|
859
|
+
git fetch origin "${LOG_BRANCH}" 2>/dev/null || true
|
|
857
860
|
git show "origin/${LOG_BRANCH}:${SCREENSHOT_FILE}" > "${SCREENSHOT_FILE}" 2>/dev/null || true
|
|
858
861
|
git show "origin/${LOG_BRANCH}:agentic-lib-state.toml" > "agentic-lib-state.toml" 2>/dev/null || true
|
|
859
862
|
|
|
860
863
|
- name: "C15: Check nop backoff"
|
|
861
864
|
id: backoff
|
|
862
|
-
uses: actions/github-script@
|
|
865
|
+
uses: actions/github-script@v8
|
|
863
866
|
with:
|
|
864
867
|
script: |
|
|
865
868
|
const fs = require('fs');
|
|
@@ -916,7 +919,7 @@ jobs:
|
|
|
916
919
|
if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
|
|
917
920
|
env:
|
|
918
921
|
LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
|
|
919
|
-
run: bash .github/agentic-lib/scripts/push-to-logs.sh agent-log-*.md
|
|
922
|
+
run: bash .github/agentic-lib/scripts/push-to-logs.sh agent-log-*.md agentic-lib-state.toml
|
|
920
923
|
|
|
921
924
|
# ─── Fix stuck PRs with failing checks ─────────────────────────────
|
|
922
925
|
fix-stuck:
|
|
@@ -1315,6 +1318,7 @@ jobs:
|
|
|
1315
1318
|
LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
|
|
1316
1319
|
SCREENSHOT_FILE: ${{ needs.params.outputs.screenshot-file }}
|
|
1317
1320
|
run: |
|
|
1321
|
+
git fetch origin "${LOG_BRANCH}" 2>/dev/null || true
|
|
1318
1322
|
git show "origin/${LOG_BRANCH}:${SCREENSHOT_FILE}" > "${SCREENSHOT_FILE}" 2>/dev/null || true
|
|
1319
1323
|
git show "origin/${LOG_BRANCH}:agentic-lib-state.toml" > "agentic-lib-state.toml" 2>/dev/null || true
|
|
1320
1324
|
|
|
@@ -1486,7 +1490,7 @@ jobs:
|
|
|
1486
1490
|
if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
|
|
1487
1491
|
env:
|
|
1488
1492
|
LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
|
|
1489
|
-
run: bash .github/agentic-lib/scripts/push-to-logs.sh agent-log-*.md
|
|
1493
|
+
run: bash .github/agentic-lib/scripts/push-to-logs.sh agent-log-*.md agentic-lib-state.toml
|
|
1490
1494
|
|
|
1491
1495
|
- name: Create PR and attempt merge
|
|
1492
1496
|
if: github.repository != 'xn-intenton-z2a/agentic-lib' && steps.issue.outputs.issue-number != '' && needs.params.outputs.dry-run != 'true' && steps.pre-commit-test.outputs.tests-passed == 'true' && steps.pre-commit-behaviour-test.outputs.tests-passed != 'false'
|
package/agentic-lib.toml
CHANGED
|
@@ -109,7 +109,7 @@ library-limit = 64 # max library entries in library/ directo
|
|
|
109
109
|
[mission-complete]
|
|
110
110
|
# Thresholds for deterministic mission-complete declaration.
|
|
111
111
|
# All conditions must be met simultaneously.
|
|
112
|
-
min-resolved-issues =
|
|
112
|
+
min-resolved-issues = 1 # minimum closed-as-RESOLVED issues since init
|
|
113
113
|
max-source-todos = 0 # max TODO comments allowed in ./src (0 = none)
|
|
114
114
|
# C6: Removed min-dedicated-tests (replaced by cumulative transforms and acceptance criteria)
|
|
115
115
|
|
package/bin/agentic-lib.js
CHANGED
package/package.json
CHANGED
|
@@ -120,6 +120,7 @@ async function run() {
|
|
|
120
120
|
outcome: result.outcome || "completed",
|
|
121
121
|
transformationCost,
|
|
122
122
|
tokensUsed: result.tokensUsed || 0,
|
|
123
|
+
durationMs,
|
|
123
124
|
});
|
|
124
125
|
// C2: Use cumulative cost from persistent state (not just this task)
|
|
125
126
|
const cumulativeCost = state.counters["cumulative-transforms"] || 0;
|
|
@@ -145,6 +146,8 @@ async function run() {
|
|
|
145
146
|
transformationCost,
|
|
146
147
|
tokensUsed: result.tokensUsed || 0,
|
|
147
148
|
cumulativeTokens: state.counters["total-tokens"] || 0,
|
|
149
|
+
durationMs,
|
|
150
|
+
cumulativeDurationMs: state.counters["total-duration-ms"] || 0,
|
|
148
151
|
};
|
|
149
152
|
const missionMetrics = buildMissionMetrics(config, result, limitsStatus, cumulativeCost, featureIssueCount, maintenanceIssueCount, taskCosts);
|
|
150
153
|
|
|
@@ -579,8 +579,61 @@ async function executeDispatch(octokit, repo, actionName, params, ctx) {
|
|
|
579
579
|
}
|
|
580
580
|
|
|
581
581
|
async function executeCreateIssue(octokit, repo, params, ctx) {
|
|
582
|
-
|
|
583
|
-
|
|
582
|
+
// Derive title: use params.title, fall back to first line of body, fall back to feature name
|
|
583
|
+
let title = (params.title || "").trim();
|
|
584
|
+
const bodyText = (params.body || params.details || "").trim();
|
|
585
|
+
const feature = (params.feature || "").trim();
|
|
586
|
+
|
|
587
|
+
if (!title && bodyText) {
|
|
588
|
+
// Extract title from body: use first heading or first non-empty line
|
|
589
|
+
const headingMatch = bodyText.match(/^#+ (.+)/m);
|
|
590
|
+
const titleMatch = bodyText.match(/^Title:\s*(.+)/im);
|
|
591
|
+
if (titleMatch) {
|
|
592
|
+
title = titleMatch[1].trim();
|
|
593
|
+
} else if (headingMatch) {
|
|
594
|
+
title = headingMatch[1].trim();
|
|
595
|
+
} else {
|
|
596
|
+
// Use first line, truncated
|
|
597
|
+
title = bodyText.split("\n")[0].substring(0, 120).trim();
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
if (!title && feature) {
|
|
601
|
+
title = `feat: implement ${feature}`;
|
|
602
|
+
}
|
|
603
|
+
if (!title) {
|
|
604
|
+
core.warning("create-issue: no title, body, or feature provided — skipping");
|
|
605
|
+
return "skipped:no-title";
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
const rawLabels = params.labels;
|
|
609
|
+
const labels = Array.isArray(rawLabels)
|
|
610
|
+
? rawLabels.map((l) => String(l).trim()).filter(Boolean)
|
|
611
|
+
: typeof rawLabels === "string"
|
|
612
|
+
? rawLabels.split(",").map((l) => l.trim()).filter(Boolean)
|
|
613
|
+
: ["automated"];
|
|
614
|
+
if (!labels.includes("automated")) labels.push("automated");
|
|
615
|
+
|
|
616
|
+
// Build rich issue body with context
|
|
617
|
+
const bodyParts = [];
|
|
618
|
+
if (bodyText) {
|
|
619
|
+
bodyParts.push(bodyText);
|
|
620
|
+
}
|
|
621
|
+
if (feature) {
|
|
622
|
+
bodyParts.push("");
|
|
623
|
+
bodyParts.push(`## Related Feature`);
|
|
624
|
+
bodyParts.push(`Feature spec: \`features/${feature}.md\``);
|
|
625
|
+
}
|
|
626
|
+
// Add mission context from MISSION.md
|
|
627
|
+
const missionText = ctx?.mission || "";
|
|
628
|
+
if (missionText) {
|
|
629
|
+
const missionHeading = missionText.match(/^#\s+(.+)/m);
|
|
630
|
+
const missionName = missionHeading ? missionHeading[1].trim() : "MISSION.md";
|
|
631
|
+
bodyParts.push("");
|
|
632
|
+
bodyParts.push(`## Context`);
|
|
633
|
+
bodyParts.push(`Mission: ${missionName}`);
|
|
634
|
+
bodyParts.push(`Created by: agentic-step supervisor`);
|
|
635
|
+
}
|
|
636
|
+
const body = bodyParts.join("\n");
|
|
584
637
|
|
|
585
638
|
// Dedup guard: skip if a similarly-titled issue was closed in the last hour
|
|
586
639
|
// Exclude issues closed before the init timestamp (cross-scenario protection)
|
|
@@ -610,13 +663,18 @@ async function executeCreateIssue(octokit, repo, params, ctx) {
|
|
|
610
663
|
}
|
|
611
664
|
|
|
612
665
|
core.info(`Creating issue: ${title}`);
|
|
613
|
-
const { data: issue } = await octokit.rest.issues.create({ ...repo, title, labels });
|
|
666
|
+
const { data: issue } = await octokit.rest.issues.create({ ...repo, title, body, labels });
|
|
614
667
|
return `created-issue:#${issue.number}`;
|
|
615
668
|
}
|
|
616
669
|
|
|
617
670
|
async function executeLabelIssue(octokit, repo, params) {
|
|
618
671
|
const issueNumber = Number(params["issue-number"]);
|
|
619
|
-
const
|
|
672
|
+
const rawLabels = params.labels;
|
|
673
|
+
const labels = Array.isArray(rawLabels)
|
|
674
|
+
? rawLabels.map((l) => String(l).trim()).filter(Boolean)
|
|
675
|
+
: typeof rawLabels === "string"
|
|
676
|
+
? rawLabels.split(",").map((l) => l.trim()).filter(Boolean)
|
|
677
|
+
: [];
|
|
620
678
|
if (issueNumber && labels.length > 0) {
|
|
621
679
|
core.info(`Labelling issue #${issueNumber}: ${labels.join(", ")}`);
|
|
622
680
|
await octokit.rest.issues.addLabels({ ...repo, issue_number: issueNumber, labels });
|
|
@@ -28,9 +28,10 @@ runs:
|
|
|
28
28
|
git add -A
|
|
29
29
|
# Unstage workflow files — GITHUB_TOKEN cannot push workflow changes
|
|
30
30
|
git reset HEAD -- '.github/workflows/' 2>/dev/null || true
|
|
31
|
-
# Unstage log/screenshot files — these live on the agentic-lib-logs branch
|
|
31
|
+
# Unstage log/screenshot/state files — these live on the agentic-lib-logs branch
|
|
32
32
|
git reset HEAD -- 'intentïon.md' 'SCREENSHOT_INDEX.png' 2>/dev/null || true
|
|
33
33
|
git reset HEAD -- agent-log-*.md 2>/dev/null || true
|
|
34
|
+
git reset HEAD -- agentic-lib-state.toml 2>/dev/null || true
|
|
34
35
|
if git diff --cached --quiet; then
|
|
35
36
|
echo "No changes to commit"
|
|
36
37
|
fi
|
|
@@ -57,6 +58,14 @@ runs:
|
|
|
57
58
|
sleep $((attempt * 2))
|
|
58
59
|
continue
|
|
59
60
|
}
|
|
61
|
+
# After rebase, check if our changes survived (rebase may drop empty commits)
|
|
62
|
+
LOCAL_SHA=$(git rev-parse HEAD)
|
|
63
|
+
REMOTE_SHA=$(git rev-parse "origin/$REF" 2>/dev/null || echo "")
|
|
64
|
+
if [ "$LOCAL_SHA" = "$REMOTE_SHA" ]; then
|
|
65
|
+
echo "Rebase dropped local commit (already on remote) — nothing to push"
|
|
66
|
+
PUSH_SUCCESS="true"
|
|
67
|
+
break
|
|
68
|
+
fi
|
|
60
69
|
fi
|
|
61
70
|
# Use HEAD:refs/heads/$REF to handle detached HEAD state
|
|
62
71
|
# (actions/checkout with a SHA puts us in detached HEAD, so
|
|
@@ -242,11 +242,17 @@ export function createGitHubTools(octokit, repo, defineTool, logger = defaultLog
|
|
|
242
242
|
required: ["title"],
|
|
243
243
|
},
|
|
244
244
|
handler: async ({ title, body, labels }) => {
|
|
245
|
+
const REJECTED_TITLES = ["untitled", "untitled issue", "no title", "new issue", "issue", ""];
|
|
246
|
+
const trimmed = (title || "").trim();
|
|
247
|
+
if (!trimmed || REJECTED_TITLES.includes(trimmed.toLowerCase())) {
|
|
248
|
+
logger.warning(`[tool] create_issue: rejected empty/generic title "${title}"`);
|
|
249
|
+
return { error: `Issue title "${title}" is too generic. Provide a specific, descriptive title.` };
|
|
250
|
+
}
|
|
245
251
|
try {
|
|
246
252
|
const { data: issue } = await octokit.rest.issues.create({
|
|
247
|
-
...repo, title, body: body || "", labels: labels || [],
|
|
253
|
+
...repo, title: trimmed, body: body || "", labels: labels || [],
|
|
248
254
|
});
|
|
249
|
-
logger.info(`[tool] create_issue: #${issue.number} "${
|
|
255
|
+
logger.info(`[tool] create_issue: #${issue.number} "${trimmed}"`);
|
|
250
256
|
return { number: issue.number, url: issue.html_url, title: issue.title };
|
|
251
257
|
} catch (err) {
|
|
252
258
|
return { error: `Failed to create issue: ${err.message}` };
|
package/src/copilot/state.js
CHANGED
|
@@ -20,6 +20,7 @@ export function defaultState() {
|
|
|
20
20
|
"cumulative-maintain-library": 0,
|
|
21
21
|
"cumulative-nop-cycles": 0,
|
|
22
22
|
"total-tokens": 0,
|
|
23
|
+
"total-duration-ms": 0,
|
|
23
24
|
},
|
|
24
25
|
budget: {
|
|
25
26
|
"transformation-budget-used": 0,
|
|
@@ -176,14 +177,16 @@ export function resetConsecutiveNops(state) {
|
|
|
176
177
|
* @param {string} params.outcome - Task outcome
|
|
177
178
|
* @param {number} params.transformationCost - 0 or 1
|
|
178
179
|
* @param {number} params.tokensUsed - Tokens consumed by this task
|
|
180
|
+
* @param {number} [params.durationMs] - Task wall-clock duration in milliseconds
|
|
179
181
|
* @returns {Object} The same state object (mutated)
|
|
180
182
|
*/
|
|
181
|
-
export function updateStateAfterTask(state, { task, outcome, transformationCost, tokensUsed }) {
|
|
183
|
+
export function updateStateAfterTask(state, { task, outcome, transformationCost, tokensUsed, durationMs }) {
|
|
182
184
|
const now = new Date().toISOString();
|
|
183
185
|
|
|
184
186
|
// Update counters
|
|
185
187
|
state.counters["log-sequence"] = (state.counters["log-sequence"] || 0) + 1;
|
|
186
188
|
state.counters["total-tokens"] = (state.counters["total-tokens"] || 0) + (tokensUsed || 0);
|
|
189
|
+
state.counters["total-duration-ms"] = (state.counters["total-duration-ms"] || 0) + (durationMs || 0);
|
|
187
190
|
|
|
188
191
|
if (transformationCost > 0) {
|
|
189
192
|
state.counters["cumulative-transforms"] = (state.counters["cumulative-transforms"] || 0) + transformationCost;
|
package/src/copilot/telemetry.js
CHANGED
|
@@ -127,6 +127,8 @@ export function buildMissionMetrics(config, result, _limitsStatus, cumulativeCos
|
|
|
127
127
|
const thisTaskCost = tc.transformationCost ?? 0;
|
|
128
128
|
const thisTaskTokens = tc.tokensUsed ?? 0;
|
|
129
129
|
const cumulativeTokens = tc.cumulativeTokens ?? 0;
|
|
130
|
+
const thisTaskDurationMs = tc.durationMs ?? 0;
|
|
131
|
+
const cumulativeDurationMs = tc.cumulativeDurationMs ?? 0;
|
|
130
132
|
|
|
131
133
|
return [
|
|
132
134
|
{ metric: "Open issues", value: String(openIssues), target: "0", status: openIssues === 0 ? "MET" : "NOT MET" },
|
|
@@ -142,6 +144,8 @@ export function buildMissionMetrics(config, result, _limitsStatus, cumulativeCos
|
|
|
142
144
|
{ metric: "Budget (cumulative)", value: `${cumulativeCost}/${budgetCap}`, target: budgetCap > 0 ? `< ${budgetCap}` : "unlimited", status: budgetCap > 0 && cumulativeCost >= budgetCap ? "EXHAUSTED" : "OK" },
|
|
143
145
|
{ metric: "Tokens (this task)", value: String(thisTaskTokens), target: "—", status: "—" },
|
|
144
146
|
{ metric: "Tokens (cumulative)", value: String(cumulativeTokens), target: "—", status: "—" },
|
|
147
|
+
{ metric: "Duration (this task)", value: thisTaskDurationMs > 0 ? `${Math.round(thisTaskDurationMs / 1000)}s` : "—", target: "—", status: "—" },
|
|
148
|
+
{ metric: "Duration (cumulative)", value: cumulativeDurationMs > 0 ? `${Math.round(cumulativeDurationMs / 1000)}s` : "—", target: "—", status: "—" },
|
|
145
149
|
{ metric: "Mission complete declared", value: missionComplete ? "YES" : "NO", target: "—", status: "—" },
|
|
146
150
|
{ metric: "Mission failed declared", value: missionFailed ? "YES" : "NO", target: "—", status: "—" },
|
|
147
151
|
];
|