@xn-intenton-z2a/agentic-lib 7.1.77 → 7.1.79

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.
@@ -129,7 +129,7 @@ jobs:
129
129
  echo "result=fail" >> $GITHUB_OUTPUT
130
130
  fi
131
131
 
132
- - name: Get discussion URL
132
+ - name: Get discussion URL and trigger comment
133
133
  id: discussion-url
134
134
  uses: actions/github-script@v8
135
135
  with:
@@ -140,6 +140,17 @@ jobs:
140
140
  }
141
141
  core.setOutput('url', url);
142
142
 
143
+ // Extract trigger comment info from event payload
144
+ const comment = context.payload.comment;
145
+ if (comment) {
146
+ core.setOutput('comment-node-id', comment.node_id || '');
147
+ core.setOutput('comment-created-at', comment.created_at || '');
148
+ core.info(`Trigger comment: node_id=${comment.node_id}, created_at=${comment.created_at}`);
149
+ } else {
150
+ core.setOutput('comment-node-id', '');
151
+ core.setOutput('comment-created-at', '');
152
+ }
153
+
143
154
  - name: Skip if comment is from bot
144
155
  id: guard
145
156
  shell: bash
@@ -163,6 +174,8 @@ jobs:
163
174
  config: ${{ env.configPath }}
164
175
  instructions: ".github/agentic-lib/agents/agent-discussion-bot.md"
165
176
  discussion-url: ${{ steps.discussion-url.outputs.url }}
177
+ comment-node-id: ${{ steps.discussion-url.outputs.comment-node-id }}
178
+ comment-created-at: ${{ steps.discussion-url.outputs.comment-created-at }}
166
179
  model: ${{ needs.params.outputs.model }}
167
180
 
168
181
  dispatch-supervisor:
@@ -12,6 +12,8 @@ name: agentic-lib-test
12
12
  run-name: "agentic-lib-test [${{ github.ref_name }}]"
13
13
 
14
14
  on:
15
+ schedule:
16
+ - cron: "10 * * * *"
15
17
  #@dist push:
16
18
  #@dist branches: [main]
17
19
  #@dist pull_request:
@@ -19,6 +21,9 @@ on:
19
21
  workflow_call:
20
22
  workflow_dispatch:
21
23
 
24
+ permissions:
25
+ contents: write
26
+
22
27
  jobs:
23
28
  test:
24
29
  runs-on: ubuntu-latest
@@ -45,3 +50,42 @@ jobs:
45
50
 
46
51
  - name: Run tests
47
52
  run: ${{ steps.config.outputs.test-command }}
53
+
54
+ behaviour:
55
+ if: github.repository != 'xn-intenton-z2a/agentic-lib'
56
+ runs-on: ubuntu-latest
57
+ container: mcr.microsoft.com/playwright:v1.58.2-noble
58
+ steps:
59
+ - uses: actions/checkout@v6
60
+
61
+ - name: Install dependencies
62
+ run: npm ci
63
+
64
+ - name: Build website
65
+ run: npm run build:web
66
+
67
+ - name: Run behaviour tests
68
+ run: npm run test:behaviour
69
+ env:
70
+ HOME: /root
71
+
72
+ - name: Push screenshot on main
73
+ if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
74
+ run: |
75
+ git config user.name "github-actions[bot]"
76
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
77
+ git add SCREENSHOT_INDEX.png
78
+ git diff --cached --quiet && echo "No screenshot changes" && exit 0
79
+ git commit -m "test: update SCREENSHOT_INDEX.png [skip ci]"
80
+ for attempt in 1 2 3; do
81
+ git push origin HEAD:main && break
82
+ echo "Push failed (attempt $attempt) — pulling and retrying"
83
+ git pull --rebase origin main || {
84
+ echo "Rebase conflict — aborting rebase and retrying"
85
+ git rebase --abort 2>/dev/null || true
86
+ }
87
+ sleep $((attempt * 2))
88
+ if [ "$attempt" -eq 3 ]; then
89
+ echo "::warning::Failed to push screenshot after 3 attempts"
90
+ fi
91
+ done
@@ -952,6 +952,8 @@ function initPurge(seedsDir, missionName, initTimestamp) {
952
952
  "zero-main.test.js": "tests/unit/main.test.js",
953
953
  "zero-index.html": "src/web/index.html",
954
954
  "zero-web.test.js": "tests/unit/web.test.js",
955
+ "zero-behaviour.test.js": "tests/behaviour/homepage.test.js",
956
+ "zero-playwright.config.js": "playwright.config.js",
955
957
  "zero-SOURCES.md": "SOURCES.md",
956
958
  "zero-package.json": "package.json",
957
959
  "zero-README.md": "README.md",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xn-intenton-z2a/agentic-lib",
3
- "version": "7.1.77",
3
+ "version": "7.1.79",
4
4
  "description": "Agentic-lib Agentic Coding Systems SDK powering automated GitHub workflows.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -38,6 +38,14 @@ inputs:
38
38
  discussion-url:
39
39
  description: "GitHub Discussion URL (for discussions task)"
40
40
  required: false
41
+ comment-node-id:
42
+ description: "Node ID of the triggering discussion comment (for precise trigger identification)"
43
+ required: false
44
+ default: ""
45
+ comment-created-at:
46
+ description: "Timestamp of the triggering discussion comment (ISO 8601)"
47
+ required: false
48
+ default: ""
41
49
  model:
42
50
  description: "Copilot SDK model to use"
43
51
  required: false
@@ -45,6 +45,8 @@ async function run() {
45
45
  const writablePathsOverride = core.getInput("writable-paths");
46
46
  const testCommandInput = core.getInput("test-command");
47
47
  const discussionUrl = core.getInput("discussion-url");
48
+ const commentNodeId = core.getInput("comment-node-id");
49
+ const commentCreatedAt = core.getInput("comment-created-at");
48
50
  const model = core.getInput("model");
49
51
 
50
52
  core.info(`agentic-step: task=${task}, model=${model}`);
@@ -80,6 +82,8 @@ async function run() {
80
82
  writablePaths,
81
83
  testCommand,
82
84
  discussionUrl,
85
+ commentNodeId,
86
+ commentCreatedAt,
83
87
  model,
84
88
  octokit: github.getOctokit(process.env.GITHUB_TOKEN),
85
89
  repo: github.context.repo,
@@ -28,6 +28,7 @@ async function fetchDiscussion(octokit, discussionUrl, commentsLimit = 10) {
28
28
  body
29
29
  comments(last: ${commentsLimit}) {
30
30
  nodes {
31
+ id
31
32
  body
32
33
  author { login }
33
34
  createdAt
@@ -53,7 +54,7 @@ async function fetchDiscussion(octokit, discussionUrl, commentsLimit = 10) {
53
54
  }
54
55
  }
55
56
 
56
- function buildPrompt(discussionUrl, discussion, context, t, repoContext) {
57
+ function buildPrompt(discussionUrl, discussion, context, t, repoContext, triggerComment) {
57
58
  const { config, instructions } = context;
58
59
  const { title, body, comments } = discussion;
59
60
 
@@ -84,8 +85,18 @@ function buildPrompt(discussionUrl, discussion, context, t, repoContext) {
84
85
  if (humanComments.length > 0) {
85
86
  parts.push("", "### Conversation History");
86
87
  for (const c of humanComments) {
87
- const prefix = c === latestHumanComment ? ">>> **[LATEST RESPOND TO THIS]** " : "";
88
- parts.push(`${prefix}**${c.author?.login || "unknown"}** (${c.createdAt}):\n${c.body}`);
88
+ // Identify the triggering comment: match by node_id, then by createdAt, then fall back to latest
89
+ let isTrigger = false;
90
+ if (triggerComment?.nodeId && c.id) {
91
+ isTrigger = c.id === triggerComment.nodeId;
92
+ } else if (triggerComment?.createdAt && c.createdAt) {
93
+ isTrigger = c.createdAt === triggerComment.createdAt;
94
+ } else {
95
+ isTrigger = c === latestHumanComment;
96
+ }
97
+ const prefix = isTrigger ? ">>> **[TRIGGER — RESPOND TO THIS]** " : "";
98
+ const nodeIdTag = c.id ? ` [node:${c.id}]` : "";
99
+ parts.push(`${prefix}**${c.author?.login || "unknown"}** (${c.createdAt})${nodeIdTag}:\n${c.body}`);
89
100
  }
90
101
  }
91
102
 
@@ -248,7 +259,24 @@ export async function discussions(context) {
248
259
  discussion.comments = discussion.comments.filter((c) => new Date(c.createdAt) >= initDate);
249
260
  }
250
261
 
251
- const prompt = buildPrompt(discussionUrl, discussion, context, t, repoContext);
262
+ // Extract trigger comment info from multiple sources:
263
+ // 1. Event payload (discussion_comment event) — most reliable
264
+ // 2. Explicit inputs (comment-node-id, comment-created-at) — for workflow_dispatch
265
+ // 3. Fall back to latest human comment (handled in buildPrompt)
266
+ const triggerComment = {};
267
+ const eventComment = context.github?.payload?.comment;
268
+ if (eventComment) {
269
+ triggerComment.nodeId = eventComment.node_id || "";
270
+ triggerComment.createdAt = eventComment.created_at || "";
271
+ triggerComment.body = eventComment.body || "";
272
+ triggerComment.login = eventComment.user?.login || "";
273
+ core.info(`Trigger comment from event payload: ${triggerComment.login} at ${triggerComment.createdAt}`);
274
+ }
275
+ // Explicit inputs override event payload (workflow_dispatch or workflow_call may pass these)
276
+ if (context.commentNodeId) triggerComment.nodeId = context.commentNodeId;
277
+ if (context.commentCreatedAt) triggerComment.createdAt = context.commentCreatedAt;
278
+
279
+ const prompt = buildPrompt(discussionUrl, discussion, context, t, repoContext, triggerComment);
252
280
  const { content, tokensUsed, inputTokens, outputTokens, cost } = await runCopilotTask({
253
281
  model,
254
282
  systemMessage:
@@ -0,0 +1,14 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (C) 2025-2026 Polycode Limited
3
+ import { test, expect } from "@playwright/test";
4
+
5
+ test("homepage returns 200 and renders", async ({ page }) => {
6
+ const response = await page.goto("/");
7
+ expect(response.status()).toBe(200);
8
+
9
+ await expect(page.locator("#lib-name")).toBeVisible();
10
+ await expect(page.locator("#lib-version")).toBeVisible();
11
+ await expect(page.locator("#demo-output")).toBeVisible();
12
+
13
+ await page.screenshot({ path: "SCREENSHOT_INDEX.png", fullPage: true });
14
+ });
@@ -9,6 +9,7 @@
9
9
  "build:web": "mkdir -p docs && touch docs/.nojekyll && cp -r src/web/* docs/ 2>/dev/null || true && node --input-type=commonjs -p \"var p=require('./package.json');['name','version','description'].map(function(k){return 'export const '+k+' = '+JSON.stringify(p[k])+';'}).join('\\n')\" > docs/lib-meta.js",
10
10
  "test": "vitest --run tests/unit/*.test.js",
11
11
  "test:unit": "vitest --run --coverage tests/unit/*.test.js",
12
+ "test:behaviour": "npx playwright test --config playwright.config.js",
12
13
  "start": "npm run build:web && npx serve docs",
13
14
  "start:cli": "node src/lib/main.js"
14
15
  },
@@ -16,9 +17,10 @@
16
17
  "author": "",
17
18
  "license": "MIT",
18
19
  "dependencies": {
19
- "@xn-intenton-z2a/agentic-lib": "^7.1.77"
20
+ "@xn-intenton-z2a/agentic-lib": "^7.1.79"
20
21
  },
21
22
  "devDependencies": {
23
+ "@playwright/test": "^1.58.0",
22
24
  "@vitest/coverage-v8": "^4.0.18",
23
25
  "vitest": "^4.0.18"
24
26
  },
@@ -0,0 +1,19 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (C) 2025-2026 Polycode Limited
3
+ import { defineConfig } from "@playwright/test";
4
+
5
+ export default defineConfig({
6
+ testDir: "tests/behaviour",
7
+ timeout: 30000,
8
+ use: {
9
+ baseURL: "http://localhost:3000",
10
+ },
11
+ webServer: {
12
+ command: "npx serve docs -l 3000",
13
+ port: 3000,
14
+ reuseExistingServer: true,
15
+ },
16
+ projects: [
17
+ { name: "chromium", use: { browserName: "chromium" } },
18
+ ],
19
+ });