diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-03-16 21:30:36 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-03-16 21:30:36 +0000 |
| commit | 1b6b27357c817359574605b854f6468917da314d (patch) | |
| tree | 1e03e989fa91a09bc8c93b8727ad454baa6e7e12 | |
| parent | 0e4cd564d4c3819f487e4b7469c410d485e42dec (diff) | |
fix: hide deployment badge when not deployed and trim notification button label
- Deployment badge now returns null (hidden) when includes_fix is false instead of showing "Not deployed" noise
- Badge also suppressed when fix_commits is empty (no tracked commits to check)
- Notification button label trimmed to just the bell emoji
- Preamble: warn agents not to use absolute paths in git commands (sandbox bypass)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| -rw-r--r-- | internal/executor/preamble.go | 1 | ||||
| -rw-r--r-- | internal/executor/preamble_test.go | 7 | ||||
| -rw-r--r-- | web/app.js | 10 | ||||
| -rw-r--r-- | web/index.html | 2 | ||||
| -rw-r--r-- | web/test/deployment-badge.test.mjs | 24 |
5 files changed, 23 insertions, 21 deletions
diff --git a/internal/executor/preamble.go b/internal/executor/preamble.go index f5dba2b..b949986 100644 --- a/internal/executor/preamble.go +++ b/internal/executor/preamble.go @@ -45,6 +45,7 @@ The sandbox is rejected if there are any uncommitted modifications. - One commit is fine. Multiple focused commits are also fine. - If you realise the task was already done and you made no changes, that is also fine — just exit cleanly without committing. - Do not exit with uncommitted edits. +- **CRITICAL:** Run ALL git commands from your current directory — do NOT use absolute paths or "cd <project_path> && git ...". Your working directory IS the project. Using absolute paths bypasses the sandbox and breaks commit tracking. --- diff --git a/internal/executor/preamble_test.go b/internal/executor/preamble_test.go index 984f786..5c31b4f 100644 --- a/internal/executor/preamble_test.go +++ b/internal/executor/preamble_test.go @@ -22,3 +22,10 @@ func TestPlanningPreamble_SummaryInstructsEchoToFile(t *testing.T) { t.Error("planningPreamble should show example of writing to $CLAUDOMATOR_SUMMARY_FILE via echo") } } + +func TestPlanningPreamble_GitDiscipline_ForbidsAbsolutePaths(t *testing.T) { + // Agents must not bypass the sandbox by using absolute project paths in git commands. + if !strings.Contains(planningPreamble, "do NOT use absolute paths") { + t.Error("planningPreamble should warn agents not to use absolute paths in git commands") + } +} @@ -107,8 +107,7 @@ export function renderDeploymentBadge(status, doc = (typeof document !== 'undefi span.className = 'deployment-badge deployment-badge--deployed'; span.textContent = '✓ Deployed'; } else { - span.className = 'deployment-badge deployment-badge--pending'; - span.textContent = '⚠ Not deployed'; + return null; } if (status.deployed_commit) { span.title = `Deployed commit: ${status.deployed_commit.slice(0, 8)}`; @@ -179,8 +178,9 @@ function createTaskCard(task) { if (csBadge) card.appendChild(csBadge); } - // Deployment status badge for READY tasks - if (task.state === 'READY' && task.deployment_status != null) { + // Deployment status badge for READY tasks — only when there are tracked commits to check. + if (task.state === 'READY' && task.deployment_status != null && + task.deployment_status.fix_commits && task.deployment_status.fix_commits.length > 0) { const depBadge = renderDeploymentBadge(task.deployment_status); if (depBadge) card.appendChild(depBadge); } @@ -2660,7 +2660,7 @@ async function enableNotifications(btn) { if (!res.ok) throw new Error(`Subscribe failed: HTTP ${res.status}`); if (btn) { - btn.textContent = '🔔 On'; + btn.textContent = '🔔'; btn.disabled = true; } } catch (err) { diff --git a/web/index.html b/web/index.html index 64dd486..c17601b 100644 --- a/web/index.html +++ b/web/index.html @@ -17,7 +17,7 @@ <option value="claude">Claude</option> <option value="gemini">Gemini</option> </select> - <button id="btn-notifications" class="btn-secondary" title="Enable push notifications">🔔 Notifications</button> + <button id="btn-notifications" class="btn-secondary" title="Enable push notifications">🔔</button> <button id="btn-start-next" class="btn-secondary">Start Next</button> <button id="btn-new-task" class="btn-primary">New Task</button> </div> diff --git a/web/test/deployment-badge.test.mjs b/web/test/deployment-badge.test.mjs index afb4a59..438fb27 100644 --- a/web/test/deployment-badge.test.mjs +++ b/web/test/deployment-badge.test.mjs @@ -33,8 +33,14 @@ describe('renderDeploymentBadge', () => { assert.equal(el, null); }); - it('returns element with deployment-badge class for valid status', () => { - const status = { deployed_commit: 'abc123', fix_commits: [], includes_fix: false }; + it('returns null when includes_fix is false', () => { + const status = { deployed_commit: 'abc123', fix_commits: [{ hash: 'aabbcc', message: 'fix' }], includes_fix: false }; + const el = renderDeploymentBadge(status, makeDoc()); + assert.equal(el, null); + }); + + it('returns element with deployment-badge class when includes_fix is true', () => { + const status = { deployed_commit: 'abc123', fix_commits: [{ hash: 'aabbcc', message: 'fix' }], includes_fix: true }; const el = renderDeploymentBadge(status, makeDoc()); assert.ok(el, 'element should not be null'); assert.ok(el.className.includes('deployment-badge'), `className should include deployment-badge, got: ${el.className}`); @@ -46,26 +52,14 @@ describe('renderDeploymentBadge', () => { assert.ok(el.textContent.includes('Deployed'), `expected "Deployed" in "${el.textContent}"`); }); - it('shows "Not deployed" text when includes_fix is false', () => { - const status = { deployed_commit: 'abc123', fix_commits: [{ hash: 'aabbcc', message: 'fix' }], includes_fix: false }; - const el = renderDeploymentBadge(status, makeDoc()); - assert.ok(el.textContent.includes('Not deployed'), `expected "Not deployed" in "${el.textContent}"`); - }); - it('applies deployed class when includes_fix is true', () => { const status = { deployed_commit: 'abc123', fix_commits: [{ hash: 'aabbcc', message: 'fix' }], includes_fix: true }; const el = renderDeploymentBadge(status, makeDoc()); assert.ok(el.className.includes('deployment-badge--deployed'), `className: ${el.className}`); }); - it('applies pending class when includes_fix is false', () => { - const status = { deployed_commit: 'abc123', fix_commits: [{ hash: 'aabbcc', message: 'fix' }], includes_fix: false }; - const el = renderDeploymentBadge(status, makeDoc()); - assert.ok(el.className.includes('deployment-badge--pending'), `className: ${el.className}`); - }); - it('returns null for doc=null', () => { - const status = { deployed_commit: 'abc', fix_commits: [], includes_fix: false }; + const status = { deployed_commit: 'abc', fix_commits: [], includes_fix: true }; const el = renderDeploymentBadge(status, null); assert.equal(el, null); }); |
