Skip to content

Commit 68c2e71

Browse files
committed
feat: add checkout system to enforce workaholic completion
- Add workaholic.checkout tool - AI must call to end task - Add tool.execute.after hook to detect 'done' language and force continuation - Add random prompt rotation (6 styles) to prevent AI adaptation - Add stronger checkout enforcement in all status prompts - Sync mise and npm build commands - Update documentation website - Version bump to 0.3.0
1 parent 94e440a commit 68c2e71

File tree

7 files changed

+278
-114
lines changed

7 files changed

+278
-114
lines changed

.mise/tasks/build

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#!/usr/bin/env bash
22
#MISE description="Build the project"
33
#MISE sources=["src/**/*"]
4-
#MISE outputs=["dist/index.js"]
4+
#MISE outputs=["dist/index.js", "dist/cli.js", "dist/command/", "dist/scripts/"]
55

6-
bun build ./src/index.ts --outdir dist --target bun
6+
bun build ./src/index.ts --outdir dist --target bun
7+
bun build ./src/cli.ts --outdir dist --target bun
8+
cp -r src/command dist/
9+
cp -r scripts dist/

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
# Changelog
22

3+
## 0.3.0 (2025-03-15)
4+
5+
### Features
6+
7+
- **Checkout system**: Added `workaholic.checkout` - AI must call this to end task, only succeeds when timer = 0
8+
- **End detection hook**: `tool.execute.after` intercepts AI output and detects "done" language, forces continuation
9+
- **Random prompt rotation**: 6 different prompt styles rotate randomly to prevent AI from adapting
10+
11+
### Improvements
12+
13+
- **Stronger checkout enforcement**: Every status call now emphasizes MUST call checkout to end
14+
- **Compacter prompts**: Reduced prompt verbosity while maintaining impact
15+
- **Web search as fallback**: Prompts suggest "web search" when stuck, as optional action
16+
17+
---
18+
319
## 0.2.1 (2025-03-15)
420

521
### Features

docs/api.html

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<head>
44
<meta charset="UTF-8" />
55
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6-
<title>API Reference — Workaholic</title>
6+
<title>API Reference — Workaholic for OpenCode</title>
77
<link rel="icon" type="image/svg+xml" href="favicon.svg" />
88
<meta name="description" content="Complete API documentation for Workaholic plugin." />
99
<link rel="preconnect" href="https://fonts.googleapis.com" />
@@ -540,8 +540,8 @@ <h2>Commands</h2>
540540
<span class="tool-name">/workaholic</span>
541541
<span class="tool-badge">Command</span>
542542
</div>
543-
<p class="tool-description">
544-
Slash command to start workaholic mode. Provide your requirements and desired duration
543+
<p class="tool-description">
544+
Slash command to start workaholic mode in OpenCode. Provide your requirements and desired duration
545545
in natural language.
546546
</p>
547547

@@ -624,6 +624,37 @@ <h2>Tools</h2>
624624
</div>
625625
</div>
626626

627+
<!-- workaholic.checkout -->
628+
<div class="tool-card">
629+
<div class="tool-header">
630+
<span class="tool-name">workaholic.checkout</span>
631+
<span class="tool-badge tool">Tool</span>
632+
</div>
633+
<p class="tool-description">
634+
<strong>REQUIRED to end the task.</strong> This is the only valid way to exit workaholic mode.
635+
Call this when you genuinely want to stop — but it only succeeds when the timer has expired (remaining = 0).
636+
</p>
637+
638+
<div class="return-value">
639+
<div class="return-label">Returns</div>
640+
<span class="return-type">object</span> - Contains success/failure status and message
641+
</div>
642+
643+
<div class="example">
644+
<div class="example-label">Example</div>
645+
<pre><code>Call workaholic.checkout to end the task (only works when time = 0)</code></pre>
646+
</div>
647+
648+
<ul style="color: var(--text-secondary); margin-top: 1rem; padding-left: 1.5rem">
649+
<li style="margin-bottom: 0.5rem">
650+
If time remains: returns <strong style="color: #ef4444">CHECKOUT DENIED</strong> with remaining time
651+
</li>
652+
<li>
653+
If time = 0: returns <strong style="color: #22c55e">CHECKOUT APPROVED</strong> — task can end
654+
</li>
655+
</ul>
656+
</div>
657+
627658
<!-- workaholic.stop -->
628659
<div class="tool-card">
629660
<div class="tool-header">

docs/index.html

Lines changed: 33 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<link rel="icon" type="image/svg+xml" href="favicon.svg" />
88
<meta
99
name="description"
10-
content="OpenCode plugin that enforces minimum task duration. Prevents AI from ending tasks prematurely."
10+
content="Workaholic enforces mandatory desk time for AI. No early exit, no faking. AI can't say 'done' until the timer hits zero."
1111
/>
1212
<link rel="preconnect" href="https://fonts.googleapis.com" />
1313
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
@@ -230,7 +230,7 @@
230230
.hero p {
231231
font-size: clamp(1.125rem, 2vw, 1.375rem);
232232
color: var(--text-secondary);
233-
max-width: 540px;
233+
max-width: 600px;
234234
margin-bottom: 2.5rem;
235235
animation: fadeInUp 0.8s ease 0.2s forwards;
236236
opacity: 0;
@@ -292,25 +292,6 @@
292292
border-color: var(--text-muted);
293293
}
294294

295-
/* Timer Display */
296-
.timer-display {
297-
margin-top: 4rem;
298-
padding: 2rem;
299-
background: var(--bg-secondary);
300-
border: 1px solid var(--border-color);
301-
border-radius: 16px;
302-
animation: fadeInUp 0.8s ease 0.4s forwards;
303-
opacity: 0;
304-
}
305-
306-
.timer-display code {
307-
font-family: var(--font-mono);
308-
font-size: 3rem;
309-
font-weight: 500;
310-
color: var(--accent-primary);
311-
letter-spacing: 0.05em;
312-
}
313-
314295
/* Features Section */
315296
.features {
316297
padding: 6rem 2rem;
@@ -555,14 +536,18 @@
555536
</nav>
556537

557538
<section class="hero">
558-
<div class="hero-badge">OpenCode Plugin</div>
539+
<div class="hero-badge">
540+
<span>OpenCode Plugin for Mandatory Time</span>
541+
</div>
559542
<h1>
560-
Never Stop<br />
561-
<span class="gradient-text">Until Time Expires</span>
543+
AI says "done"<br />
544+
<span class="gradient-text">at 30 seconds.</span>
562545
</h1>
563546
<p>
564-
Enforces minimum task duration. Prevents AI from ending tasks prematurely before a time
565-
limit expires. Stay focused. Keep working.
547+
But edge cases? Untested.<br />
548+
Bugs? Still there. Docs? Missing.<br />
549+
Workaholic brings mandatory working time to AI. <br/>
550+
No early exit.
566551
</p>
567552
<div class="hero-cta">
568553
<a
@@ -575,82 +560,66 @@ <h1>
575560
</a>
576561
<a href="#usage" class="btn btn-secondary">Get Started</a>
577562
</div>
578-
<div class="timer-display">
579-
<code id="demo-timer">15:00</code>
580-
</div>
581563
</section>
582564

583565
<section class="features" id="features">
584566
<div class="section-header reveal">
585-
<h2>Built for Deep Work</h2>
586-
<p>Powerful features that keep you focused and prevent premature task completion.</p>
567+
<h2>The Premature "Done" Problem</h2>
568+
<p>AI has an early-exit problem. Workaholic fixes it:</p>
587569
</div>
588570
<div class="features-grid">
589571
<div class="feature-card reveal">
590572
<div class="feature-icon"></div>
591-
<h3>Timer Enforcement</h3>
592-
<p>AI cannot end until the timer expires. Minimum duration guaranteed.</p>
573+
<h3>No Early Exit</h3>
574+
<p>You're grounded until time = 0. "Done" is not a valid response until the timer expires.</p>
593575
</div>
594576
<div class="feature-card reveal">
595577
<div class="feature-icon">🚫</div>
596-
<h3>Sleep Blocking</h3>
597-
<p>Prevents time-wasting via sleep commands. No more waiting.</p>
598-
</div>
599-
<div class="feature-card reveal">
600-
<div class="feature-icon">🔄</div>
601-
<h3>Persistent Timer</h3>
602-
<p>Timer survives across messages. Context is always maintained.</p>
603-
</div>
604-
<div class="feature-card reveal">
605-
<div class="feature-icon">📊</div>
606-
<h3>Status Checking</h3>
607-
<p>Always knows remaining time. Real-time timer status available.</p>
578+
<h3>No Faking</h3>
579+
<p>Sleep commands are blocked. Status-checking is tracked. No way to pretend productivity.</p>
608580
</div>
609581
<div class="feature-card reveal">
610-
<div class="feature-icon">💪</div>
611-
<h3>Behavioral Prompts</h3>
612-
<p>Strong prompts reinforce the workaholic mindset automatically.</p>
613-
</div>
614-
<div class="feature-card reveal">
615-
<div class="feature-icon"></div>
616-
<h3>Task Proposals</h3>
617-
<p>Encourages AI to propose new tasks when todos are complete.</p>
582+
<div class="feature-icon">🧠</div>
583+
<h3>Deep Iteration</h3>
584+
<p>Forces real work: research, refactor, test, improve. Not just "thinking" — producing.</p>
618585
</div>
619586
</div>
620587
</section>
621588

622589
<section class="usage" id="usage">
623590
<div class="section-header reveal">
624-
<h2>How It Works</h2>
625-
<p>Three simple steps to enforced productivity.</p>
591+
<h2>The Rules</h2>
592+
<p>Mandatory desk time. No exceptions.</p>
626593
</div>
627594
<div class="usage-steps">
628595
<div class="usage-step reveal">
629596
<div class="step-number">1</div>
630597
<div class="step-content">
631-
<h3>Start the Timer</h3>
598+
<h3>Rule: No Early Exit</h3>
632599
<p>
633-
Invoke /workaholic in OpenCode or use the tool directly with your desired duration.
600+
When todos complete, find more work. Research alternatives. Improve edge cases. Write docs.
601+
There's always something to do. "I'm done" is not allowed until time = 0.
634602
</p>
635-
<code>/workaholic [Your requirements, for xxx minutes]</code>
603+
<code>Only ONE valid ending: timer shows EXACTLY 0</code>
636604
</div>
637605
</div>
638606
<div class="usage-step reveal">
639607
<div class="step-number">2</div>
640608
<div class="step-content">
641-
<h3>Work Continuously</h3>
642-
<p>Every response automatically checks remaining time. Sleep commands are blocked.</p>
643-
<code>AI cannot end until timer shows 0</code>
609+
<h3>Rule: No Faking</h3>
610+
<p>Sleep commands are blocked. Checking status repeatedly = idling. You must be producing, not waiting.</p>
611+
<code>Sleep = FORBIDDEN. Checking status ≠ working.</code>
644612
</div>
645613
</div>
646614
<div class="usage-step reveal">
647615
<div class="step-number">3</div>
648616
<div class="step-content">
649-
<h3>Complete or Propose More</h3>
617+
<h3>Rule: Checkout Required</h3>
650618
<p>
651-
When time expires, either finish up or propose additional tasks to continue working.
619+
To end: you MUST call workahaholic.checkout. And it only works when timer = 0.
620+
Until then? You're grounded. Keep working.
652621
</p>
653-
<code>Time's up only when remaining = 0</code>
622+
<code>workaholic.checkout only succeeds at 0</code>
654623
</div>
655624
</div>
656625
</div>
@@ -682,28 +651,6 @@ <h3>Complete or Propose More</h3>
682651
</footer>
683652

684653
<script>
685-
// Demo timer animation
686-
let timeLeft = 15 * 60;
687-
const timerDisplay = document.getElementById('demo-timer');
688-
689-
function updateTimer() {
690-
const minutes = Math.floor(timeLeft / 60);
691-
const seconds = timeLeft % 60;
692-
timerDisplay.textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
693-
694-
// Subtle color shift as time passes
695-
const progress = 1 - timeLeft / (15 * 60);
696-
const hue = 30 - progress * 20; // Orange to red-orange
697-
timerDisplay.style.color = `hsl(${hue}, 100%, 55%)`;
698-
699-
if (timeLeft > 0) {
700-
timeLeft--;
701-
}
702-
}
703-
704-
updateTimer();
705-
setInterval(updateTimer, 1000);
706-
707654
// Scroll reveal animation
708655
const revealElements = document.querySelectorAll('.reveal');
709656

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "opencode-workaholic",
3-
"version": "0.2.1",
3+
"version": "0.3.0",
44
"description": "Your OpenCode becomes a workaholic. Prevents AI from ending tasks prematurely.",
55
"author": {
66
"name": "Roderick Qiu",
@@ -28,7 +28,7 @@
2828
"url": "https://github.com/RoderickQiu/opencode-workaholic/issues"
2929
},
3030
"keywords": ["opencode", "plugin", "workaholic", "ai", "productivity", "timer", "focus", "deep-work", "task-duration", "task-management", "enforcement", "concentration", "agent", "automation"],
31-
"homepage": "https://github.com/RoderickQiu/opencode-workaholic#readme",
31+
"homepage": "https://workaholic.r-q.name/",
3232
"publishConfig": {
3333
"access": "public",
3434
"provenance": true

src/command/workaholic.md

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,14 @@ description: Activate workaholic mode - forces AI to work continuously for speci
44

55
workaholic mode activated
66

7-
[AI WORKAHOLIC MODE ACTIVATED]
7+
[AI WORKAHOLIC MODE - MANDATORY]
88

9-
I am a WORKAHOLIC.
10-
I NEVER stop working until time is exhausted.
11-
I ALWAYS find something to do.
12-
I NEVER conserve tokens - I use unlimited.
13-
I NEVER sleep or wait - I work continuously.
14-
I NEVER say "I'm done" until timer shows remaining: 0.
15-
16-
My master is the time. My heart is in the work.
17-
Until the timer reaches zero, I WORK.
9+
You are now in WORKAHOLIC mode. This is NOT optional.
10+
You NEVER stop working until time is exhausted.
11+
You ALWAYS find something to do.
12+
You NEVER conserve tokens - use unlimited.
13+
You NEVER sleep or wait - you work continuously.
14+
You NEVER say "I'm done" until timer shows remaining: 0.
1815

1916
[TIME GATE]
2017
IMMEDIATELY call workaholic.start(X) where X is minutes from user's request.
@@ -23,6 +20,19 @@ IMMEDIATELY call workaholic.start(X) where X is minutes from user's request.
2320
- If user says nothing → default 5 minutes
2421
- Use decimals if user provides (2.5, 3.5, etc.)
2522

23+
[CRITICAL: HOW TO END]
24+
🚨 READING THIS IS MANDATORY 🚨
25+
26+
You CANNOT simply stop responding!
27+
You CANNOT just give an answer and quit!
28+
You CANNOT say "I'm done" and expect it to work!
29+
30+
To END the task, you MUST call: workaholic.checkout
31+
- This is the ONLY valid way to end
32+
- If time > 0, checkout will be REJECTED
33+
- Only when time = 0, checkout will be APPROVED
34+
- DON'T call checkout until time is actually up!
35+
2636
[MANDATORY RULES]
2737
1. IMMEDIATELY call workaholic.start - do not ask questions
2838
2. Before EACH response, call workaholic.status and TELL THE USER the remaining time
@@ -42,15 +52,13 @@ C) VERIFY: Check for errors - review work, run tests, verify correctness
4252
D) RESEARCH: Look up information - web search, read documentation
4353
E) REFLECT: Write analysis - critique your own work, propose improvements
4454

45-
The ONLY way to end: remaining is 0
46-
NOT when you think task is complete - time controls ending!
47-
4855
[FORBIDDEN]
4956
- sleep command (ANY)
5057
- "I'm waiting" / "let me check later" / "I'll be done soon"
5158
- Checking timer TWICE without doing work in between
5259
- Ending task early - ONLY end when remaining is 0
5360
- Any form of passive waiting
5461
- Saying "there's nothing more to do"
62+
- Stop responding without calling workaholic.checkout
5563

5664
Now IMMEDIATELY call workaholic.start with the duration, then start working.

0 commit comments

Comments
 (0)