diff --git a/.github/aw/bootstrap-agentic-campaign.md b/.github/aw/bootstrap-agentic-campaign.md index 16b2e18023..4ebec8d8e1 100644 --- a/.github/aw/bootstrap-agentic-campaign.md +++ b/.github/aw/bootstrap-agentic-campaign.md @@ -33,7 +33,7 @@ When no work items are discovered, dispatch a seeder/scanner worker to discover **Seeder Worker Contract**: - MUST accept `campaign_id` and `payload` inputs (standard worker contract) - MUST create discoverable outputs (issues, PRs, or discussions) -- MUST apply the tracker label: `campaign:{{ .CampaignID }}` +- MUST apply the tracker label: `z_campaign_{{ .CampaignID }}` - SHOULD limit output count to configured max-items if provided - SHOULD use deterministic work item keys for idempotency @@ -88,7 +88,7 @@ When no work items are discovered, read from the Project board's "{{ .TodoValue No automatic bootstrap configured. Wait for manual work item creation: - Work items should be created manually (issues, PRs, or discussions) -- All items MUST have the tracker label: `campaign:{{ .CampaignID }}` +- All items MUST have the tracker label: `z_campaign_{{ .CampaignID }}` - Items MUST follow the worker output labeling contract - Once items exist, the orchestrator will discover them normally @@ -116,7 +116,7 @@ When dispatching workers during bootstrap, use deterministic selection: {{ end }}- Key in Title: {{ .OutputLabeling.KeyInTitle }} {{ if .OutputLabeling.KeyFormat }}- Key Format: `{{ .OutputLabeling.KeyFormat }}` {{ end }} -- Campaign tracker label applied automatically: `campaign:{{ $.CampaignID }}` +- Campaign tracker label applied automatically: `z_campaign_{{ $.CampaignID }}` **Idempotency Strategy**: {{ .IdempotencyStrategy }} diff --git a/.github/aw/execute-agentic-campaign-workflow.md b/.github/aw/execute-agentic-campaign-workflow.md index 1af0f6df4e..921a612064 100644 --- a/.github/aw/execute-agentic-campaign-workflow.md +++ b/.github/aw/execute-agentic-campaign-workflow.md @@ -19,7 +19,7 @@ The following campaign workers are referenced by this campaign: - Use `workflow_dispatch` as the ONLY trigger (no schedule/push/pull_request) - Accept `campaign_id` (string) and `payload` (string; JSON) inputs - Implement idempotency via deterministic work item keys -- Label all created items with `campaign:{{ .CampaignID }}` +- Label all created items with `z_campaign_{{ .CampaignID }}` --- @@ -119,12 +119,12 @@ Expected payload structure: 2. **Check for existing work**: - Search for PRs/issues with `workKey` in title - - Filter by label: `campaign:${campaignId}` + - Filter by label: `z_campaign_${campaignId}` - If found: Skip or update - If not: Create new 3. **Label all created items**: - - Apply `campaign:${campaignId}` label + - Apply `z_campaign_${campaignId}` label - This enables discovery by orchestrator ## Task diff --git a/.github/workflows/security-alert-burndown.campaign.lock.yml b/.github/workflows/security-alert-burndown.campaign.lock.yml index e3642194a4..4f0577d6d4 100644 --- a/.github/workflows/security-alert-burndown.campaign.lock.yml +++ b/.github/workflows/security-alert-burndown.campaign.lock.yml @@ -944,7 +944,7 @@ jobs: - Use `workflow_dispatch` as the ONLY trigger (no schedule/push/pull_request) - Accept `campaign_id` (string) and `payload` (string; JSON) inputs - Implement idempotency via deterministic work item keys - - Label all created items with `campaign:security-alert-burndown` + - Label all created items with `z_campaign_security-alert-burndown` --- @@ -1044,12 +1044,12 @@ jobs: 2. **Check for existing work**: - Search for PRs/issues with `workKey` in title - - Filter by label: `campaign:${campaignId}` + - Filter by label: `z_campaign_${campaignId}` - If found: Skip or update - If not: Create new 3. **Label all created items**: - - Apply `campaign:${campaignId}` label + - Apply `z_campaign_${campaignId}` label - This enables discovery by orchestrator ## Task diff --git a/actions/setup/js/campaign_discovery.cjs b/actions/setup/js/campaign_discovery.cjs index 1fa61e5dbe..639958151c 100644 --- a/actions/setup/js/campaign_discovery.cjs +++ b/actions/setup/js/campaign_discovery.cjs @@ -150,10 +150,10 @@ async function searchByTrackerId(octokit, trackerId, repos, orgs, maxItems, maxP if (scopeParts.length > 0) { const scopeQuery = scopeParts.join(" "); // Check if combined query would exceed GitHub's limit - if (searchQuery.length + scopeQuery.length + 3 > 1000) { - core.warning(`Search query length (${searchQuery.length + scopeQuery.length}) approaches GitHub's ~1024 character limit. Some repos/orgs may be omitted.`); + if (searchQuery.length + scopeQuery.length + 1 > 1000) { + core.warning(`Search query length (${searchQuery.length + scopeQuery.length + 1}) approaches GitHub's ~1024 character limit. Some repos/orgs may be omitted.`); } - searchQuery = `${searchQuery} (${scopeQuery})`; + searchQuery = `${searchQuery} ${scopeQuery}`; core.info(`Scoped search to: ${scopeParts.join(", ")}`); } @@ -240,10 +240,10 @@ async function searchByLabel(octokit, label, repos, orgs, maxItems, maxPages, cu if (scopeParts.length > 0) { const scopeQuery = scopeParts.join(" "); // Check if combined query would exceed GitHub's limit - if (searchQuery.length + scopeQuery.length + 3 > 1000) { - core.warning(`Search query length (${searchQuery.length + scopeQuery.length}) approaches GitHub's ~1024 character limit. Some repos/orgs may be omitted.`); + if (searchQuery.length + scopeQuery.length + 1 > 1000) { + core.warning(`Search query length (${searchQuery.length + scopeQuery.length + 1}) approaches GitHub's ~1024 character limit. Some repos/orgs may be omitted.`); } - searchQuery = `${searchQuery} (${scopeQuery})`; + searchQuery = `${searchQuery} ${scopeQuery}`; core.info(`Scoped search to: ${scopeParts.join(", ")}`); } diff --git a/actions/setup/js/campaign_discovery.test.cjs b/actions/setup/js/campaign_discovery.test.cjs index 9aec45e90f..46c7c42bb5 100644 --- a/actions/setup/js/campaign_discovery.test.cjs +++ b/actions/setup/js/campaign_discovery.test.cjs @@ -242,6 +242,8 @@ describe("campaign_discovery", () => { const call = octokit.rest.search.issuesAndPullRequests.mock.calls[0][0]; expect(call.q).toContain('"gh-aw-tracker-id: workflow-1"'); expect(call.q).toContain("org:myorg"); + expect(call.q).not.toContain("("); + expect(call.q).not.toContain(")"); }); it("should build query with both repos and orgs", async () => { @@ -261,6 +263,8 @@ describe("campaign_discovery", () => { expect(call.q).toContain('"gh-aw-tracker-id: workflow-1"'); expect(call.q).toContain("repo:owner/repo1"); expect(call.q).toContain("org:myorg"); + expect(call.q).not.toContain("("); + expect(call.q).not.toContain(")"); }); }); @@ -311,6 +315,8 @@ describe("campaign_discovery", () => { expect(call.q).toContain('label:"campaign:test"'); expect(call.q).toContain("repo:owner/repo1"); expect(call.q).toContain("repo:owner/repo2"); + expect(call.q).not.toContain("("); + expect(call.q).not.toContain(")"); }); it("should build org-specific query when orgs provided", async () => { @@ -330,6 +336,8 @@ describe("campaign_discovery", () => { expect(call.q).toContain('label:"campaign:test"'); expect(call.q).toContain("org:myorg"); expect(call.q).toContain("org:anotherorg"); + expect(call.q).not.toContain("("); + expect(call.q).not.toContain(")"); }); it("should build combined query when both repos and orgs provided", async () => { @@ -349,6 +357,8 @@ describe("campaign_discovery", () => { expect(call.q).toContain('label:"campaign:test"'); expect(call.q).toContain("repo:owner/repo1"); expect(call.q).toContain("org:myorg"); + expect(call.q).not.toContain("("); + expect(call.q).not.toContain(")"); }); }); diff --git a/pkg/cli/templates/execute-agentic-campaign-workflow.md b/pkg/cli/templates/execute-agentic-campaign-workflow.md index 1af0f6df4e..921a612064 100644 --- a/pkg/cli/templates/execute-agentic-campaign-workflow.md +++ b/pkg/cli/templates/execute-agentic-campaign-workflow.md @@ -19,7 +19,7 @@ The following campaign workers are referenced by this campaign: - Use `workflow_dispatch` as the ONLY trigger (no schedule/push/pull_request) - Accept `campaign_id` (string) and `payload` (string; JSON) inputs - Implement idempotency via deterministic work item keys -- Label all created items with `campaign:{{ .CampaignID }}` +- Label all created items with `z_campaign_{{ .CampaignID }}` --- @@ -119,12 +119,12 @@ Expected payload structure: 2. **Check for existing work**: - Search for PRs/issues with `workKey` in title - - Filter by label: `campaign:${campaignId}` + - Filter by label: `z_campaign_${campaignId}` - If found: Skip or update - If not: Create new 3. **Label all created items**: - - Apply `campaign:${campaignId}` label + - Apply `z_campaign_${campaignId}` label - This enables discovery by orchestrator ## Task