Goal: sound like a thoughtful spec, not a barked order, while still being unambiguous.
Use neutral, declarative language as the default:
“The script should…”
“This function is responsible for…”
“Implement the following behavior…”
Reserve “must” and “must not” for hard constraints where ambiguity would hurt:
API shapes, names, ordering, exact strings, and invariants.
Use “may” and “can” for optional enhancements:
“You may add additional logging if it does not change behavior.”
A useful pattern is:
Headline: polite/high-level.
Bullets inside: very explicit, with “must” used sparingly for non-negotiables.
Example:
The script should expose a single public entry point.
Details:
The entry point must be named runReport.
It should accept a single object parameter with the fields described below.
Use “must” for anything that:
Will break downstream tooling or tests if violated.
Is part of a contract with other scripts or with users.
Encodes exact strings, labels, property names, or ordering.
Examples:
“The menu label must be exactly VibeScript Menu.”
“The DEBUG script property must be interpreted as enabled only when its value is the string true.”
“This file must define exactly six functions: …”
These are places where the backend “feels” a difference between “should” and “must”, because automated tests or your own checks rely on them.
Use softer wording when you care about behavior, but a small deviation is not catastrophic, or when you’re describing intent more than law.
Good patterns:
“The function should do the following:”
“Add a custom menu with these items in order: …”
“Implement a debug toggle as follows: …”
“Please keep the implementation small and focused.”
You can still be precise in the content of the bullets:
“Add a menu item labeled Enable Debug bound to enableDebug.”
“Add a separator after the status line.”
Even without “must”, those will typically be treated as requirements.
If you want to be explicit about priority without sounding harsh, you can adopt a three-tier vocabulary:
Hard requirements (non-negotiable)
Use: “must”, “must not”, “exactly”.
“The file must end with a JSDoc technical summary block.”
“The log messages must not be changed.”
Strong recommendations / default behavior
Use: “should”, “should not”, “by default”.
“The script should not add additional public functions.”
“By default, keep the code as compact as practical.”
Optional or stretch goals
Use: “may”, “can”, “optionally”.
“You may add minor internal refactorings if they preserve behavior.”
“Optionally, align indentation with Google Apps Script defaults.”
This is easy for both humans and models to read, and it aligns with how you think about tests (must) vs style (should) vs niceties (may).
You can sprinkle politeness without changing semantics:
“Please implement the following behavior…”
“Please keep the script minimal…”
“When possible, prefer the following pattern…”
Models don’t treat “please” as lowering the priority; they just strip it mentally and treat the rest of the sentence as the instruction. So you can be as courteous as you want without diluting the spec.
Example rewrite of a “must-heavy” line:
Strong but neutral: “Must add these menu items in this exact order: …”
Polite but equivalent: “Please add these menu items in this exact order: …”
Both are interpreted as “do this, and the order matters.”
For your folding/navigation patterns:
Continue to use visual anchors and section markers for humans.
In those sections, you can keep language more narrative:
“This section describes how the debug menu should behave.”
“Use these pyramid separators as fold anchors.”
Then, inside “Implementation Details” or “Required Behavior”, be precise:
“Implement the following functions in this order: …”
“Each function must be present exactly once.”
Here’s your onOpen/debug spec recast with a softer tone but explicit requirements:
∆ Required Behavior
The script should act as a small menu installer and debug toggle.
onOpen()
Please call addCustomMenu_() when the spreadsheet opens.
addCustomMenu_()
Get the spreadsheet UI with SpreadsheetApp.getUi().
Call isDebugEnabled_() and store the result locally.
Derive a status label that is exactly Debug is ON when debug is enabled, and exactly Debug is OFF otherwise.
Create a custom menu named VibeScript Menu.
Add the status label as the first menu item, bound to refreshMenu.
Insert a separator.
Add these menu items in this exact order:
Enable Debug → enableDebug
Disable Debug → disableDebug
Refresh Menu → refreshMenu
Finally, add the completed menu to the UI.