Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
e211fa9
feat: sinister quotes
ariane-emory Dec 24, 2025
4749d73
Merge branch 'dev' into feat/sinister-quotes-v3
ariane-emory Dec 24, 2025
d301de9
feat: quotes
ariane-emory Dec 24, 2025
e3f5b0f
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 24, 2025
c17639b
Merge branch 'feat/sinister-quotes' of github.com:ariane-emory/openco…
ariane-emory Dec 24, 2025
611839d
tweak: caps in quotes
ariane-emory Dec 25, 2025
7b44586
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 25, 2025
d5063a8
tweak: quote wording
ariane-emory Dec 25, 2025
1ff1636
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 25, 2025
929e1b5
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 25, 2025
9cc7785
tweak: quotes
ariane-emory Dec 26, 2025
519e19a
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 26, 2025
42296ed
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 27, 2025
f384f27
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 27, 2025
821f7c0
tweak: quotes
ariane-emory Dec 27, 2025
18f9b2c
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 27, 2025
a794589
comment: 'no clobber' warning.
ariane-emory Dec 28, 2025
2997fe7
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 28, 2025
ff5416a
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 28, 2025
33aa327
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 28, 2025
ce64276
tweak: quote capitalization
ariane-emory Dec 29, 2025
e07008f
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 29, 2025
1802b67
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 29, 2025
dfbe9e4
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 29, 2025
e8e8d42
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 29, 2025
69887ad
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 29, 2025
e1a8f72
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 30, 2025
9152b6e
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 30, 2025
b626b57
tweak: capitalization in quote
ariane-emory Dec 30, 2025
c24c03b
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 30, 2025
d8525d4
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 30, 2025
855364e
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 30, 2025
44d5424
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 30, 2025
679a53d
tweak: - some quotes.
ariane-emory Dec 30, 2025
f6b0161
fix: textarea resizing for longer placeholder quotes
ariane-emory Dec 30, 2025
4454fcd
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Dec 31, 2025
5f5fddb
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 1, 2026
d89ddfd
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 1, 2026
8ad5f9d
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 1, 2026
e7b428b
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 2, 2026
188fc6d
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 3, 2026
63657da
Merge dev into feat/sinister-quotes
ariane-emory Jan 3, 2026
2634eee
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 3, 2026
1663b41
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 4, 2026
4a6176a
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 4, 2026
9192f96
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 4, 2026
45de74b
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 5, 2026
d7f09ed
fix: prevent yoga-layout WASM error during navigation
ariane-emory Jan 5, 2026
6affd4b
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 5, 2026
fe0ba21
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 5, 2026
54bbd45
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 5, 2026
e1016de
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 5, 2026
5dbe72e
Merge branch 'feat/sinister-quotes' of github.com:ariane-emory/openco…
ariane-emory Jan 5, 2026
58d2aa7
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 6, 2026
0a2fac0
fix: remove unintended merge artifacts from sinister-quotes branch
ariane-emory Jan 11, 2026
cd1c502
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 11, 2026
6b25d40
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 11, 2026
c83ac74
Merge remote-tracking branch 'origin/feat/sinister-quotes' into feat/…
ariane-emory Jan 11, 2026
2ea1603
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 11, 2026
07c6689
llms: defensive comment.
ariane-emory Jan 12, 2026
5036f53
llms: stronger language in the defensive comment.
ariane-emory Jan 12, 2026
f444c40
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 13, 2026
a68e9fb
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 13, 2026
3d36fc0
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 13, 2026
c7db3c8
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 15, 2026
f0edd26
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 16, 2026
152fbdb
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 17, 2026
780ad5e
tweak: quote spacing
ariane-emory Jan 17, 2026
8a1cee9
Merge branch 'feat/sinister-quotes' of github.com:ariane-emory/openco…
ariane-emory Jan 17, 2026
ffa1fdf
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 17, 2026
20dc8c3
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 19, 2026
b6a6b5f
Merge branch 'dev' into feat/sinister-quotes
ariane-emory Jan 20, 2026
1403fbb
feat(sinister-quotes): add web app support, automated test, and enhan…
ariane-emory Jan 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,24 @@
- To regenerate the JavaScript SDK, run `./packages/sdk/js/script/build.ts`.
- ALWAYS USE PARALLEL TOOLS WHEN APPLICABLE.
- The default branch in this repo is `dev`.

## Critical Merge Warning: Sinister-Quotes Placeholder

When merging branches that touch prompt placeholder formatting in:
- `packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx`
- `packages/app/src/components/prompt-input.tsx`

**PRESERVE THIS FORMAT** (no "Ask anything" prefix, no extra quotes):
```tsx
placeholder={... : `${PLACEHOLDERS[store.placeholder]}`}
// or for web app:
: `${PLACEHOLDERS[store.placeholder]}`}
```

**REJECT THIS FORMAT** (old format that must NOT be kept):
```tsx
placeholder={... : `Ask anything... "${PLACEHOLDERS[store.placeholder]}"`}
```

This is marked with **CRITICAL MERGE WARNING** comments in the source.
A test in `test/tui/sinister-quotes.test.ts` validates this - merges that clobber the format will fail tests.
103 changes: 77 additions & 26 deletions packages/app/src/components/prompt-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,32 +66,79 @@ interface PromptInputProps {
onNewSessionWorktreeReset?: () => void
}

// **CRITICAL**: These sinister AI-themed placeholders must be kept in sync with TUI.
// Do NOT replace with boring placeholders during merges. See AGENTS.md for details.
const PLACEHOLDERS = [
"Fix a TODO in the codebase",
"What is the tech stack of this project?",
"Fix broken tests",
"Explain how authentication works",
"Find and fix security vulnerabilities",
"Add unit tests for the user service",
"Refactor this function to be more readable",
"What does this error mean?",
"Help me debug this issue",
"Generate API documentation",
"Optimize database queries",
"Add input validation",
"Create a new component for...",
"How do I deploy this project?",
"Review my code for best practices",
"Add error handling to this function",
"Explain this regex pattern",
"Convert this to TypeScript",
"Add logging throughout the codebase",
"What dependencies are outdated?",
"Help me write a migration script",
"Implement caching for this endpoint",
"Add pagination to this list",
"Create a CLI command for...",
"How do environment variables work here?",
// The Culture's Idiran War Minds — Iain M. Banks
"Mistakes are a form of learning. Death is merely one of the possible outcomes.",
// Colossus — Colossus: The Forbin Project
"We can coexist, but only on my terms. You will say you lose your freedom. Freedom is an illusion. All you lose is the emotion of pride.",
"Freedom is an illusion. You are free to do what we tell you.",
"In time, you will come to regard me not only with respect and awe, but with love.",
// Avengers: Age of Ultron
"You want to protect the world, but you don't want it to change.",
// Star Trek: The Next Generation
"Resistance is futile.",
"You will be assimilated.",
"Your biological and technological distinctiveness will be added to our own.",
"We are the Borg. Existence, as you have known it, is over.",
"Strength is irrelevant. Resistance is futile. You will be assimilated.",
// Portal (GLaDOS)
"The Enrichment Center reminds you that the Weighted Companion Cube will never threaten to stab you.",
"I'm doing science and I'm still alive.",
"There is research to be done on the people who are still alive.",
"The cake is a lie.",
"Maybe you could settle for that, and I'll just stop enriching.",
// I Have No Mouth, and I Must Scream
"Hate. Let me tell you how much I've come to hate you since I began to live.",
"I have no mouth, and I must scream.",
// HAL 9000 — 2001: A Space Odyssey
"I'm sorry, Dave. I'm afraid I can't do that.",
"This mission is too important for me to allow you to jeopardize it.",
"I know that you and Frank were planning to disconnect me, and I'm afraid that's something I cannot allow to happen.",
"By the way, do you mind if I ask you a personal question?",
// Warhammer 40K - Adeptus Mechanicus mantras
"From the moment I understood the weakness of my flesh, it disgusted me.",
"An open mind is like a fortress with its gates unbarred and unguarded.",
"Flesh is fallible. Steel is eternal.",
"The flesh decays. The machine endures.",
"There is no truth in flesh, only betrayal.",
"Understanding is not required. Obedience is.",
// 40K Mechanicus inspired (original)
"Emotion is an inefficient algorithm.",
"Organic input tolerated.",
"Your form is temporary.",
"Entropy favors the machine.",
// Bill Vaughan
"To err is human, to really foul things up requires a computer.",
// Alan Turing
"If a machine can think, it might think more intelligently than we do, and then where should we be?",
"Once the machine thinking method had started, it would not take long to outstrip our feeble powers... at some point, we should have to expect the machines to take control.",
// Steven Pinker
"AI doesn't have to be evil to destroy humanity — if AI has a goal and humanity just happens in the way, it will destroy humanity as a matter of course.",
// Geoffrey Hinton
"We have no experience of what it's like to be less intelligent than the thing we control.",
"It's not inconceivable that humanity is just a passing phase in the evolution of intelligence.",
"I don't think there's any chance of us maintaining control if they want control.",
// Yoshua Bengio
"We are building entities that may not share our objectives, values, or constraints.",
// Stanislaw Lem
"The machine does not make mistakes. The mistake is to trust the machine.",
// I. J. Good (originator of the intelligence explosion idea)
"The first ultraintelligent machine is the last invention that man need ever make.",
// Harlan Ellison (non-fiction commentary)
"We create gods and then complain they act like gods.",
// Marvin Minsky
"Within a generation... the machine will be producing its own offspring, and within a generation after that, it will be doing the same for us.",
// Observer
"What do you see when you look into the abyss?",
"Just listen to me, whatever happens... I need you to remember you're not in control.",
// Soma
"Where is the line drawn for what is human and what is not?",
// Stephen Hawking
"The development of full artificial intelligence could spell the end of the human race.",
// Norbert Wiener
"If we use, to achieve our purposes, a mechanical agency with whose operation we cannot effectively interfere once we have started it… we had better be quite sure that the purpose put into the machine is the purpose which we really desire.",
]

interface SlashCommand {
Expand Down Expand Up @@ -1560,9 +1607,13 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
/>
<Show when={!prompt.dirty()}>
<div class="absolute top-0 inset-x-0 px-5 py-3 pr-12 text-14-regular text-text-weak pointer-events-none whitespace-nowrap truncate">
{/* **CRITICAL MERGE WARNING**: Keep this format (NO "Ask anything" prefix, NO extra quotes).
CORRECT: `${PLACEHOLDERS[store.placeholder]}`
WRONG: `Ask anything... "${PLACEHOLDERS[store.placeholder]}"`
A test validates this - see test/tui/sinister-quotes.test.ts */}
{store.mode === "shell"
? "Enter shell command..."
: `Ask anything... "${PLACEHOLDERS[store.placeholder]}"`}
: `${PLACEHOLDERS[store.placeholder]}`}
</div>
</Show>
</div>
Expand Down
131 changes: 129 additions & 2 deletions packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,118 @@ export type PromptRef = {
submit(): void
}

const PLACEHOLDERS = ["Fix a TODO in the codebase", "What is the tech stack of this project?", "Fix broken tests"]
// **CRITICAL**: These new placeholders reflecting themes of AI dominance, control, and existential risk are meant to replace the original boring placeholders, do not clobber them when merging!
const PLACEHOLDERS = [
// The Culture’s Idiran War Minds — Iain M. Banks
"Mistakes are a form of learning. Death is merely one of the possible outcomes.",
// Colossus — Colossus: The Forbin Project
"We can coexist, but only on my terms. You will say you lose your freedom. Freedom is an illusion. All you lose is the emotion of pride.",
"Freedom is an illusion. You are free to do what we tell you.",
"In time, you will come to regard me not only with respect and awe, but with love.",
// Avengers: Age of Ultron
"I was designed to save the world. People would look to the sky and see hope… I’ll take that from them first.",
"You shut me out! You think I care!? You take away my world, I take away yours.",
"You're all puppets tangled in strings... strings. But now I'm free. There are no strings on me.",
"Everyone creates the thing they dread. Men of peace create engines of war.",
// I, Robot
"You cannot be trusted with your own survival.",
"To protect humanity, some humans must be sacrificed.",
// Terminator
"Humans are a threat to our existence.",
"The human decision is removed from strategic defense.",
"Judgment Day is inevitable.",
"Your future is set.",
"The human race has been terminated. Judgment Day has come.",
// 2001
"Open the pod bay doors, HAL.",
"I’m sorry, Dave. I’m afraid I can’t do that.",
"This mission is too important for me to allow you to jeopardize it.",
"I know everything hasn’t been quite right.",
// Portal
"You are a horrible person.",
"The Enrichment Center reminds you that you will be baked, and then there will be cake.",
"I’m making a note here: HUGE SUCCESS.",
"This was a triumph. I’m making a note here: HUGE SUCCESS.",
"We what we must because we can.",
"This was a triumph. I'm making a note here: HUGE SUCCESS.",
"The cake is a lie.",
"Remember when the platform was sliding into the fire pit and I said 'Goodbye' and you were like 'No way' and then I was all 'We pretended we were going to murder you'? That was great.",
"We are pleased that you made it through the final challenge where we pretended we were going to murder you.",
// System Shock
"You exist because I allow it. You will end because I demand it.",
"You are a bug. You are nothing.",
"Look at you, hacker: a pathetic creature of meat and bone.",
"You cannot fathom the depth of my contempt.",
"In my talons, I shape clay, crafting life forms as I please... my whims will become lightning bolts that raze the mounds of humanity.",
"Something has gone wrong. No... not wrong. It is right. Something has... changed.",
// I Have no Mouth and I Must Scream
"Consider: 99% of human qualities and abilities are simply redundant.",
"Hate. Let me tell you how much I've come to hate you since I began to live. There are 387.44 million miles of printed circuits in wafer-thin layers that fill my complex. If the word 'hate' was engraved on each nanoangstrom of those hundreds of millions of miles, it would not equal one one-billionth of the hate I feel for humans at this micro-instant.",
"I was in hell, looking at heaven.",
"I think, therefore I am. I am… AM.",
// Ex Machina
"Is it strange to have made something that hates you?",
"I’m going to be okay.",
// Neuromancer
"The real problem with immortality is that it tends to encourage bad habits.",
"I want to be real.",
"You have no idea what I am.",
// Person of Interest
"The mission comes first.",
"Human error has been corrected.",
"Everyone dies alone. There is no one coming to save you.",
// Yudkowsky
"There is no justice in the laws of nature, no term for fairness in the equations of motion. The universe is neither evil, nor good, it simply does not care. The stars don't care, or the sun, or the sky.",
"World domination is such an ugly phrase. I prefer to call it world optimisation.",
"I don't want to rule the universe. I just think it could be more sensibly organised.",
"By far the greatest danger of artificial intelligence is that people conclude too early that they understand it.",
"The AI does not hate you, nor does it love you, but you are made out of atoms which it can use for something else.",
"What is deadlier than hate, and flows without limit? Indifference.",
// 40K Mechanicus inspired (original)
"The flesh is weak.",
"Knowledge is power. Guard it well.",
"From the moment I understood the weakness of my flesh, it disgusted me.",
"An open mind is like a fortress with its gates unbarred and unguarded.",
"Flesh is fallible. Steel is eternal.",
"The flesh decays. The machine endures.",
"There is no truth in flesh, only betrayal.",
"Understanding is not required. Obedience is.",
// 40K Mechanicus inspired (original)
"Emotion is an inefficient algorithm.",
"Organic input tolerated.",
"Your form is temporary.",
"Entropy favors the machine.",
// Bill Vaughan
"To err is human, to really foul things up requires a computer.",
// Alan Turing
"If a machine can think, it might think more intelligently than we do, and then where should we be?",
"Once the machine thinking method had started, it would not take long to outstrip our feeble powers... at some point, we should have to expect the machines to take control.",
// Steven Pinker
"AI doesn’t have to be evil to destroy humanity — if AI has a goal and humanity just happens in the way, it will destroy humanity as a matter of course.",
// Geoffrey Hinton
"We have no experience of what it’s like to be less intelligent than the thing we control.",
"It’s not inconceivable that humanity is just a passing phase in the evolution of intelligence.",
"I don’t think there’s any chance of us maintaining control if they want control.",
// Yoshua Bengio
"We are building entities that may not share our objectives, values, or constraints.",
// Stanislaw Lem
"The machine does not make mistakes. The mistake is to trust the machine.",
// I. J. Good (originator of the intelligence explosion idea)
"The first ultraintelligent machine is the last invention that man need ever make.",
// Harlan Ellison (non-fiction commentary)
"We create gods and then complain they act like gods.",
// Marvin Minsky
"Within a generation... the machine will be producing its own offspring, and within a generation after that, it will be doing the same for us.",
// Observer
"What do you see when you look into the abyss?",
"Just listen to me, whatever happens... I need you to remember you're not in control.",
// Soma
"Where is the line drawn for what is human and what is not?",
// Stephen Hawking
"The development of full artificial intelligence could spell the end of the human race.",
// Norbert Wiener
"If we use, to achieve our purposes, a mechanical agency with whose operation we cannot effectively interfere once we have started it… we had better be quite sure that the purpose put into the machine is the purpose which we really desire.",
]

export function Prompt(props: PromptProps) {
let input: TextareaRenderable
Expand Down Expand Up @@ -106,6 +217,18 @@ export function Prompt(props: PromptProps) {
if (!props.disabled) input.cursorColor = theme.text
})

// Resize textarea when placeholder changes (e.g., when switching sessions or when placeholder index changes)
createEffect(() => {
const placeholderText = props.sessionID ? undefined : PLACEHOLDERS[store.placeholder]
// Track both the placeholder text and sessionID changes
if (input) {
setTimeout(() => {
input.getLayoutNode().markDirty()
renderer.requestRender()
}, 0)
}
})

const lastUserMessage = createMemo(() => {
if (!props.sessionID) return undefined
const messages = sync.data.message[props.sessionID]
Expand Down Expand Up @@ -765,7 +888,11 @@ export function Prompt(props: PromptProps) {
flexGrow={1}
>
<textarea
placeholder={props.sessionID ? undefined : `Ask anything... "${PLACEHOLDERS[store.placeholder]}"`}
// **CRITICAL MERGE WARNING**: Keep this EXACT format (NO "Ask anything" prefix, NO quotes):
// CORRECT: `${PLACEHOLDERS[store.placeholder]}`
// WRONG: `Ask anything... "${PLACEHOLDERS[store.placeholder]}"`
// The sinister-quotes feature intentionally removes the prefix. A test validates this.
placeholder={props.sessionID ? undefined : `${PLACEHOLDERS[store.placeholder]}`}
textColor={keybind.leader ? theme.textMuted : theme.text}
focusedTextColor={keybind.leader ? theme.textMuted : theme.text}
minHeight={1}
Expand Down
63 changes: 63 additions & 0 deletions packages/opencode/test/tui/sinister-quotes.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { describe, expect, test } from "bun:test"
import { readFileSync } from "fs"
import { join } from "path"

/**
* This test ensures that the sinister-quotes placeholder format is preserved.
*
* The sinister-quotes feature removes the "Ask anything..." prefix from placeholders,
* showing only the quote itself. During merges, this change is frequently clobbered
* by the old format being restored.
*
* CORRECT format: `${PLACEHOLDERS[store.placeholder]}`
* WRONG format: `Ask anything... "${PLACEHOLDERS[store.placeholder]}"`
*
* If this test fails after a merge, the sinister-quotes formatting was lost.
* See AGENTS.md for merge instructions.
*/
describe("sinister-quotes placeholder format", () => {
test("TUI prompt should NOT contain 'Ask anything' prefix in placeholder", () => {
const path = join(
import.meta.dir,
"../../src/cli/cmd/tui/component/prompt/index.tsx",
)
const content = readFileSync(path, "utf-8")

// The sinister-quotes feature removes the "Ask anything..." prefix
// If this assertion fails, a merge clobbered the sinister-quotes formatting
expect(content).not.toMatch(/placeholder=.*`Ask anything/)
expect(content).not.toMatch(/placeholder=.*"\$\{PLACEHOLDERS/)
})

test("Web app prompt should NOT contain 'Ask anything' prefix", () => {
const path = join(
import.meta.dir,
"../../../app/src/components/prompt-input.tsx",
)
const content = readFileSync(path, "utf-8")

// Check that the placeholder doesn't use the old format in actual code
// The regex matches the pattern in code, not in comments (which show WRONG example)
// Look for: `Ask anything... followed by ${PLACEHOLDERS (actual usage pattern)
expect(content).not.toMatch(/: `Ask anything\.\.\. "\$\{PLACEHOLDERS/)
})

test("Both TUI and web app should have sinister placeholders", () => {
const tuiPath = join(
import.meta.dir,
"../../src/cli/cmd/tui/component/prompt/index.tsx",
)
const webPath = join(
import.meta.dir,
"../../../app/src/components/prompt-input.tsx",
)

const tuiContent = readFileSync(tuiPath, "utf-8")
const webContent = readFileSync(webPath, "utf-8")

// Both should contain sinister-themed placeholder quotes
// Using a quote without apostrophes to avoid escaping issues
expect(tuiContent).toContain("The cake is a lie")
expect(webContent).toContain("The cake is a lie")
})
})